Files
juwan-frontend/app/(order)/chat/[id]/page.tsx
T

129 lines
4.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client"
import { ArrowLeft, Lock, Send } from "lucide-react"
import Link from "next/link"
import { use, useState } from "react"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { ScrollArea } from "@/components/ui/scroll-area"
import { mockChatMessages, mockChatSessions } from "@/lib/mock"
import { cn } from "@/lib/utils"
import { useAuthStore } from "@/store/auth"
export default function ChatDetailPage({ params }: { params: Promise<{ id: string }> }) {
const { id } = use(params)
const session = mockChatSessions.find((s) => s.id === id)
const messages = mockChatMessages.filter((m) => m.sessionId === id)
const [input, setInput] = useState("")
const { user } = useAuthStore()
if (!session) {
return (
<div className="container mx-auto py-8 px-4 text-center text-muted-foreground">
</div>
)
}
const currentUserId = user?.id ?? session.participants[0].id
const other = session.participants.find((p) => p.id !== currentUserId) ?? session.participants[1]
return (
<div className="flex flex-col h-[calc(100vh-3.5rem)]">
<div className="border-b px-4 py-3 flex items-center gap-3">
<Link href="/chat" className="text-muted-foreground hover:text-foreground">
<ArrowLeft className="h-5 w-5" />
</Link>
<Avatar className="h-8 w-8">
<AvatarImage src={other.avatar} />
<AvatarFallback>{other.name[0]}</AvatarFallback>
</Avatar>
<div>
<span className="text-sm font-medium">{other.name}</span>
<div className="flex items-center gap-1">
<Badge variant="outline" className="text-[10px] px-1.5 py-0">
{session.type === "order" ? "订单会话" : "咨询会话"}
</Badge>
{session.readonly && (
<span className="text-[10px] text-muted-foreground flex items-center gap-0.5">
<Lock className="h-3 w-3" />
</span>
)}
</div>
</div>
</div>
<ScrollArea className="flex-1 p-4">
<div className="space-y-4 max-w-2xl mx-auto">
{messages.map((msg) => {
if (msg.type === "system") {
return (
<div key={msg.id} className="text-center">
<span className="text-xs text-muted-foreground bg-muted px-2 py-1 rounded">
{msg.content}
</span>
</div>
)
}
const isMine = msg.senderId === currentUserId
return (
<div key={msg.id} className={cn("flex gap-2", isMine && "flex-row-reverse")}>
<Avatar className="h-8 w-8 shrink-0">
<AvatarImage src={msg.senderAvatar} />
<AvatarFallback>{msg.senderName[0]}</AvatarFallback>
</Avatar>
<div className={cn("max-w-[70%]", isMine && "text-right")}>
<p
className={cn(
"inline-block rounded-lg px-3 py-2 text-sm",
isMine ? "bg-primary text-primary-foreground" : "bg-muted",
)}
>
{msg.content}
</p>
<p className="text-[10px] text-muted-foreground mt-1">
{new Date(msg.createdAt).toLocaleTimeString("zh-CN", {
hour: "2-digit",
minute: "2-digit",
})}
</p>
</div>
</div>
)
})}
</div>
</ScrollArea>
{!session.readonly ? (
<div className="border-t p-4">
<form
className="flex gap-2 max-w-2xl mx-auto"
onSubmit={(e) => {
e.preventDefault()
setInput("")
}}
>
<Input
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="输入消息..."
className="flex-1"
/>
<Button type="submit" size="icon" disabled={!input.trim()}>
<Send className="h-4 w-4" />
</Button>
</form>
</div>
) : (
<div className="border-t p-4 text-center text-sm text-muted-foreground">
<Lock className="h-4 w-4 inline mr-1" />
</div>
)}
</div>
)
}