improvement: QRcode and shared link added to cases inorder to make it possible for staff users to share a case info with other staffs or other clinics.

This commit is contained in:
2026-07-14 21:07:05 +03:30
parent 953e609fb8
commit 08df2f71ea
41 changed files with 1535 additions and 83 deletions

View File

@@ -0,0 +1,75 @@
import { apiClient } from './client';
import type { LabCaseComment, LabTaskListItem } from '@/types/cases';
export interface LabCaseAccessProsthesisGroup {
prosthesisTypeCode: string;
prosthesisTypeLabel: string;
teeth: string[];
}
export interface LabCaseAccessSession {
labCaseId: string;
accessMode: 'lab' | 'clinic';
canEditTaskStatus: boolean;
canPostComments: boolean;
canToggleCommentVisibility: boolean;
shareUrl: string;
sentAt: string | null;
dueDate: string | null;
isOverdue: boolean;
isImportant: boolean;
clinic: { id: string; name: string };
lab: { id: string; name: string } | null;
patient: { id: string; firstName: string; lastName: string };
prosthesisGroups: LabCaseAccessProsthesisGroup[];
}
export const labCaseAccessApi = {
resolve: async (
token: string,
): Promise<{ success: boolean; data: LabCaseAccessSession }> => {
const response = await apiClient.get(`/lab-cases/access/${encodeURIComponent(token)}`);
return response.data;
},
listTasks: async (
token: string,
): Promise<{ success: boolean; data: { items: LabTaskListItem[] } }> => {
const response = await apiClient.get(
`/lab-cases/access/${encodeURIComponent(token)}/tasks`,
);
return response.data;
},
listComments: async (
token: string,
): Promise<{ success: boolean; data: LabCaseComment[] }> => {
const response = await apiClient.get(
`/lab-cases/access/${encodeURIComponent(token)}/comments`,
);
return response.data;
},
addComment: async (
token: string,
payload: { body: string; visibleToClinic?: boolean },
): Promise<{ success: boolean; data: LabCaseComment }> => {
const response = await apiClient.post(
`/lab-cases/access/${encodeURIComponent(token)}/comments`,
payload,
);
return response.data;
},
setCommentVisibility: async (
token: string,
commentId: string,
visibleToClinic: boolean,
): Promise<{ success: boolean; data: LabCaseComment }> => {
const response = await apiClient.patch(
`/lab-cases/access/${encodeURIComponent(token)}/comments/${commentId}/visibility`,
{ visibleToClinic },
);
return response.data;
},
};

View File

@@ -0,0 +1,17 @@
import { stripLocaleFromPathname } from '@/i18n/routing';
const AUTH_REDIRECT_KEY = 'authRedirect';
export function storeAuthRedirectFromPath(pathWithOptionalLocale: string) {
if (typeof window === 'undefined') return;
const path = stripLocaleFromPathname(pathWithOptionalLocale);
if (!path || path === '/login' || path === '/register') return;
sessionStorage.setItem(AUTH_REDIRECT_KEY, path);
}
export function consumeAuthRedirect(): string | null {
if (typeof window === 'undefined') return null;
const path = sessionStorage.getItem(AUTH_REDIRECT_KEY);
if (path) sessionStorage.removeItem(AUTH_REDIRECT_KEY);
return path;
}

View File

@@ -17,6 +17,7 @@ import {
startProactiveSessionRefresh,
} from '@/lib/auth/proactiveRefresh';
import { asApiError, legacyStatusCode, type ApiError } from '@/types/api';
import { consumeAuthRedirect } from '@/lib/auth/postAuthRedirect';
function toApiError(err: unknown): ApiError {
return (
@@ -288,10 +289,8 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
await authApi.selectOrganization(org.id);
setCurrentOrganization(org);
localStorage.setItem('currentOrganizationId', org.id);
router.push('/today');
} else {
router.push('/select-organization');
}
} catch (err: any) {
@@ -332,7 +331,6 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
await authApi.selectOrganization(org.id);
setCurrentOrganization(org);
localStorage.setItem('currentOrganizationId', org.id);
router.push('/today');
} else {
router.push('/select-organization');
}
@@ -388,12 +386,8 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
plan: (organization as { plan?: Organization['plan'] }).plan,
});
const redirectPath =
typeof window !== 'undefined'
? sessionStorage.getItem('authRedirect')
: null;
const redirectPath = consumeAuthRedirect();
if (redirectPath) {
sessionStorage.removeItem('authRedirect');
router.push(redirectPath);
} else {
router.push('/today');