Bettersplit/src/lib/store/expense-store.ts

102 lines
2.6 KiB
TypeScript

"use client";
import { create } from "zustand";
import { calculateSplits, type Payment } from "@/lib/utils/expense";
import type { Group, User } from "@/server/db/schema";
export enum SplitTypeEnum {
Fixed = "fixed",
Percentage = "percentage",
Equal = "equal",
}
export type SplitType = keyof typeof SplitTypeEnum;
export const splitTypeKeys = Object.keys(SplitTypeEnum);
interface ExpenseStore {
amount: number;
participants: User[];
groupBadges: Group[];
friendTarget?: string;
splitType: SplitType;
payments: Payment[];
splits: Record<string, string>;
setAmount: (amount: number) => void;
addGroupBadges: (groupIds: Group[]) => void;
removeGroupBadge: (groupIds: string[]) => void;
addParticipants: (user: User[]) => void;
removeParticipant: (userId: string) => void;
setFriendTarget: (id?: string) => void;
setSplitType: (type: SplitType) => void;
setPayments: (payments: Array<Payment>) => void;
recalculateSplits: () => void;
resetExpenseStore: () => void;
}
const defaultValues: Pick<
ExpenseStore,
| "amount"
| "participants"
| "friendTarget"
| "splitType"
| "payments"
| "splits"
| "groupBadges"
> = {
amount: 0,
participants: [],
groupBadges: [],
friendTarget: undefined,
splitType: "Equal",
payments: [],
splits: {},
};
export const useExpenseStore = create<ExpenseStore>((set, get) => ({
...defaultValues,
setAmount: (amount) => set({ amount }),
addParticipants: (newUsers) => {
const { participants } = get();
const uniqueUsers = newUsers.filter(
(user) => !participants.find((u) => u.id === user.id)
);
set({ participants: [...participants, ...uniqueUsers] });
},
removeParticipant: (userId) => {
const filtered = get().participants.filter((user) => user.id !== userId);
set({ participants: filtered });
},
setFriendTarget: (id) => set({ friendTarget: id }),
setSplitType: (type) => set({ splitType: type }),
setPayments: (payments) => set({ payments }),
recalculateSplits: () => {
const { amount, participants, splitType } = get();
const splits = calculateSplits({
amount,
users: participants.map((u) => u.id!),
splitType,
});
set({ splits });
},
addGroupBadges: (newGroups) => {
const { groupBadges } = get();
const uniqueGroups = newGroups.filter(
(group) => !groupBadges.find((g) => g.id === group.id)
);
set({ groupBadges: [...groupBadges, ...uniqueGroups] });
},
removeGroupBadge: (groupIds) =>
set({
groupBadges: get().groupBadges.filter(({ id }) => !groupIds.includes(id)),
}),
resetExpenseStore: () => set(defaultValues),
}));