Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 31 additions & 10 deletions app/chat/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import React, {
useRef,
useState,
} from "react";
import { ChatWelcomeState } from "@/components/chat-welcome-state";
import { Header } from "@/components/header";
import { Footer } from "@/components/footer";
import { ChatEmptyState } from "@/components/chat-empty-state";
Expand Down Expand Up @@ -170,9 +171,21 @@ export default function ChatPage() {
setIsLoadingRooms(true);
try {
const response = await fetch("/api/rooms");

// Handle non-200 responses gracefully (like the 500 error you're getting)
if (!response.ok) {
console.warn(`Rooms API returned status ${response.status}. Using local preview mode.`);
setChats([]);
setSelectedChatId(null);
return;
}

const data = await response.json();
if (!response.ok || data.error) {
throw new Error(data.error || "Failed to fetch rooms");
if (data.error) {
console.warn("Rooms API returned a custom error:", data.error);
setChats([]);
setSelectedChatId(null);
return;
}

const rawRooms: DBRoom[] = data.rooms || [];
Expand All @@ -196,8 +209,10 @@ export default function ChatPage() {
(currentSelected) => currentSelected || previews[0]?.id || null,
);
} catch (error) {
console.error("Failed to fetch rooms", error);
// This catches the 'TypeError: fetch failed' from your dummy URL completely!
console.warn("Network fetch to rooms failed. Falling back to empty state for preview.");
setChats([]);
setSelectedChatId(null);
} finally {
setIsLoadingRooms(false);
}
Expand Down Expand Up @@ -402,11 +417,11 @@ export default function ChatPage() {
prev.map((chat) =>
chat.id === selectedChatId
? {
...chat,
lastMessage: trimmedMessage,
lastSeen: savedMessage.time,
unreadCount: 0,
}
...chat,
lastMessage: trimmedMessage,
lastSeen: savedMessage.time,
unreadCount: 0,
}
: chat,
),
);
Expand Down Expand Up @@ -600,7 +615,13 @@ export default function ChatPage() {
activeMobileTab === "chats" && "hidden md:flex",
)}
>
{!selectedChat && <ChatEmptyState />}
{/* INTEGRATED WELCOME STATE HERE */}
{!selectedChat && (
<ChatWelcomeState
onCreateGroup={() => console.log("Open Create Group Overlay Trigger")}
onJoinGroup={() => console.log("Open Join Group Code Overlay Trigger")}
/>
)}

{selectedChat && (
<>
Expand Down Expand Up @@ -846,4 +867,4 @@ export default function ChatPage() {
<Footer />
</div>
);
}
}
99 changes: 99 additions & 0 deletions components/chat-welcome-state.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
"use client";

import React from "react";
import { Plus, Users, MessageSquare, Sparkles } from "lucide-react";

interface ChatWelcomeStateProps {
onCreateGroup?: () => void;
onJoinGroup?: () => void;
}

export function ChatWelcomeState({
onCreateGroup = () => console.log("Create group triggered"),
onJoinGroup = () => console.log("Join group triggered"),
}: ChatWelcomeStateProps) {
return (
<div className="w-full h-full flex items-center justify-center relative p-6">
{/* Background Decorative Elements */}
<div className="absolute top-12 left-12 text-primary/10 animate-pulse pointer-events-none">
<Sparkles className="h-16 w-16" />
</div>
<div className="absolute bottom-12 right-12 text-muted-foreground/10 pointer-events-none">
<MessageSquare className="h-24 w-24" />
</div>

{/* Centered Interaction Box */}
<div className="max-w-md w-full text-center space-y-8 z-10 animate-fade-in">

{/* Animated Icon Container */}
<div className="inline-flex p-4 rounded-2xl bg-primary/10 border border-primary/20 text-primary shadow-sm animate-bounce-slow mx-auto">
<MessageSquare className="h-6 w-6" />
</div>

{/* Content Headers */}
<div className="space-y-3">
<h2 className="text-2xl sm:text-3xl font-semibold tracking-tight text-foreground">
Welcome to AnonChat
</h2>
<p className="text-xs text-muted-foreground max-w-xs mx-auto leading-relaxed">
Your curated space for encrypted, real-time group interactions. Select your entry pathway below to begin.
</p>
</div>

{/* CTA Buttons */}
<div className="space-y-3 pt-2">
<button
type="button"
onClick={onCreateGroup}
className="w-full inline-flex cursor-pointer items-center justify-between bg-primary text-primary-foreground h-12 px-5 rounded-xl text-xs font-semibold tracking-wider uppercase shadow-sm transition-all duration-300 group hover:translate-y-[-1px] hover:shadow-md"
>
<span className="flex items-center gap-3">
<Plus className="h-4 w-4 opacity-80 group-hover:scale-110 transition-transform" />
Create New Group
</span>
<span className="text-[10px] opacity-60 font-mono tracking-normal transform translate-x-0 group-hover:translate-x-1 transition-transform">
&rarr;
</span>
</button>

<button
type="button"
onClick={onJoinGroup}
className="w-full cursor-pointer inline-flex items-center justify-between bg-background border border-border/80 text-foreground h-12 px-5 rounded-xl text-xs font-semibold tracking-wider uppercase transition-all duration-300 group hover:translate-y-[-1px] hover:bg-muted/40 hover:border-border"
>
<span className="flex items-center gap-3">
<Users className="h-4 w-4 text-muted-foreground group-hover:text-primary transition-colors" />
Join Existing Group
</span>
<span className="text-[10px] opacity-40 font-mono tracking-normal transform translate-x-0 group-hover:translate-x-1 transition-transform">
&rarr;
</span>
</button>
</div>

{/* Security Disclaimers */}
<p className="text-[10px] text-muted-foreground/60 tracking-wide pt-4">
No tracking profile configurations or personal identity details required.
</p>
</div>

{/* Local Animation Styling CSS Overrides */}
<style jsx global>{`
@keyframes fadeIn {
from { opacity: 0; transform: scale(0.98) translateY(10px); }
to { opacity: 1; transform: scale(1) translateY(0); }
}
@keyframes bounceSlow {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-4px); }
}
.animate-fade-in {
animation: fadeIn 0.5s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
.animate-bounce-slow {
animation: bounceSlow 3s ease-in-out infinite;
}
`}</style>
</div>
);
}
Loading