feat: implement compare functionality, checkout flow, and add 30 blog posts

This commit is contained in:
MichalC
2026-06-27 18:09:22 +02:00
parent 6bdfe18e18
commit 0c59086a6b
63 changed files with 9766 additions and 1874 deletions
+19 -71
View File
@@ -2,16 +2,12 @@ import { create } from 'zustand';
import { persist } from 'zustand/middleware';
export interface CartItem {
id: string; // Unikalne ID, połączenie slug + wybrane opcje
id: string;
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;
price: number;
quantity: number;
}
@@ -20,9 +16,9 @@ interface CartState {
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 };
getTotal: () => number;
getCount: () => number;
}
export const useCartStore = create<CartState>()(
@@ -32,89 +28,41 @@ export const useCartStore = create<CartState>()(
addItem: (newItem) => {
set((state) => {
const id = `${newItem.slug}-${newItem.label || 'base'}-${newItem.withInstall}`;
const existingItem = state.items.find((item) => item.id === id);
if (existingItem) {
const id = newItem.slug;
const existing = state.items.find((i) => i.id === id);
if (existing) {
return {
items: state.items.map((item) =>
item.id === id ? { ...item, quantity: item.quantity + 1 } : item
items: state.items.map((i) =>
i.id === id ? { ...i, quantity: i.quantity + 1 } : i
),
};
}
return { items: [...state.items, { ...newItem, id, quantity: 1 }] };
});
},
removeItem: (id) => {
set((state) => ({
items: state.items.filter((item) => item.id !== id),
}));
},
removeItem: (id) =>
set((state) => ({ items: state.items.filter((i) => i.id !== id) })),
updateQuantity: (id, quantity) => {
if (quantity < 1) return;
set((state) => ({
items: state.items.map((item) =>
item.id === id ? { ...item, quantity } : item
),
items: state.items.map((i) => (i.id === id ? { ...i, quantity } : i)),
}));
},
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: () => {
getTotal: () => {
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;
return items.reduce((sum, i) => sum + i.price * i.quantity, 0);
},
subtotal += itemTotalNet;
vat += itemVat;
});
return {
subtotal,
vat,
total: subtotal + vat
};
getCount: () => {
const { items } = get();
return items.reduce((sum, i) => sum + i.quantity, 0);
},
}),
{
name: 'air-project-cart',
}
{ name: 'thermcool-cart' }
)
);
+35
View File
@@ -0,0 +1,35 @@
import { create } from 'zustand';
interface CompareItem {
slug: string;
name: string;
brand: string;
price: number | null;
image: string;
specs: Record<string, string>;
}
interface CompareState {
items: CompareItem[];
addItem: (item: CompareItem) => void;
removeItem: (slug: string) => void;
clearAll: () => void;
isAdded: (slug: string) => boolean;
}
export const useCompareStore = create<CompareState>()((set, get) => ({
items: [],
addItem: (item) => {
const { items } = get();
if (items.length >= 3 || items.find((i) => i.slug === item.slug)) return;
set({ items: [...items, item] });
},
removeItem: (slug) =>
set((state) => ({ items: state.items.filter((i) => i.slug !== slug) })),
clearAll: () => set({ items: [] }),
isAdded: (slug) => get().items.some((i) => i.slug === slug),
}));