use zustand for contacts

This commit is contained in:
vchikalkin 2025-01-14 19:10:05 +03:00
parent 550c5474a3
commit 000cb77acd
6 changed files with 88 additions and 27 deletions

View File

@ -3,16 +3,29 @@ import { authOptions } from '@/config/auth';
import { getCustomerClients, getCustomerMasters } from '@repo/graphql/api';
import { getServerSession } from 'next-auth/next';
export async function getContacts() {
export async function getClients() {
const session = await getServerSession(authOptions);
if (session) {
const { user } = session;
const getCustomerClientsResponse = await getCustomerClients({ telegramId: user?.telegramId });
return {
clients: getCustomerClientsResponse?.clients,
};
}
return null;
}
export async function getMasters() {
const session = await getServerSession(authOptions);
if (session) {
const { user } = session;
const getCustomerMastersResponse = await getCustomerMasters({ telegramId: user?.telegramId });
const getCustomerClientsResponse = await getCustomerClients({ telegramId: user?.telegramId });
return {
clients: getCustomerClientsResponse?.clients,
masters: getCustomerMastersResponse?.masters,
};
}

View File

@ -1,43 +1,37 @@
/* eslint-disable promise/prefer-await-to-then */
'use client';
import { getContacts } from '@/actions/contacts';
import { getClients, getMasters } from '@/actions/contacts';
import { ContactsFilterContext } from '@/context/contacts-filter';
import type * as GQL from '@repo/graphql/types';
import { useBoundStore } from '@/store';
import { sift } from 'radash';
import { use, useEffect, useMemo, useState } from 'react';
type Clients = NonNullable<GQL.GetCustomerClientsQuery['customers'][0]>['clients'];
type Masters = NonNullable<GQL.GetCustomerMastersQuery['customers'][0]>['masters'];
import { use, useEffect, useMemo } from 'react';
export function useCustomerContacts() {
const [contacts, setContacts] = useState<{ clients: Clients; masters: Masters }>({
clients: [],
masters: [],
});
const { filter } = use(ContactsFilterContext);
const { clients = [], masters = [], setClients, setMasters } = useBoundStore();
useEffect(() => {
getContacts().then((response) => {
setContacts({
clients: response?.clients || [],
masters: response?.masters || [],
if ((filter === 'masters' || filter === 'all') && !masters)
getMasters().then((response) => {
if (response?.masters) setMasters(response.masters);
});
});
}, []);
if ((filter === 'clients' || filter === 'all') && !clients)
getClients().then((response) => {
if (response?.clients) setClients(response.clients);
});
}, [filter]);
const filteredContacts = useMemo(() => {
const { clients, masters } = contacts;
switch (filter) {
case 'clients':
return sift(clients);
return clients ? sift(clients) : [];
case 'masters':
return sift(masters);
return masters ? sift(masters) : [];
default:
return [...sift(clients), ...sift(masters)];
return [...(clients ? sift(clients) : []), ...(masters ? sift(masters) : [])];
}
}, [contacts, filter]);
}, [clients, masters, filter]);
return { contacts: filteredContacts };
}

View File

@ -26,7 +26,8 @@
"react": "catalog:",
"react-dom": "catalog:",
"use-debounce": "^10.0.4",
"zod": "catalog:"
"zod": "catalog:",
"zustand": "^5.0.3"
},
"devDependencies": {
"@playwright/test": "^1.49.1",

View File

@ -0,0 +1,21 @@
import type * as GQL from '@repo/graphql/types';
import { type StateCreator } from 'zustand';
export type ContactsStore = {
clients: Clients | null;
masters: Masters | null;
setClients: (clients: Clients) => void;
setMasters: (masters: Masters) => void;
};
type Clients = NonNullable<GQL.GetCustomerClientsQuery['customers'][0]>['clients'];
type Masters = NonNullable<GQL.GetCustomerMastersQuery['customers'][0]>['masters'];
export const createContactsSlice: StateCreator<ContactsStore> = (set) => {
return {
clients: null,
masters: null,
setClients: (clients) => set({ clients }),
setMasters: (masters) => set({ masters }),
};
};

6
apps/web/store/index.ts Normal file
View File

@ -0,0 +1,6 @@
import { type ContactsStore, createContactsSlice } from './contacts';
import { create } from 'zustand';
type Store = ContactsStore;
export const useBoundStore = create<Store>()((...a) => ({ ...createContactsSlice(...a) }));

26
pnpm-lock.yaml generated
View File

@ -177,6 +177,9 @@ importers:
zod:
specifier: 'catalog:'
version: 3.24.1
zustand:
specifier: ^5.0.3
version: 5.0.3(@types/react@19.0.1)(react@19.0.0)
devDependencies:
'@playwright/test':
specifier: ^1.49.1
@ -6305,6 +6308,24 @@ packages:
zod@3.24.1:
resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==}
zustand@5.0.3:
resolution: {integrity: sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==}
engines: {node: '>=12.20.0'}
peerDependencies:
'@types/react': '>=18.0.0'
immer: '>=9.0.6'
react: '>=18.0.0'
use-sync-external-store: '>=1.2.0'
peerDependenciesMeta:
'@types/react':
optional: true
immer:
optional: true
react:
optional: true
use-sync-external-store:
optional: true
snapshots:
'@alloc/quick-lru@5.2.0': {}
@ -13059,3 +13080,8 @@ snapshots:
zen-observable@0.8.15: {}
zod@3.24.1: {}
zustand@5.0.3(@types/react@19.0.1)(react@19.0.0):
optionalDependencies:
'@types/react': 19.0.1
react: 19.0.0