enum VoteTally { MAJORITY = 'MAJORITY', NO_MAJORITY = 'NO_MAJORITY', NO_VOTE = 'NO_VOTE', NONE = '' }
enum MultipleCommitteeVoteTally { VOTE_MAJORITY = 'MAJORITY', VOTE_NON_MAJORITY = 'NO_MAJORITY', NO_VOTE = 'NO_VOTE', NONE = '' }
const MultipleCommitteeOutcomeVoteColumnBridge: Record<MultipleCommitteeVoteTally, VoteTally> = { [MultipleCommitteeVoteTally.VOTE_MAJORITY]: VoteTally.MAJORITY, [MultipleCommitteeVoteTally.VOTE_NON_MAJORITY]: VoteTally.NO_MAJORITY, [MultipleCommitteeVoteTally.NO_VOTE]: VoteTally.NO_VOTE, [MultipleCommitteeVoteTally.NONE]: VoteTally.NONE };
const eventValue = 'VOTE_MAJORITY'; const selectedVoteValue = MultipleCommitteeOutcomeVoteColumnBridge[MultipleCommitteeVoteTally[eventValue as keyof typeof MultipleCommitteeVoteTally]];
console.log(selectedVoteValue);
// src/services/api/httpClient.ts
import axios, { AxiosInstance } from 'axios'
export const createHttpClient = (): AxiosInstance => {
const client = axios.create({
baseURL: import.meta.env.VITE_API_URL,
})
client.interceptors.request.use((config) => {
const token = localStorage.getItem('token')
if (token) {
config.headers['Authorization'] = `Bearer ${token}`
}
return config
})
return client
}
// src/services/api/repository.ts
import { AxiosInstance } from 'axios'
export class Repository {
constructor(protected httpClient: AxiosInstance) {}
protected async get<T>(url: string, params?: object): Promise<T> {
const response = await this.httpClient.get<T>(url, { params })
return response.data
}
protected async post<T>(url: string, data?: object): Promise<T> {
const response = await this.httpClient.post<T>(url, data)
return response.data
}
// Add other methods (put, delete, etc.) as needed
}
// src/services/api/productRepository.ts
import { Repository } from './repository'
import type { Product } from '@/types'
export class ProductRepository extends Repository {
async getProducts(): Promise<Product[]> {
return this.get<Product[]>('/products')
}
async getProduct(id: number): Promise<Product> {
return this.get<Product>(`/products/${id}`)
}
}
// src/services/api/orderRepository.ts
import { Repository } from './repository'
import type { Order } from '@/types'
export class OrderRepository extends Repository {
async getOrders(): Promise<Order[]> {
return this.get<Order[]>('/orders')
}
async createOrder(orderData: Partial<Order>): Promise<Order> {
return this.post<Order>('/orders', orderData)
}
}
// src/services/api/index.ts
import { createHttpClient } from './httpClient'
import { ProductRepository } from './productRepository'
import { OrderRepository } from './orderRepository'
const httpClient = createHttpClient()
export const productRepository = new ProductRepository(httpClient)
export const orderRepository = new OrderRepository(httpClient)
// src/composables/useApi.ts
import { ref, Ref } from 'vue'
export function useApi<T, E = any>(
apiCall: () => Promise<T>
): {
data: Ref<T | null>
error: Ref<E | null>
loading: Ref<boolean>
execute: () => Promise<void>
} {
const data = ref<T | null>(null) as Ref<T | null>
const error = ref<E | null>(null)
const loading = ref<boolean>(false)
const execute = async () => {
loading.value = true
error.value = null
try {
data.value = await apiCall()
} catch (e) {
error.value = e as E
} finally {
loading.value = false
}
}
return { data, error, loading, execute }
}
// src/stores/product.ts
import { defineStore } from 'pinia'
import { computed } from 'vue'
import { productRepository } from '@/services/api'
import { useApi } from '@/composables/useApi'
import type { Product } from '@/types'
export const useProductStore = defineStore('product', () => {
const {
data: products,
error,
loading,
execute: fetchProducts
} = useApi<Product[]>(() => productRepository.getProducts())
const getProductById = computed(() => (id: number) =>
products.value?.find(p => p.id === id)
)
return { products, error, loading, getProductById, fetchProducts }
})
// src/stores/order.ts
import { defineStore } from 'pinia'
import { orderRepository } from '@/services/api'
import { useApi } from '@/composables/useApi'
import { useCartStore } from './cart'
import type { Order } from '@/types'
export const useOrderStore = defineStore('order', () => {
const {
data: orders,
error,
loading,
execute: fetchOrders
} = useApi<Order[]>(() => orderRepository.getOrders())
const cartStore = useCartStore()
const createOrder = async () => {
const { data: newOrder, error } = await useApi(() =>
orderRepository.createOrder({
items: cartStore.items,
total: cartStore.total
})
)()
if (newOrder.value) {
orders.value?.push(newOrder.value)
cartStore.clearCart()
}
return { newOrder, error }
}
return { orders, error, loading, fetchOrders, createOrder }
})
// src/composables/useFilterStrategy.ts
import { ref, computed } from 'vue'
interface Filterable {
[key: string]: any
}
interface FilterStrategy<T extends Filterable> {
apply(items: T[]): T[]
}
export function useFilterStrategy<T extends Filterable>() {
const filterStrategy = ref<FilterStrategy<T> | null>(null)
const setFilterStrategy = (strategy: FilterStrategy<T>) => {
filterStrategy.value = strategy
}
const applyFilter = (items: T[]) => {
return filterStrategy.value ? filterStrategy.value.apply(items) : items
}
return { filterStrategy, setFilterStrategy, applyFilter }
}
// src/composables/usePagination.ts
import { ref, computed } from 'vue'
export function usePagination<T>(items: T[], itemsPerPage: number) {
const currentPage = ref(1)
const paginatedItems = computed(() => {
const startIndex = (currentPage.value - 1) * itemsPerPage
return items.slice(startIndex, startIndex + itemsPerPage)
})
const totalPages = computed(() => Math.ceil(items.length / itemsPerPage))
const nextPage = () => {
if (currentPage.value < totalPages.value) {
currentPage.value++
}
}
const prevPage = () => {
if (currentPage.value > 1) {
currentPage.value--
}
}
return { currentPage, paginatedItems, totalPages, nextPage, prevPage }
}
// src/composables/useNotification.ts
import { ref } from 'vue'
interface Notification {
id: number
message: string
type: 'success' | 'error' | 'info'
}
export function useNotification() {
const notifications = ref<Notification[]>([])
const addNotification = (message: string, type: Notification['type'] = 'info') => {
const id = Date.now()
notifications.value.push({ id, message, type })
setTimeout(() => removeNotification(id), 5000)
}
const removeNotification = (id: number) => {
notifications.value = notifications.value.filter(n => n.id !== id)
}
return { notifications, addNotification, removeNotification }
}
// src/components/product/ProductList.vue
<script setup lang="ts">
import { computed, onMounted } from 'vue'
import { useProductStore } from '@/stores/product'
import { useFilterStrategy } from '@/composables/useFilterStrategy'
import { usePagination } from '@/composables/usePagination'
import ProductCard from './ProductCard.vue'
import type { Product } from '@/types'
const productStore = useProductStore()
const { filterStrategy, setFilterStrategy, applyFilter } = useFilterStrategy<Product>()
const filteredProducts = computed(() => applyFilter(productStore.products || []))
const { paginatedItems, currentPage, totalPages, nextPage, prevPage } = usePagination(filteredProducts, 10)
onMounted(() => {
productStore.fetchProducts()
})
// Filter strategies
class PriceFilterStrategy implements FilterStrategy<Product> {
constructor(private maxPrice: number) {}
apply(products: Product[]): Product[] {
return products.filter(p => p.price <= this.maxPrice)
}
}
class CategoryFilterStrategy implements FilterStrategy<Product> {
constructor(private category: string) {}
apply(products: Product[]): Product[] {
return products.filter(p => p.category === this.category)
}
}
const applyPriceFilter = (maxPrice: number) => {
setFilterStrategy(new PriceFilterStrategy(maxPrice))
}
const applyCategoryFilter = (category: string) => {
setFilterStrategy(new CategoryFilterStrategy(category))
}
</script>
<template>
<div class="product-list">
<h1>Our Products</h1>
<div class="filters">
<button @click="applyPriceFilter(50)">Price under $50</button>
<button @click="applyCategoryFilter('Electronics')">Electronics</button>
<!-- Add more filter buttons as needed -->
</div>
<div v-if="productStore.loading">Loading...</div>
<div v-else-if="productStore.error">{{ productStore.error }}</div>
<div v-else class="products-grid">
<ProductCard
v-for="product in paginatedItems"
:key="product.id"
:product="product"
/>
</div>
<div class="pagination">
<button @click="prevPage" :disabled="currentPage === 1">Previous</button>
<span>Page {{ currentPage }} of {{ totalPages }}</span>
<button @click="nextPage" :disabled="currentPage === totalPages">Next</button>
</div>
</div>
</template>
// src/components/cart/ShoppingCart.vue
<script setup lang="ts">
import { useCartStore } from '@/stores/cart'
import { useOrderStore } from '@/stores/order'
import { useNotification } from '@/composables/useNotification'
const cartStore = useCartStore()
const orderStore = useOrderStore()
const { addNotification } = useNotification()
const checkout = async () => {
const { newOrder, error } = await orderStore.createOrder()
if (newOrder) {
addNotification('Order placed successfully!', 'success')
} else if (error) {
addNotification('Failed to place order. Please try again.', 'error')
}
}
</script>
<template>
<div class="shopping-cart">
<h2>Your Cart</h2>
<ul>
<li v-for="item in cartStore.items" :key="item.id">
{{ item.name }} - ${{ item.price }} x {{ item.quantity }}
<button @click="cartStore.removeItem(item.id)">Remove</button>
</li>
</ul>
<p>Total: ${{ cartStore.total }}</p>
<button @click="checkout" :disabled="cartStore.items.length === 0">
Checkout
</button>
</div>
</template>
// src/plugins/errorHandler.ts
import { App } from 'vue'
import { useNotification } from '@/composables/useNotification'
export const errorHandler = {
install(app: App) {
const { addNotification } = useNotification()
app.config.errorHandler = (err, vm, info) => {
console.error(err, vm, info)
addNotification('An error occurred. Please try again later.', 'error')
}
}
}
// src/main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
import { errorHandler } from './plugins/errorHandler'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.use(errorHandler)
app.mount('#app')