diff --git a/web/app/ai-chat/page.js b/web/app/ai-chat/page.js
index 09ac5ba3..ce8895b8 100644
--- a/web/app/ai-chat/page.js
+++ b/web/app/ai-chat/page.js
@@ -8,6 +8,66 @@ import { createStompClient } from "@/lib/chatSocket";
const API_BASE = "";
+function isImageFilename(name) {
+ return /\.(jpe?g|png|gif|webp|bmp|svg)$/i.test(name || "");
+}
+
+function AttachmentPreview({ url, name, token }) {
+ const [blobUrl, setBlobUrl] = useState(null);
+ const isImage = isImageFilename(name);
+
+ useEffect(() => {
+ if (!url || !token) return;
+ let objectUrl;
+ fetch(url, { headers: { Authorization: `Bearer ${token}` } })
+ .then((r) => (r.ok ? r.blob() : null))
+ .then((blob) => {
+ if (blob) {
+ objectUrl = URL.createObjectURL(blob);
+ setBlobUrl(objectUrl);
+ }
+ })
+ .catch(() => {});
+ return () => { if (objectUrl) URL.revokeObjectURL(objectUrl); };
+ }, [url, token]);
+
+ if (isImage) {
+ return (
+
{msg.timestamp ? new Date(msg.timestamp).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }) : ""}
diff --git a/web/app/chat/page.js b/web/app/chat/page.js
index f5b8432f..1957fe78 100644
--- a/web/app/chat/page.js
+++ b/web/app/chat/page.js
@@ -8,6 +8,66 @@ import { createStompClient } from "@/lib/chatSocket";
const API_BASE = "";
+function isImageFilename(name) {
+ return /\.(jpe?g|png|gif|webp|bmp|svg)$/i.test(name || "");
+}
+
+function AttachmentPreview({ url, name, token }) {
+ const [blobUrl, setBlobUrl] = useState(null);
+ const isImage = isImageFilename(name);
+
+ useEffect(() => {
+ if (!url || !token) return;
+ let objectUrl;
+ fetch(url, { headers: { Authorization: `Bearer ${token}` } })
+ .then((r) => (r.ok ? r.blob() : null))
+ .then((blob) => {
+ if (blob) {
+ objectUrl = URL.createObjectURL(blob);
+ setBlobUrl(objectUrl);
+ }
+ })
+ .catch(() => {});
+ return () => { if (objectUrl) URL.revokeObjectURL(objectUrl); };
+ }, [url, token]);
+
+ if (isImage) {
+ return (
+
+ {blobUrl ? (
+

window.open(blobUrl, "_blank")}
+ />
+ ) : (
+
📎 Loading image…
+ )}
+
+ );
+ }
+
+ return (
+
+ );
+}
+
function ChatPage() {
const { user, token, loading: authLoading } = useAuth();
const router = useRouter();
@@ -532,16 +592,7 @@ function ChatPage() {
))}
{msg.attachmentUrl && (
-
+
)}
{msg.timestamp ? new Date(msg.timestamp).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }) : ""}
diff --git a/web/app/globals.css b/web/app/globals.css
index f54ed79b..eab50e73 100644
--- a/web/app/globals.css
+++ b/web/app/globals.css
@@ -683,8 +683,8 @@ body {
}
.info-page {
- min-height: 100vh;
background: linear-gradient(to bottom, #f9f9f9, #ffffff);
+ padding-bottom: 4rem;
}
.info-hero {