Ship Expo Router screens, seeded stores, and polished UX so auth, shop, checkout, prescriptions, loyalty, family, and account processes work end-to-end offline. Co-authored-by: Cursor <cursoragent@cursor.com>
92 lines
2.3 KiB
TypeScript
92 lines
2.3 KiB
TypeScript
import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
import { create } from "zustand";
|
|
import { createJSONStorage, persist } from "zustand/middleware";
|
|
import { seedSubscriptions } from "@/lib/data/seed";
|
|
import type { Fulfillment, PaymentMethod } from "@/lib/stores/locationStore";
|
|
|
|
export type SubscriptionStatus = "active" | "paused" | "cancelled";
|
|
|
|
export type RefillSubscription = {
|
|
id: string;
|
|
productId: string;
|
|
productName: string;
|
|
quantity: number;
|
|
frequencyDays: number;
|
|
fulfillment: Fulfillment;
|
|
paymentMethod: PaymentMethod;
|
|
memberId?: string | null;
|
|
status: SubscriptionStatus;
|
|
nextFulfillmentAt: string;
|
|
};
|
|
|
|
type SubState = {
|
|
items: RefillSubscription[];
|
|
add: (
|
|
s: Omit<RefillSubscription, "id" | "status" | "nextFulfillmentAt">
|
|
) => void;
|
|
pause: (id: string) => void;
|
|
resume: (id: string) => void;
|
|
cancel: (id: string) => void;
|
|
};
|
|
|
|
function nextDate(days: number) {
|
|
const d = new Date();
|
|
d.setDate(d.getDate() + days);
|
|
return d.toISOString();
|
|
}
|
|
|
|
export const useSubscriptionStore = create<SubState>()(
|
|
persist(
|
|
(set, get) => ({
|
|
items: seedSubscriptions,
|
|
add: (s) =>
|
|
set({
|
|
items: [
|
|
{
|
|
...s,
|
|
id: `sub_${Date.now()}`,
|
|
status: "active",
|
|
nextFulfillmentAt: nextDate(s.frequencyDays),
|
|
},
|
|
...get().items,
|
|
],
|
|
}),
|
|
pause: (id) =>
|
|
set({
|
|
items: get().items.map((i) =>
|
|
i.id === id ? { ...i, status: "paused" } : i
|
|
),
|
|
}),
|
|
resume: (id) =>
|
|
set({
|
|
items: get().items.map((i) =>
|
|
i.id === id
|
|
? {
|
|
...i,
|
|
status: "active",
|
|
nextFulfillmentAt: nextDate(i.frequencyDays),
|
|
}
|
|
: i
|
|
),
|
|
}),
|
|
cancel: (id) =>
|
|
set({
|
|
items: get().items.map((i) =>
|
|
i.id === id ? { ...i, status: "cancelled" } : i
|
|
),
|
|
}),
|
|
}),
|
|
{
|
|
name: "gishen-subscriptions",
|
|
storage: createJSONStorage(() => AsyncStorage),
|
|
version: 2,
|
|
migrate: (persisted: unknown) => {
|
|
const state = (persisted ?? {}) as Partial<SubState>;
|
|
return !state.items?.length
|
|
? { ...state, items: seedSubscriptions }
|
|
: state;
|
|
},
|
|
}
|
|
)
|
|
);
|