Vlad Chikalkin 3589ab974a
Refactor/components folder structure (#24)
* refactor components/navigation

* refactor components/orders

* refactor components/profile

* refactor components/schedule

* remove components/common/spinner
2025-05-23 17:35:13 +03:00

130 lines
4.2 KiB
TypeScript

'use client';
import { CardSectionHeader } from '@/components/ui';
import { ContactsContextProvider } from '@/context/contacts';
import { useCustomerContacts } from '@/hooks/api/contacts';
// eslint-disable-next-line import/extensions
import AvatarPlaceholder from '@/public/avatar/avatar_placeholder.png';
import { useOrderStore } from '@/stores/order';
import { withContext } from '@/utils/context';
import { type CustomerFieldsFragment } from '@repo/graphql/types';
import { Card } from '@repo/ui/components/ui/card';
import { Label } from '@repo/ui/components/ui/label';
import { LoadingSpinner } from '@repo/ui/components/ui/spinner';
import { cn } from '@repo/ui/lib/utils';
import Image from 'next/image';
import { useEffect } from 'react';
type ContactsGridProps = {
readonly contacts: CustomerFieldsFragment[];
readonly onSelect: (contactId: null | string) => void;
readonly selected?: null | string;
readonly title: string;
};
export function ContactsGridBase({ contacts, onSelect, selected, title }: ContactsGridProps) {
return (
<Card className="p-4">
<div className="flex flex-col gap-4">
<CardSectionHeader title={title} />
<div className="grid max-h-screen grid-cols-4 gap-2 overflow-y-auto">
{contacts.map((contact) => {
if (!contact) return null;
const isCurrentUser = contact?.name === 'Я';
return (
<Label
className="flex cursor-pointer flex-col items-center"
key={contact?.documentId}
>
<input
checked={selected === contact?.documentId}
className="hidden"
name="user"
onChange={() => onSelect(contact?.documentId)}
type="radio"
value={contact?.documentId}
/>
<div
className={cn(
'w-20 h-20 rounded-full border-2 transition-all duration-75',
selected === contact?.documentId ? 'border-primary' : 'border-transparent',
)}
>
<div
className={cn(
'size-full rounded-full p-1',
isCurrentUser
? 'bg-gradient-to-r from-purple-500 to-pink-500'
: 'bg-transparent',
)}
>
<Image
alt={contact?.name}
className="size-full rounded-full object-cover"
height={80}
src={contact?.photoUrl || AvatarPlaceholder}
width={80}
/>
</div>
</div>
<span
className={cn(
'mt-2 max-w-20 break-words text-center text-sm font-medium',
isCurrentUser && 'font-bold',
)}
>
{contact?.name}
</span>
</Label>
);
})}
</div>
</div>
</Card>
);
}
export const MastersGrid = withContext(ContactsContextProvider)(function () {
const { contacts, isLoading, setFilter } = useCustomerContacts();
const masterId = useOrderStore((store) => store.masterId);
const setMasterId = useOrderStore((store) => store.setMasterId);
useEffect(() => {
setFilter('masters');
}, [setFilter]);
if (isLoading) return <LoadingSpinner />;
return (
<ContactsGridBase
contacts={contacts}
onSelect={(contactId) => setMasterId(contactId)}
selected={masterId}
title="Мастера"
/>
);
});
export const ClientsGrid = withContext(ContactsContextProvider)(function () {
const { contacts, isLoading, setFilter } = useCustomerContacts();
const clientId = useOrderStore((store) => store.clientId);
const setClientId = useOrderStore((store) => store.setClientId);
useEffect(() => {
setFilter('clients');
}, [setFilter]);
if (isLoading) return <LoadingSpinner />;
return (
<ContactsGridBase
contacts={contacts}
onSelect={(contactId) => setClientId(contactId)}
selected={clientId}
title="Клиенты"
/>
);
});