sozsoft-platform/ui/src/utils/basketUtils.ts
Sedat ÖZTÜRK d982a3ce42 Genel hata kontrolü ve düzenlemeler
npx tsc --noEmit --pretty false
dotnet build --no-restore --nologo --verbosity quiet
2026-07-10 11:18:20 +03:00

176 lines
4.9 KiB
TypeScript

import { BillingCycle, BasketItem, ProductDto } from '@/proxy/order/models'
export interface BasketData {
items: BasketItem[]
subtotal: number
vatTotal: number
total: number
globalBillingCycle: BillingCycle
globalPeriod: number
}
export const initialBasketData: BasketData = {
items: [],
subtotal: 0,
vatTotal: 0,
total: 0,
globalBillingCycle: 'yearly',
globalPeriod: 1,
}
export const calculateItemPrice = (
product: ProductDto,
quantity: number,
billingCycle: BillingCycle,
period: number = 1,
): number => {
const price = billingCycle === 'monthly' ? product.monthlyPrice! : product.yearlyPrice!
const vatRate = product.vatRate ?? 0.2
return roundMoney(price * quantity * period * (1 + vatRate))
}
const roundMoney = (value: number): number => Math.round(value * 100) / 100
const calculateItemVatAmount = (totalPrice: number, vatRate: number = 0.2): number =>
vatRate > 0 ? roundMoney(totalPrice - totalPrice / (1 + vatRate)) : 0
const withItemVat = (
product: ProductDto,
quantity: number,
billingCycle: BillingCycle,
period: number,
): BasketItem => {
const vatRate = product.vatRate ?? 0.2
const totalPrice = calculateItemPrice(product, quantity, billingCycle, period)
return {
product,
quantity,
billingCycle,
vatRate,
vatAmount: calculateItemVatAmount(totalPrice, vatRate),
totalPrice,
}
}
const calculateBasketTotals = (items: BasketItem[]) => {
const total = roundMoney(items.reduce((sum, item) => sum + item.totalPrice, 0))
const vatTotal = roundMoney(items.reduce((sum, item) => sum + (item.vatAmount ?? 0), 0))
return {
subtotal: roundMoney(total - vatTotal),
vatTotal,
total,
}
}
export const addItemToBasket = (
basketData: BasketData,
product: ProductDto,
quantity: number,
billingCycle: BillingCycle,
): BasketData => {
const isAlreadyInBasket = isItemInBasketData(basketData.items, product.id, billingCycle)
if (!product.isQuantityBased && isAlreadyInBasket) {
return basketData
}
const existingItemIndex = basketData.items.findIndex(
(item) => item.product.id === product.id && item.billingCycle === billingCycle,
)
let newItems
if (existingItemIndex > -1) {
newItems = [...basketData.items]
newItems[existingItemIndex].quantity += quantity
newItems[existingItemIndex] = withItemVat(
product,
newItems[existingItemIndex].quantity,
billingCycle,
basketData.globalPeriod,
)
} else {
const actualQuantity = !product.isQuantityBased ? 1 : quantity
newItems = [
...basketData.items,
withItemVat(product, actualQuantity, billingCycle, basketData.globalPeriod),
]
}
const updatedState = { ...basketData, items: newItems, ...calculateBasketTotals(newItems) }
return updatedState
}
export const removeItemFromBasket = (basketData: BasketData, id: string): BasketData => {
const newItems = basketData.items.filter((item) => item.product.id !== id)
const updatedState = { ...basketData, items: newItems, ...calculateBasketTotals(newItems) }
return updatedState
}
export const updateBasketItemQuantity = (
basketData: BasketData,
id: string,
quantity: number,
): BasketData => {
const newItems = basketData.items
.map((item) => {
if (item.product.id === id) {
if (quantity <= 0) return null
if (!item.product.isQuantityBased) return item
return withItemVat(item.product, quantity, item.billingCycle, basketData.globalPeriod)
}
return item
})
.filter(Boolean) as BasketItem[]
const updatedState = { ...basketData, items: newItems, ...calculateBasketTotals(newItems) }
return updatedState
}
export const clearBasket = (): BasketData => {
return initialBasketData
}
export const setBasketGlobalBillingCycle = (basketData: BasketData, cycle: BillingCycle): BasketData => {
const newItems = basketData.items.map((item) =>
withItemVat(item.product, item.quantity, cycle, basketData.globalPeriod),
)
const updatedState = {
...basketData,
globalBillingCycle: cycle,
items: newItems,
...calculateBasketTotals(newItems),
}
return updatedState
}
export const setBasketGlobalPeriod = (basketData: BasketData, period: number): BasketData => {
const newItems = basketData.items.map((item) =>
withItemVat(item.product, item.quantity, item.billingCycle, period),
)
const updatedState = {
...basketData,
globalPeriod: period,
items: newItems,
...calculateBasketTotals(newItems),
}
return updatedState
}
export const isItemInBasket = (
basketData: BasketData,
productId: string,
billingCycle: BillingCycle,
): boolean => {
return basketData.items.some(
(item) => item.product.id === productId && item.billingCycle === billingCycle,
)
}
export const isItemInBasketData = (
items: BasketItem[],
productId: string,
billingCycle: BillingCycle,
): boolean => {
return items.some((item) => item.product.id === productId && item.billingCycle === billingCycle)
}