feature: localization's first implmentation done. all frontend hardcoded text is now localized.

This commit is contained in:
2026-06-20 14:51:43 +03:30
parent 284fbd08aa
commit b2f4dfa4ca
52 changed files with 3306 additions and 1041 deletions

View File

@@ -1,6 +1,7 @@
'use client';
import { useMemo, useState } from 'react';
import { useTranslations } from 'next-intl';
import type { AppointmentColumnProvider, AppointmentRecord } from '@/types/appointment';
import {
SCHEDULE_SLOT_MINUTES,
@@ -91,6 +92,7 @@ export function AppointmentScheduleGrid({
onAppointmentClick,
onAppointmentOutsideHours,
}: AppointmentScheduleGridProps) {
const t = useTranslations('appointments');
const [overlapPopover, setOverlapPopover] = useState<OverlapPopoverState | null>(null);
const visibleRange = useMemo(() => {
@@ -159,18 +161,13 @@ export function AppointmentScheduleGrid({
if (providers.length === 0) {
return (
<div className="surface-card p-6 text-sm text-text-muted">
No providers available. Add staff with treatment edit access to see columns here.
</div>
<div className="surface-card p-6 text-sm text-text-muted">{t('noProviders')}</div>
);
}
if (!snappedRange || slotStarts.length === 0) {
return (
<div className="surface-card p-6 text-sm text-text-muted">
No working hours are configured for this day. Set provider working hours in Staff
management.
</div>
<div className="surface-card p-6 text-sm text-text-muted">{t('noWorkingHours')}</div>
);
}
@@ -188,12 +185,12 @@ export function AppointmentScheduleGrid({
{p.name}
{!p.hasWorkingHours && (
<span className="block text-[10px] font-normal text-text-muted mt-0.5">
No hours set
{t('noHoursSet')}
</span>
)}
{p.hasWorkingHours && p.dayBlocks.length === 0 && (
<span className="block text-[10px] font-normal text-text-muted mt-0.5">
Off today
{t('offToday')}
</span>
)}
</div>
@@ -252,13 +249,15 @@ export function AppointmentScheduleGrid({
title={
columnFullyDisabled
? p.hasWorkingHours
? 'Provider is off today'
: 'Working hours not configured'
? t('slotOffToday')
: t('slotHoursNotConfigured')
: !slotActive
? 'Outside working hours'
? t('slotOutsideHours')
: slotDisabled
? 'You cannot create appointments'
: `Book ${formatMinuteLabel(slotStartMinute)}`
? t('slotCannotCreate')
: t('slotBookAt', {
time: formatMinuteLabel(slotStartMinute),
})
}
className={`absolute left-0 right-0 border-b border-border/50 transition-colors ${
slotDisabled
@@ -297,8 +296,10 @@ export function AppointmentScheduleGrid({
const patientName = `${apt.patient.firstName} ${apt.patient.lastName}`;
const bannerTitle = [
patientName,
outsideHours ? 'Outside working hours — editing blocked' : null,
clusterSize > 1 ? `${clusterSize} overlapping — click to choose` : null,
outsideHours ? t('outsideHoursBlocked') : null,
clusterSize > 1
? t('overlappingChoose', { count: clusterSize })
: null,
!isUnderOneHour && apt.patient.phone ? apt.patient.phone : null,
]
.filter(Boolean)
@@ -345,7 +346,7 @@ export function AppointmentScheduleGrid({
)}
{!isUnderOneHour && clusterSize > 1 && (
<span className="block w-full truncate pointer-events-none text-[9px] leading-tight opacity-75">
{clusterSize} overlapping
{t('overlapping', { count: clusterSize })}
</span>
)}
</button>