Skip to content

Commit 637592e

Browse files
committed
UI: Documents
1 parent 2ff987c commit 637592e

2 files changed

Lines changed: 99 additions & 65 deletions

File tree

Lines changed: 98 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,47 @@
11
'use client';
22

3-
import { useEffect, useState } from 'react';
3+
import { useEffect, useState, useRef } from 'react';
44
import { uploadPatientDocument } from '../../../../features/patient/api/uploadDocument';
55
import { getPatientDocuments } from '../../../../features/patient/api/getDocument';
66
import { deletePatientDocument } from '../../../../features/patient/api/deleteDocument';
7-
import { FileText, Upload, Trash2 } from 'lucide-react';
7+
8+
import {
9+
FileText,
10+
Upload,
11+
Trash2,
12+
Image,
13+
File,
14+
Download
15+
} from 'lucide-react';
816

917
type DocumentType = {
1018
file_url: string;
1119
file_key: string;
1220
file_name: string;
1321
};
1422

15-
export default function DocumentsPage() {
23+
function getFileIcon(fileName: string) {
1624

25+
const extension = fileName.split('.').pop()?.toLowerCase();
26+
27+
if (extension === 'pdf') {
28+
return <FileText className="w-6 h-6 text-red-500" />;
29+
}
30+
31+
if (['png', 'jpg', 'jpeg', 'webp'].includes(extension || '')) {
32+
return <Image className="w-6 h-6 text-blue-500" />;
33+
}
34+
35+
return <File className="w-6 h-6 text-gray-500" />;
36+
}
37+
38+
export default function DocumentsPage() {
1739

1840
const [documents, setDocuments] = useState<DocumentType[]>([]);
1941
const [uploading, setUploading] = useState(false);
2042

21-
function getFileName(url: string) {
22-
return url.split('/').pop();
23-
}
24-
// load documents
43+
const fileInputRef = useRef<HTMLInputElement | null>(null);
44+
2545
useEffect(() => {
2646

2747
async function loadDocuments() {
@@ -77,95 +97,109 @@ export default function DocumentsPage() {
7797
}
7898

7999
return (
80-
<div className="space-y-8">
81100

82-
<div>
83-
<h1 className="text-3xl font-bold text-slate-900">
84-
Documents
85-
</h1>
101+
<div className="max-w-6xl mx-auto space-y-8">
86102

87-
<p className="text-slate-500">
88-
Upload and manage your medical documents
89-
</p>
90-
</div>
103+
{/* Header */}
91104

92-
{/* Upload Section */}
105+
<div className="flex items-center justify-between">
93106

94-
<div className="bg-white rounded-2xl p-6 shadow border">
107+
<div>
108+
<h1 className="text-2xl font-bold text-slate-900">
109+
Documents
110+
</h1>
95111

96-
<label className="flex flex-col items-center justify-center border-2 border-dashed rounded-xl p-10 cursor-pointer hover:bg-slate-50">
112+
<p className="text-sm text-slate-500 mt-1">
113+
Your medical documents and files
114+
</p>
115+
</div>
97116

98-
<Upload size={30} className="mb-2 text-slate-500" />
117+
<button
118+
onClick={() => fileInputRef.current?.click()}
119+
className="flex items-center gap-2 px-5 py-2.5 rounded-xl bg-indigo-600 text-white font-semibold text-sm hover:bg-indigo-700 transition"
120+
>
121+
<Upload className="w-4 h-4" />
99122

100-
<p className="text-slate-700 font-medium">
101-
{uploading ? "Uploading..." : "Click to upload document"}
102-
</p>
123+
{uploading ? "Uploading..." : "Upload"}
103124

104-
<input
105-
type="file"
106-
className="hidden"
107-
onChange={handleUpload}
108-
/>
125+
</button>
109126

110-
</label>
127+
<input
128+
type="file"
129+
ref={fileInputRef}
130+
className="hidden"
131+
onChange={handleUpload}
132+
/>
111133

112134
</div>
113135

114-
{/* Document List */}
136+
{/* Empty State */}
115137

116-
<div className="bg-white rounded-2xl p-6 shadow border">
138+
{documents.length === 0 && (
117139

118-
<h2 className="font-semibold mb-4 text-lg">
119-
Uploaded Documents
120-
</h2>
140+
<div className="bg-white rounded-2xl p-10 border text-center text-slate-500">
141+
No documents uploaded yet
142+
</div>
121143

122-
{documents.length === 0 && (
123-
<p className="text-slate-500">
124-
No documents uploaded yet.
125-
</p>
126-
)}
144+
)}
127145

128-
<div className="space-y-3">
146+
{/* Document Grid */}
129147

130-
{documents.map((doc, index) => (
148+
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
131149

132-
<div
133-
key={doc.file_key}
134-
className="flex items-center justify-between p-3 border rounded-lg hover:bg-slate-50"
135-
>
150+
{documents.map((doc, index) => (
136151

137-
<a
138-
href={doc.file_url}
139-
target="_blank"
140-
className="flex items-center gap-3"
141-
>
152+
<div
153+
key={doc.file_key}
154+
className="bg-white rounded-2xl p-5 shadow hover:shadow-lg transition group"
155+
>
142156

143-
<FileText size={18} className="text-blue-600" />
144-
<span className="text-sm font-medium">
145-
{getFileName(doc.file_name)}
146-
</span>
157+
<div className="flex items-start justify-between mb-4">
147158

148-
</a>
159+
<div className="w-12 h-12 rounded-xl flex items-center justify-center bg-slate-100">
160+
{getFileIcon(doc.file_name)}
161+
</div>
149162

150-
<button
151-
onClick={() => handleDelete(index, doc.file_key)}
152-
className="text-red-500 flex items-center gap-1 text-sm"
153-
>
163+
<div className="flex items-center gap-2 opacity-0 group-hover:opacity-100 transition">
154164

155-
<Trash2 size={16} />
165+
<a
166+
href={doc.file_url}
167+
target="_blank"
168+
className="p-2 rounded-lg hover:bg-slate-100"
169+
>
170+
<Download className="w-4 h-4 text-slate-500" />
171+
</a>
156172

157-
Delete
173+
<button
174+
onClick={() => handleDelete(index, doc.file_key)}
175+
className="p-2 rounded-lg hover:bg-red-50"
176+
>
177+
<Trash2 className="w-4 h-4 text-red-500" />
178+
</button>
158179

159-
</button>
180+
</div>
160181

161182
</div>
162183

163-
))}
184+
<a
185+
href={doc.file_url}
186+
target="_blank"
187+
className="block"
188+
>
164189

165-
</div>
190+
<h3 className="font-semibold text-slate-900 text-sm truncate">
191+
{doc.file_name}
192+
</h3>
193+
194+
</a>
195+
196+
</div>
197+
198+
))}
166199

167200
</div>
168201

169202
</div>
203+
170204
);
171205
}

services/patient-service/src/modules/patients/patient.documents.repository.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export async function savePatientDocument(
2121
export async function getPatientDocuments(patientId: string) {
2222
const result = await pool.query(
2323
`
24-
SELECT file_url, file_key
24+
SELECT file_url, file_key, file_name
2525
FROM patient_documents
2626
WHERE patient_id=$1
2727
ORDER BY created_at DESC

0 commit comments

Comments
 (0)