ui phase 7

This commit is contained in:
hamid
2026-07-19 11:56:59 +03:30
parent a438edeeaa
commit edc38543fd
39 changed files with 1538 additions and 208 deletions
@@ -1,36 +1,36 @@
'use client';
import { useLocale, useTranslations } from 'next-intl';
import { useRouter } from 'next/navigation';
import { Box, Skeleton, Stack, Typography } from '@mui/material';
import { AppButton, EmptyState } from '@/components';
import { Box, Skeleton, Stack } from '@mui/material';
import { AppButton, EmptyState, ErrorState, PageHeader } from '@/components';
import { SessionCard, useEvvController } from '@/components/booking';
import { CONTENT_MAX_WIDTH } from '@/components/config';
import { ROUTES } from '@/constants';
import { formatShamsiDate } from '@/utils';
import { useSessionEvv, useTodaySessions } from '@/services/bookings';
import type { BookingSessionListItemDto } from '@/services/bookings/types';
const TODAY_HEADER_DATE_OPTIONS: Intl.DateTimeFormatOptions = { month: 'long', day: 'numeric' };
/**
* Nurse ویزیت امروز (E3 top) — the day's operational surface. Lists today's sessions from
* `useTodaySessions`; each renders the shared `SessionCard` with the per-session EVV check-in/out control
* (driven by one `useEvvController`) and the advisory EVV banner once checked in. A GPS mismatch is
* advisory, never a block. Each card also deep-links to the full booking detail (`/nurse/visits/{id}`),
* where the gated care instructions live. Visit-note authoring + task checklist are deferred to f13.
* `useTodaySessions` (polled every 60s so a same-day schedule change surfaces without re-navigation);
* each renders the shared `SessionCard` with the per-session EVV check-in/out control (driven by one
* `useEvvController`) and the advisory EVV banner once checked in. A GPS mismatch is advisory, never a
* block. Each card also deep-links to the full booking detail (`/nurse/visits/{id}`), where the gated
* care instructions live. Visit-note authoring + task checklist are deferred to f13.
*/
export default function NurseVisitsPage() {
const t = useTranslations('booking');
const { data, isLoading } = useTodaySessions();
const locale = useLocale();
const { data, isLoading, isError, refetch } = useTodaySessions();
const evv = useEvvController();
const items = data?.items ?? [];
const dateAnchor = t('today_date_prefix', { date: formatShamsiDate(new Date(), locale, TODAY_HEADER_DATE_OPTIONS) });
return (
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 3, maxWidth: 640 }}>
<Box>
<Typography variant="h5" component="h1">
{t('evv_visits_title')}
</Typography>
<Typography variant="body2" sx={{ color: 'text.secondary' }}>
{t('evv_visits_subtitle')}
</Typography>
</Box>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 3, maxWidth: CONTENT_MAX_WIDTH, mx: 'auto', width: '100%' }}>
<PageHeader title={dateAnchor} subtitle={t('evv_visits_subtitle')} />
{isLoading ? (
<Stack sx={{ gap: 2 }}>
@@ -38,6 +38,8 @@ export default function NurseVisitsPage() {
<Skeleton key={key} variant="rounded" height={150} />
))}
</Stack>
) : isError ? (
<ErrorState message={t('evv_visits_error')} retryLabel={t('retry')} onRetry={() => refetch()} />
) : items.length === 0 ? (
<EmptyState icon="visits" title={t('evv_no_visits')} />
) : (
@@ -64,6 +66,7 @@ function TodayVisitCard({ item, evv }: { item: BookingSessionListItemDto; evv: R
<Stack sx={{ gap: 0.75 }}>
<SessionCard
title={item.patientName}
serviceLabel={item.variantLabel}
sessionIndex={item.sessionIndex}
scheduledDate={item.scheduledDate}
scheduledTimeStart={item.scheduledTimeStart}