improvement: error handeling structure changed and unified all across the app. user no longer sees inappropriate messages.
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
import { useCallback, useEffect, useState, type KeyboardEvent } from 'react';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { Eye, EyeOff, Send } from 'lucide-react';
|
||||
import { formatApiErrorMessage } from '@/components/shared/formatApiError';
|
||||
import { getUserFacingError } from '@/components/shared/formatApiError';
|
||||
import type { LabCaseComment } from '@/types/cases';
|
||||
|
||||
interface LabCaseCommentsPanelProps {
|
||||
@@ -36,6 +36,7 @@ export function LabCaseCommentsPanel({
|
||||
onComposerValueChange,
|
||||
}: LabCaseCommentsPanelProps) {
|
||||
const t = useTranslations('caseComments');
|
||||
const tErrors = useTranslations('errors');
|
||||
const [comments, setComments] = useState<LabCaseComment[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [posting, setPosting] = useState(false);
|
||||
@@ -48,7 +49,7 @@ export function LabCaseCommentsPanel({
|
||||
const items = await loadComments();
|
||||
setComments(items);
|
||||
} catch (error: unknown) {
|
||||
onError?.(formatApiErrorMessage(error, t('errorLoad')));
|
||||
onError?.(getUserFacingError(error, tErrors, t('errorLoad')));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
@@ -68,7 +69,7 @@ export function LabCaseCommentsPanel({
|
||||
setBody('');
|
||||
setVisibleToClinic(false);
|
||||
} catch (error: unknown) {
|
||||
onError?.(formatApiErrorMessage(error, t('errorPost')));
|
||||
onError?.(getUserFacingError(error, tErrors, t('errorPost')));
|
||||
} finally {
|
||||
setPosting(false);
|
||||
}
|
||||
@@ -87,7 +88,7 @@ export function LabCaseCommentsPanel({
|
||||
const updated = await onToggleVisibility(comment.id, !comment.visibleToClinic);
|
||||
setComments((prev) => prev.map((c) => (c.id === updated.id ? updated : c)));
|
||||
} catch (error: unknown) {
|
||||
onError?.(formatApiErrorMessage(error, t('errorToggle')));
|
||||
onError?.(getUserFacingError(error, tErrors, t('errorToggle')));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { formatApiErrorMessage } from '@/components/shared/formatApiError';
|
||||
import { getUserFacingError } from '@/components/shared/formatApiError';
|
||||
import { canEditCases } from '@/components/shared/permissions';
|
||||
import { useAuth } from '@/lib/hooks/useAuth';
|
||||
import { useToast } from '@/lib/hooks/useToast';
|
||||
@@ -37,6 +37,7 @@ export function ConnectionCaseHistoryContent({
|
||||
onBack,
|
||||
}: ConnectionCaseHistoryContentProps) {
|
||||
const t = useTranslations('organizations');
|
||||
const tErrors = useTranslations('errors');
|
||||
const tCases = useTranslations('cases');
|
||||
const tCommon = useTranslations('common');
|
||||
const { currentOrganization, user } = useAuth();
|
||||
@@ -102,7 +103,7 @@ export function ConnectionCaseHistoryContent({
|
||||
setPagination(response.data.pagination);
|
||||
} catch (error: unknown) {
|
||||
if (cancelled) return;
|
||||
showError(formatApiErrorMessage(error, tRef.current('caseHistoryErrorLoadList')));
|
||||
showError(getUserFacingError(error, tErrors, tRef.current('caseHistoryErrorLoadList')));
|
||||
} finally {
|
||||
if (!cancelled) setLoadingList(false);
|
||||
}
|
||||
@@ -142,7 +143,7 @@ export function ConnectionCaseHistoryContent({
|
||||
setSelectedCase(response.data);
|
||||
} catch (error: unknown) {
|
||||
if (cancelled) return;
|
||||
showError(formatApiErrorMessage(error, tRef.current('caseHistoryErrorLoadDetail')));
|
||||
showError(getUserFacingError(error, tErrors, tRef.current('caseHistoryErrorLoadDetail')));
|
||||
setSelectedCase(null);
|
||||
} finally {
|
||||
if (!cancelled) setLoadingDetail(false);
|
||||
@@ -182,7 +183,7 @@ export function ConnectionCaseHistoryContent({
|
||||
setSelectedCase(response.data);
|
||||
} catch (error: unknown) {
|
||||
setSelectedCase(previousCase);
|
||||
showError(formatApiErrorMessage(error, tCases('errorUpdateTask')));
|
||||
showError(getUserFacingError(error, tErrors, tCases('errorUpdateTask')));
|
||||
} finally {
|
||||
setUpdatingImportant(false);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { getUserFacingError } from '@/components/shared/formatApiError';
|
||||
import { useAuth } from '@/lib/hooks/useAuth';
|
||||
import { canCreateOrganizationFromCurrentOrg } from '@/components/shared/permissions';
|
||||
import { Building2, Beaker, Mail } from 'lucide-react';
|
||||
@@ -12,13 +13,14 @@ export function OrganizationSelectorContent() {
|
||||
const t = useTranslations('organizations');
|
||||
const tAuth = useTranslations('auth');
|
||||
const tCommon = useTranslations('common');
|
||||
const tErrors = useTranslations('errors');
|
||||
const {
|
||||
organizations,
|
||||
currentOrganization,
|
||||
selectOrganization,
|
||||
createOrganization,
|
||||
isLoading,
|
||||
error,
|
||||
apiError,
|
||||
clearError,
|
||||
} = useAuth();
|
||||
const canCreateOrganization = useMemo(
|
||||
@@ -82,6 +84,12 @@ export function OrganizationSelectorContent() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{apiError && (
|
||||
<div className="p-3 bg-red-950/30 border border-red-600/40 rounded-[var(--radius-md)]">
|
||||
<p className="text-sm text-red-600">{getUserFacingError(apiError, tErrors)}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{canCreateOrganization && isCreateOpen && (
|
||||
<div className="surface-card p-4 sm:p-6 space-y-4">
|
||||
<Input
|
||||
@@ -128,11 +136,6 @@ export function OrganizationSelectorContent() {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{error && (
|
||||
<div className="p-3 bg-red-950/30 border border-red-600/40 rounded-[var(--radius-md)]">
|
||||
<p className="text-sm text-red-600">{error}</p>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-col sm:flex-row sm:justify-end">
|
||||
<Button
|
||||
type="button"
|
||||
|
||||
@@ -22,7 +22,7 @@ import { treatmentCatalogApi } from '@/lib/api/treatment-catalog';
|
||||
import { treatmentsApi } from '@/lib/api/treatments';
|
||||
import { pickAutoAppointment } from '@/components/shared/treatmentSelection';
|
||||
import { canEditTreatment, canViewTreatment } from '@/components/shared/permissions';
|
||||
import { formatApiErrorMessage } from '@/components/shared/formatApiError';
|
||||
import { getUserFacingError } from '@/components/shared/formatApiError';
|
||||
import { useToast } from '@/lib/hooks/useToast';
|
||||
import type { Organization } from '@/types/organization';
|
||||
import type { AppointmentRecord } from '@/types/appointment';
|
||||
@@ -264,6 +264,7 @@ export function TreatmentWorkspace({
|
||||
initialAppointmentId = null,
|
||||
}: TreatmentWorkspaceProps) {
|
||||
const t = useTranslations('treatment');
|
||||
const tErrors = useTranslations('errors');
|
||||
const router = useRouter();
|
||||
const { showError, showSuccess, messages: toastMessages } = useToast();
|
||||
const canView = canViewTreatment(currentOrganization);
|
||||
@@ -493,7 +494,7 @@ export function TreatmentWorkspace({
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
if (!cancelled) {
|
||||
showError(formatApiErrorMessage(error, t('errorLoadAppointments')));
|
||||
showError(getUserFacingError(error, tErrors, t('errorLoadAppointments')));
|
||||
}
|
||||
} finally {
|
||||
if (!cancelled) setApptsLoading(false);
|
||||
@@ -534,7 +535,7 @@ export function TreatmentWorkspace({
|
||||
);
|
||||
} catch (error: unknown) {
|
||||
if (!cancelled) {
|
||||
showError(formatApiErrorMessage(error, t('errorLoadOrgs')));
|
||||
showError(getUserFacingError(error, tErrors, t('errorLoadOrgs')));
|
||||
}
|
||||
}
|
||||
})();
|
||||
@@ -563,7 +564,7 @@ export function TreatmentWorkspace({
|
||||
if (!cancelled) setHistory(response.data);
|
||||
} catch (error: unknown) {
|
||||
if (!cancelled) {
|
||||
showError(formatApiErrorMessage(error, t('errorLoadHistory')));
|
||||
showError(getUserFacingError(error, tErrors, t('errorLoadHistory')));
|
||||
}
|
||||
} finally {
|
||||
if (!cancelled) setHistoryLoading(false);
|
||||
@@ -621,7 +622,7 @@ export function TreatmentWorkspace({
|
||||
setSaveStatus('idle');
|
||||
} catch (error: unknown) {
|
||||
if (!cancelled) {
|
||||
showError(formatApiErrorMessage(error, t('errorLoadDraft')));
|
||||
showError(getUserFacingError(error, tErrors, t('errorLoadDraft')));
|
||||
}
|
||||
} finally {
|
||||
if (!cancelled) {
|
||||
@@ -693,7 +694,7 @@ export function TreatmentWorkspace({
|
||||
setSaveStatus('saved');
|
||||
} catch (error: unknown) {
|
||||
setSaveStatus('error');
|
||||
showError(formatApiErrorMessage(error, t('errorSaveDraft')));
|
||||
showError(getUserFacingError(error, tErrors, t('errorSaveDraft')));
|
||||
throw error;
|
||||
} finally {
|
||||
saveInFlightRef.current = false;
|
||||
@@ -711,7 +712,7 @@ export function TreatmentWorkspace({
|
||||
const response = await treatmentsApi.listPatientHistory(patientId);
|
||||
setHistory(response.data);
|
||||
} catch (error: unknown) {
|
||||
showError(formatApiErrorMessage(error, t('errorLoadHistory')));
|
||||
showError(getUserFacingError(error, tErrors, t('errorLoadHistory')));
|
||||
}
|
||||
}, [showError, t]);
|
||||
|
||||
@@ -864,7 +865,7 @@ export function TreatmentWorkspace({
|
||||
);
|
||||
showSuccess(t('successFilesUploaded', { count: uploaded.data.length }));
|
||||
} catch (error: unknown) {
|
||||
showError(formatApiErrorMessage(error, t('errorUpload')));
|
||||
showError(getUserFacingError(error, tErrors, t('errorUpload')));
|
||||
} finally {
|
||||
setUploadBusyDetailId(null);
|
||||
}
|
||||
@@ -954,7 +955,7 @@ export function TreatmentWorkspace({
|
||||
const saved = await persistDraft({ force: true });
|
||||
await persistLabCases(saved, cleaned);
|
||||
} catch (error: unknown) {
|
||||
showError(formatApiErrorMessage(error, t('errorSaveLabShipments')));
|
||||
showError(getUserFacingError(error, tErrors, t('errorSaveLabShipments')));
|
||||
}
|
||||
})();
|
||||
}
|
||||
@@ -999,7 +1000,7 @@ export function TreatmentWorkspace({
|
||||
const saved = await persistDraft({ force: true });
|
||||
await persistLabCases(saved, updatedLabCases);
|
||||
} catch (error: unknown) {
|
||||
showError(formatApiErrorMessage(error, t('errorSaveLabShipments')));
|
||||
showError(getUserFacingError(error, tErrors, t('errorSaveLabShipments')));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1016,7 +1017,7 @@ export function TreatmentWorkspace({
|
||||
const saved = await persistDraft({ force: true });
|
||||
await persistLabCases(saved, updatedLabCases);
|
||||
} catch (error: unknown) {
|
||||
showError(formatApiErrorMessage(error, t('errorSaveLabShipments')));
|
||||
showError(getUserFacingError(error, tErrors, t('errorSaveLabShipments')));
|
||||
}
|
||||
}, [
|
||||
activeDetailId,
|
||||
@@ -1104,7 +1105,7 @@ export function TreatmentWorkspace({
|
||||
});
|
||||
showSuccess(t('successCaseSent'));
|
||||
} catch (error: unknown) {
|
||||
showError(formatApiErrorMessage(error, t('errorSendCase')));
|
||||
showError(getUserFacingError(error, tErrors, t('errorSendCase')));
|
||||
} finally {
|
||||
setSendBusyId(null);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user