Positioning, sizing and sorting of the gadgets improved.

This commit is contained in:
2026-07-11 22:32:37 +03:30
parent ed8ff61205
commit 83f6003a2b
35 changed files with 1615 additions and 678 deletions

View File

@@ -189,6 +189,9 @@ export default function AppointmentsPage() {
}
function handleSlotClick(startMinute: number, providerUserId: string, providerName: string) {
if (!canManageAppointments) {
return;
}
if (isViewingPastDay) {
toast.showInfo(t('infoPastViewOnly'));
return;
@@ -205,6 +208,9 @@ export default function AppointmentsPage() {
}
function handleAppointmentClick(appointment: AppointmentRecord) {
if (!canManageAppointments) {
return;
}
if (isViewingPastDay) {
toast.showInfo(t('infoPastViewOnly'));
return;

View File

@@ -4,18 +4,8 @@ import { useMemo } from 'react';
import { useTranslations } from 'next-intl';
import { Link } from '@/i18n/navigation';
import { useAuth } from '@/lib/hooks/useAuth';
import {
canAccessAppointmentsSection,
canViewAppointmentsTab,
canViewCases,
canViewLabCasesOrTasks,
canViewTasks,
canViewTreatment,
} from '@/components/shared/permissions';
import { formatApiErrorMessage } from '@/components/shared/formatApiError';
import { TodayKpiGrid } from '@/components/today/TodayKpiGrid';
import { TodayChartsSection } from '@/components/today/TodayChartsSection';
import { TodayUpcomingAppointments } from '@/components/today/TodayUpcomingAppointments';
import { TodayDashboard } from '@/components/today/TodayDashboard';
import { TodayLoadErrorBanner } from '@/components/today/TodayLoadErrorBanner';
import { TodaySectionErrorFallback } from '@/components/today/TodaySectionErrorFallback';
import { TodayWidgetErrorBoundary } from '@/components/today/TodayWidgetErrorBoundary';
@@ -27,29 +17,10 @@ export default function TodayPage() {
const orgId = currentOrganization?.id;
const { data, loading, isInitialLoad, error, reload } = useTodaySummary(orgId);
const showNoSubscriptionNotice =
Boolean(currentOrganization?.isOwner) && !currentOrganization?.plan;
const showUpcoming =
currentOrganization?.type === 'CLINIC' && canViewTreatment(currentOrganization);
const showCharts = useMemo(() => {
const orgType = currentOrganization?.type;
if (!orgType) return false;
if (orgType === 'CLINIC') {
return (
canAccessAppointmentsSection(currentOrganization) ||
canViewAppointmentsTab(currentOrganization) ||
canViewTreatment(currentOrganization)
);
}
return (
canViewCases(currentOrganization) ||
canViewTasks(currentOrganization) ||
canViewLabCasesOrTasks(currentOrganization)
);
}, [currentOrganization]);
const showNoSubscriptionNotice = useMemo(
() => Boolean(currentOrganization?.isOwner) && !currentOrganization?.plan,
[currentOrganization],
);
const sectionErrorMessage = t('sectionLoadError');
@@ -93,47 +64,16 @@ export default function TodayPage() {
<TodayWidgetErrorBoundary
fallback={<TodaySectionErrorFallback message={sectionErrorMessage} />}
>
<TodayKpiGrid
<TodayDashboard
widgets={data?.widgets ?? {}}
charts={data?.charts ?? {}}
actions={data?.actions ?? {}}
subscription={data?.subscription}
loading={loading}
isInitialLoad={isInitialLoad}
hasError={Boolean(error)}
/>
</TodayWidgetErrorBoundary>
{showUpcoming && (!error || data) ? (
<TodayWidgetErrorBoundary
fallback={<TodaySectionErrorFallback message={sectionErrorMessage} />}
>
<div
className={`grid grid-cols-1 gap-4 lg:grid-cols-2 ${loading ? 'opacity-70 transition-opacity' : ''}`}
>
<TodayUpcomingAppointments
actions={data?.actions ?? {}}
loading={loading}
isInitialLoad={isInitialLoad}
/>
{showCharts ? (
<TodayChartsSection
charts={data?.charts ?? {}}
loading={loading}
isInitialLoad={isInitialLoad}
embedded
/>
) : null}
</div>
</TodayWidgetErrorBoundary>
) : showCharts && (!error || data) ? (
<TodayWidgetErrorBoundary
fallback={<TodaySectionErrorFallback message={sectionErrorMessage} />}
>
<TodayChartsSection
charts={data?.charts ?? {}}
loading={loading}
isInitialLoad={isInitialLoad}
/>
</TodayWidgetErrorBoundary>
) : null}
</div>
);
}