feat: add per-patient Local folder in Documents page backed by Cloud Storage

- Documents page shows a "Local Folder" card for each selected patient
  with an "Open in Cloud Storage" button that deep-links to their folder
- Cloud Storage page reads ?folderId URL param on mount and auto-opens
  the folder panel for seamless navigation from Documents
- Backend: GET /api/cloud-storage/patient-folder/:patientId endpoint
  that idempotently gets or creates a top-level CloudFolder per patient
- CloudFolder schema gains optional patientId field linked to Patient
- Disk directories for cloud storage folders now use the folder's name
  (e.g. "Xiaohui Wang/") instead of the opaque "folder-{id}/" path

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
ff
2026-06-05 23:01:56 -04:00
parent 2457e12b5c
commit d5bc96ff39
158 changed files with 1539 additions and 130 deletions

File diff suppressed because one or more lines are too long

View File

@@ -370,6 +370,7 @@ exports.Prisma.CloudFolderScalarFieldEnum = {
userId: 'userId',
name: 'name',
parentId: 'parentId',
patientId: 'patientId',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
};

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
{
"name": "prisma-client-dffa61cfa33500c5a3d8eb3911d8102dda0abe78c0c02287d94a83d7e3de2af7",
"name": "prisma-client-5274dcc359e2ac7cb6d4e95a13b684de504baf5945107a0270a97148d1ad0620",
"main": "index.js",
"types": "index.d.ts",
"browser": "default.js",

View File

@@ -78,6 +78,7 @@ model Patient {
communications Communication[]
documents PatientDocument[]
conversation PatientConversation?
cloudFolders CloudFolder[] @relation("PatientCloudFolder")
@@index([insuranceId])
@@index([createdAt])
@@ -479,15 +480,18 @@ model CloudFolder {
userId Int
name String
parentId Int?
patientId Int?
parent CloudFolder? @relation("FolderChildren", fields: [parentId], references: [id], onDelete: Cascade)
children CloudFolder[] @relation("FolderChildren")
user User @relation(fields: [userId], references: [id])
patient Patient? @relation("PatientCloudFolder", fields: [patientId], references: [id], onDelete: SetNull)
files CloudFile[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([userId, parentId, name]) // prevents sibling folder name duplicates
@@index([parentId])
@@index([patientId])
}
model CloudFile {
@@ -602,11 +606,11 @@ model AiSettings {
apiKey String
aiEnabled Boolean @default(true)
openAiKey String @default("")
openAiEnabled Boolean @default(true)
openAiEnabled Boolean @default(false)
claudeAiKey String @default("")
claudeAiEnabled Boolean @default(true)
claudeAiEnabled Boolean @default(false)
dentalMgmtKey String @default("")
dentalMgmtEnabled Boolean @default(true)
dentalMgmtEnabled Boolean @default(false)
afterHoursEnabled Boolean @default(true)
openPhoneReply Boolean @default(false)