This repository has been archived on 2026-08-11. You can view files and clone it, but cannot push or open issues or pull requests.
Gishen-Mob/lib/stores/notificationStore.ts
kirukib 5391780b9b Ship Rx Care tab, notifications inbox, and guest pickup codes.
Replace the profile tab with prescription management (inline reminders and family invite), add a shared tab top bar, separate notifications from orders, and support any-branch guest checkout with GSH codes.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-07 15:35:51 +03:00

142 lines
3.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import AsyncStorage from "@react-native-async-storage/async-storage";
import { create } from "zustand";
import { createJSONStorage, persist } from "zustand/middleware";
export type NotificationKind =
| "order"
| "rx"
| "dose"
| "loyalty"
| "promo"
| "system";
export type AppNotification = {
id: string;
kind: NotificationKind;
title: string;
body: string;
createdAt: string;
read: boolean;
/** Deep-link target inside the app */
href?: string | null;
};
type NotificationState = {
items: AppNotification[];
unreadCount: () => number;
markRead: (id: string) => void;
markAllRead: () => void;
remove: (id: string) => void;
push: (
n: Omit<AppNotification, "id" | "createdAt" | "read"> & {
id?: string;
createdAt?: string;
read?: boolean;
}
) => AppNotification;
};
function hoursAgo(n: number) {
const d = new Date();
d.setHours(d.getHours() - n);
return d.toISOString();
}
export const seedNotifications: AppNotification[] = [
{
id: "ntf_dose_1",
kind: "dose",
title: "Time for Metformin 500mg",
body: "Confirm your 20:00 dose or snooze for 10 minutes.",
createdAt: hoursAgo(1),
read: false,
href: "/(root)/(screens)/prescription/calendar/rx_demo_metformin",
},
{
id: "ntf_rx_1",
kind: "rx",
title: "Prescription under review",
body: "A pharmacist is checking your Azithromycin Rx. We’ll notify you when it’s ready.",
createdAt: hoursAgo(5),
read: false,
href: "/(root)/(screens)/prescription/rx_demo_azitro",
},
{
id: "ntf_order_1",
kind: "order",
title: "Rider is on the way",
body: "Your Bole delivery is out for delivery. Track live progress anytime.",
createdAt: hoursAgo(8),
read: false,
href: "/(root)/(screens)/tracking/ord_demo_active",
},
{
id: "ntf_loyalty_1",
kind: "loyalty",
title: "120 points ready to redeem",
body: "Redeem 100 pts for voucher GISHEN10 at checkout.",
createdAt: hoursAgo(26),
read: true,
href: "/(root)/(screens)/loyalty",
},
{
id: "ntf_promo_1",
kind: "promo",
title: "Weekend wellness picks",
body: "Save on vitamins and personal care this week at any Gishen branch.",
createdAt: hoursAgo(40),
read: true,
href: "/(root)/(screens)/shop",
},
{
id: "ntf_system_1",
kind: "system",
title: "Guest pickup tip",
body: "Shopping as a guest? Use your quick pickup code at any branch counter.",
createdAt: hoursAgo(72),
read: true,
href: null,
},
];
export const useNotificationStore = create<NotificationState>()(
persist(
(set, get) => ({
items: seedNotifications,
unreadCount: () => get().items.filter((n) => !n.read).length,
markRead: (id) =>
set({
items: get().items.map((n) => (n.id === id ? { ...n, read: true } : n)),
}),
markAllRead: () =>
set({ items: get().items.map((n) => ({ ...n, read: true })) }),
remove: (id) => set({ items: get().items.filter((n) => n.id !== id) }),
push: (payload) => {
const item: AppNotification = {
id: payload.id ?? `ntf_${Date.now()}`,
createdAt: payload.createdAt ?? new Date().toISOString(),
read: payload.read ?? false,
kind: payload.kind,
title: payload.title,
body: payload.body,
href: payload.href ?? null,
};
set({ items: [item, ...get().items] });
return item;
},
}),
{
name: "gishen-notifications",
storage: createJSONStorage(() => AsyncStorage),
version: 1,
migrate: (persisted: unknown) => {
const state = (persisted ?? {}) as Partial<NotificationState>;
if (!state.items?.length) {
return { ...state, items: seedNotifications };
}
return state;
},
}
)
);