feat: chat — photo attachments
- Migration 073: attachment_url column in chat_messages - upload.ts: add 'chat' folder to ALLOWED_FOLDERS - chat.ts: accept attachment_url in send message, return it in GET messages - api.ts: attachmentUrl in ChatMessage type, uploadImage() with raw FormData fetch - ChatWidget: paperclip button, file preview thumbnail with remove, image display inline in message bubbles (clickable, opens original), send enabled with image only Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -94,7 +94,7 @@ const chatRoutes: FastifyPluginAsync = async (fastify) => {
|
||||
const limit = Math.min(Number(request.query.limit ?? 50), 100)
|
||||
const { rows } = await db.query(
|
||||
`SELECT m.id, m.room_id, m.sender_id, m.text, m.created_at,
|
||||
m.is_system, m.system_name,
|
||||
m.is_system, m.system_name, m.attachment_url,
|
||||
COALESCE(m.system_name, u.name) AS sender_name,
|
||||
COALESCE(u.role, 'system') AS sender_role
|
||||
FROM chat_messages m
|
||||
@@ -131,14 +131,14 @@ const chatRoutes: FastifyPluginAsync = async (fastify) => {
|
||||
if (roomRows[0]?.type === 'notifications')
|
||||
return reply.code(403).send({ error: 'Cannot post to notifications room' })
|
||||
|
||||
const { text } = request.body
|
||||
if (!text?.trim()) return reply.code(400).send({ error: 'Text required' })
|
||||
const { text, attachment_url } = request.body as { text?: string; attachment_url?: string }
|
||||
if (!text?.trim() && !attachment_url) return reply.code(400).send({ error: 'Text or attachment required' })
|
||||
|
||||
const { rows } = await db.query(
|
||||
`INSERT INTO chat_messages (room_id, hotel_id, sender_id, text)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
RETURNING id, room_id, sender_id, text, created_at`,
|
||||
[roomId, hotelId, request.user.sub, text.trim()],
|
||||
`INSERT INTO chat_messages (room_id, hotel_id, sender_id, text, attachment_url)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING id, room_id, sender_id, text, created_at, attachment_url`,
|
||||
[roomId, hotelId, request.user.sub, text?.trim() ?? '', attachment_url ?? null],
|
||||
)
|
||||
const msg = rows[0]
|
||||
const { rows: uRows } = await db.query('SELECT name, role FROM users WHERE id = $1', [request.user.sub])
|
||||
|
||||
Reference in New Issue
Block a user