feat: complete website implementation

This commit is contained in:
Radosław Smoliński
2026-06-21 21:53:15 +02:00
parent b147112bdc
commit dfd3888517
110 changed files with 18276 additions and 217 deletions
+120
View File
@@ -0,0 +1,120 @@
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
export interface CartItem {
id: string; // Unikalne ID, połączenie slug + wybrane opcje
slug: string;
name: string;
brand: string;
image: string;
power?: number;
label?: string; // Np. "2.5 kW" z wariantu
price: number; // Podstawowa cena za 1 szt. bez montażu
priceWithInstall: number; // Cena za 1 szt. z montażem
withInstall: boolean;
quantity: number;
}
interface CartState {
items: CartItem[];
addItem: (item: Omit<CartItem, 'id' | 'quantity'>) => void;
removeItem: (id: string) => void;
updateQuantity: (id: string, quantity: number) => void;
toggleInstall: (id: string) => void;
clearCart: () => void;
getTotals: () => { subtotal: number; vat: number; total: number };
}
export const useCartStore = create<CartState>()(
persist(
(set, get) => ({
items: [],
addItem: (newItem) => {
set((state) => {
const id = `${newItem.slug}-${newItem.label || 'base'}-${newItem.withInstall}`;
const existingItem = state.items.find((item) => item.id === id);
if (existingItem) {
return {
items: state.items.map((item) =>
item.id === id ? { ...item, quantity: item.quantity + 1 } : item
),
};
}
return { items: [...state.items, { ...newItem, id, quantity: 1 }] };
});
},
removeItem: (id) => {
set((state) => ({
items: state.items.filter((item) => item.id !== id),
}));
},
updateQuantity: (id, quantity) => {
if (quantity < 1) return;
set((state) => ({
items: state.items.map((item) =>
item.id === id ? { ...item, quantity } : item
),
}));
},
toggleInstall: (id) => {
set((state) => {
const itemToUpdate = state.items.find(item => item.id === id);
if (!itemToUpdate) return state;
const newWithInstall = !itemToUpdate.withInstall;
const newId = `${itemToUpdate.slug}-${itemToUpdate.label || 'base'}-${newWithInstall}`;
const targetExists = state.items.find(item => item.id === newId);
if (targetExists) {
return {
items: state.items
.map(item => item.id === newId ? { ...item, quantity: item.quantity + itemToUpdate.quantity } : item)
.filter(item => item.id !== id)
}
}
return {
items: state.items.map((item) =>
item.id === id ? { ...item, withInstall: newWithInstall, id: newId } : item
),
};
});
},
clearCart: () => set({ items: [] }),
getTotals: () => {
const { items } = get();
let subtotal = 0;
let vat = 0;
items.forEach((item) => {
const itemPrice = item.withInstall ? item.priceWithInstall : item.price;
const itemTotalGross = itemPrice * item.quantity;
const vatRate = item.withInstall ? 0.08 : 0.23;
const itemTotalNet = itemTotalGross / (1 + vatRate);
const itemVat = itemTotalGross - itemTotalNet;
subtotal += itemTotalNet;
vat += itemVat;
});
return {
subtotal,
vat,
total: subtotal + vat
};
},
}),
{
name: 'air-project-cart',
}
)
);