chore: transfer repo

This commit is contained in:
Danijel
2026-01-19 20:21:14 +01:00
commit 7d2fb0c737
213 changed files with 18085 additions and 0 deletions

View File

@@ -0,0 +1,234 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { RootState } from '../store';
// Define the type for a box item
export interface BoxItem {
id: string;
name: string;
price: number;
image: string;
quantity: number;
variantId?: string;
color?: string;
compositeKey?: string;
}
// Define the type for the box state
interface BoxState {
items: BoxItem[];
total: number;
editingBoxGroupId?: string;
isInitialized: boolean;
}
// Helper function to load state from localStorage
const loadState = (): BoxState | undefined => {
try {
// Check if we're in a browser environment
if (typeof window === 'undefined') {
return undefined;
}
const serializedState = localStorage.getItem('boxState');
if (serializedState === null) {
return undefined;
}
return JSON.parse(serializedState);
} catch (err) {
console.error('Error loading box state from localStorage', err);
return undefined;
}
};
// Helper function to save state to localStorage
const saveState = (state: BoxState) => {
if (typeof window === 'undefined') {
return;
}
try {
const serializedState = JSON.stringify(state);
localStorage.setItem('boxState', serializedState);
} catch (err) {
console.error('Error saving box state to localStorage', err);
}
};
// Initial state without loading from localStorage to avoid hydration mismatch
const initialState: BoxState = {
items: [],
total: 0,
editingBoxGroupId: undefined,
isInitialized: false
};
// Helper to generate a unique key for an item based on ID and color
const generateItemKey = (item: { id: string; color?: string }): string => {
return `${item.id}-${item.color || 'no-color'}`;
};
export const boxSlice = createSlice({
name: 'box',
initialState,
reducers: {
// Initialize state from localStorage (to be called in useEffect)
initializeState: (state) => {
// Skip if already initialized
if (state.isInitialized) return;
try {
const savedState = loadState();
if (savedState) {
state.items = savedState.items || [];
state.total = savedState.total || 0;
state.editingBoxGroupId = savedState.editingBoxGroupId;
}
} catch (error) {
console.error('Error initializing state from localStorage', error);
}
state.isInitialized = true;
},
// Add an item to the box
addToBox: (state, action: PayloadAction<BoxItem>) => {
const newItem = { ...action.payload };
// Check if the variantId should be used as a color
if (newItem.variantId && !newItem.color) {
newItem.color = newItem.variantId;
}
// Generate composite key
const compositeKey = generateItemKey(newItem);
newItem.compositeKey = compositeKey;
const existingItemIndex = state.items.findIndex(
item => generateItemKey(item) === compositeKey
);
if (existingItemIndex >= 0 && state.items[existingItemIndex]) {
// If item with the same key exists, increment quantity
const quantity = newItem.quantity || 1;
state.items[existingItemIndex].quantity += quantity;
} else {
// Otherwise add the new item (or item with a different color)
state.items.push({
...newItem,
quantity: newItem.quantity || 1,
compositeKey
});
}
// Recalculate total
state.total = state.items.reduce(
(sum, item) => sum + item.price * item.quantity, 0
);
// Save to localStorage
saveState(state);
},
// Update item quantity
updateQuantity: (state, action: PayloadAction<{ id: string; color?: string; quantity: number }>) => {
const { id, color, quantity } = action.payload;
const itemKey = generateItemKey({ id, color });
const item = state.items.find(item => generateItemKey(item) === itemKey);
if (item) {
item.quantity = quantity;
// Recalculate total
state.total = state.items.reduce(
(sum, item) => sum + item.price * item.quantity, 0
);
}
// Save to localStorage
saveState(state);
},
// Remove an item from the box
removeFromBox: (state, action: PayloadAction<{ id: string; color?: string }>) => {
const { id, color } = action.payload;
const itemKeyToRemove = generateItemKey({ id, color });
state.items = state.items.filter(item => generateItemKey(item) !== itemKeyToRemove);
// Recalculate total
state.total = state.items.reduce(
(sum, item) => sum + item.price * item.quantity, 0
);
// Save to localStorage
saveState(state);
},
// Clear the entire box
clearBox: (state) => {
state.items = [];
state.total = 0;
state.editingBoxGroupId = undefined;
// Save to localStorage
saveState(state);
},
// Load a box for editing
loadBoxForEditing: (state) => {
try {
if (typeof window === 'undefined') {
return;
}
const boxStateString = localStorage.getItem('lastBoxState');
if (!boxStateString) {
return;
}
const boxState = JSON.parse(boxStateString);
// Spremi originalni boxGroupId ako postoji
if (boxState && boxState.originalBoxGroupId) {
state.editingBoxGroupId = boxState.originalBoxGroupId;
}
if (boxState && boxState.boxItems && boxState.productItems) {
// Reset current state
state.items = [];
// Add box items
boxState.boxItems.forEach((item: BoxItem) => {
state.items.push(item);
});
// Add product items
boxState.productItems.forEach((item: BoxItem) => {
state.items.push(item);
});
// Recalculate total
state.total = state.items.reduce(
(sum, item) => sum + item.price * item.quantity, 0
);
// Save to localStorage
saveState(state);
}
} catch (error) {
console.error('Error loading box for editing', error);
}
},
},
});
// Export actions
export const { initializeState, addToBox, updateQuantity, removeFromBox, clearBox, loadBoxForEditing } = boxSlice.actions;
// Selectors
export const selectBoxItems = (state: RootState) => state.box.items;
export const selectBoxTotal = (state: RootState) => state.box.total;
export const selectBoxItemsCount = (state: RootState) =>
state.box.items.reduce((total, item) => total + item.quantity, 0);
export const selectEditingBoxGroupId = (state: RootState) => state.box.editingBoxGroupId;
export default boxSlice.reducer;