Allsessions
🧩 Syntax:
import React, { useState, useEffect } from "react";
import { Session } from "@/entities/Session";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Search, FileText } from "lucide-react";
import { format } from "date-fns";
import SessionCard from "../components/sessions/SessionCard";
import SessionDetailModal from "../components/sessions/SessionDetailModal";
export default function AllSessions() {
const [sessions, setSessions] = useState([]);
const [filteredSessions, setFilteredSessions] = useState([]);
const [searchQuery, setSearchQuery] = useState("");
const [isLoading, setIsLoading] = useState(true);
const [selectedSession, setSelectedSession] = useState(null);
useEffect(() => {
loadSessions();
}, []);
useEffect(() => {
if (searchQuery) {
const filtered = sessions.filter(session =>
session.client_name.toLowerCase().includes(searchQuery.toLowerCase()) ||
session.presenting_concerns?.toLowerCase().includes(searchQuery.toLowerCase()) ||
session.session_notes?.toLowerCase().includes(searchQuery.toLowerCase())
);
setFilteredSessions(filtered);
} else {
setFilteredSessions(sessions);
}
}, [searchQuery, sessions]);
const loadSessions = async () => {
setIsLoading(true);
const data = await Session.list("-session_date");
setSessions(data);
setFilteredSessions(data);
setIsLoading(false);
};
const groupedSessions = {};
filteredSessions.forEach(session => {
if (!groupedSessions[session.client_name]) {
groupedSessions[session.client_name] = [];
}
groupedSessions[session.client_name].push(session);
});
return (
<div className="min-h-screen p-6 md:p-8">
<div className="max-w-7xl mx-auto">
<div className="mb-8">
<h1 className="text-3xl md:text-4xl font-bold text-gray-900 mb-2">All Sessions</h1>
<p className="text-gray-600">Browse and search through your session notes</p>
</div>
<Card className="mb-8 shadow-lg border-0 bg-white/80 backdrop-blur-sm">
<CardContent className="p-6">
<div className="relative">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-5 h-5" />
<Input
placeholder="Search by client name, concerns, or notes..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="pl-10 h-12 text-base"
/>
</div>
</CardContent>
</Card>
{isLoading ? (
<div className="grid gap-6">
{[1, 2, 3].map(i => (
<Card key={i} className="animate-pulse">
<CardHeader>
<div className="h-6 bg-gray-200 rounded w-1/3"></div>
</CardHeader>
<CardContent>
<div className="h-4 bg-gray-200 rounded w-full mb-2"></div>
<div className="h-4 bg-gray-200 rounded w-2/3"></div>
</CardContent>
</Card>
))}
</div>
) : Object.keys(groupedSessions).length === 0 ? (
<Card className="shadow-lg border-0 bg-white/80 backdrop-blur-sm">
<CardContent className="p-12 text-center">
<FileText className="w-16 h-16 mx-auto mb-4 text-gray-300" />
<h3 className="text-xl font-semibold text-gray-900 mb-2">No sessions found</h3>
<p className="text-gray-600">
{searchQuery ? "Try adjusting your search" : "Start by creating your first session note"}
</p>
</CardContent>
</Card>
) : (
<div className="space-y-8">
{Object.entries(groupedSessions).map(([clientName, clientSessions]) => (
<div key={clientName}>
<h2 className="text-2xl font-bold text-gray-900 mb-4 flex items-center gap-2">
<div className="w-8 h-8 bg-gradient-to-br from-[#8ba888] to-[#a8a5c9] rounded-full flex items-center justify-center text-white text-sm font-semibold">
{clientName[0].toUpperCase()}
</div>
{clientName}
<span className="text-sm font-normal text-gray-500 ml-2">
({clientSessions.length} {clientSessions.length === 1 ? 'session' : 'sessions'})
</span>
</h2>
<div className="grid gap-4">
{clientSessions.map(session => (
<SessionCard
key={session.id}
session={session}
onClick={() => setSelectedSession(session)}
/>
))}
</div>
</div>
))}
</div>
)}
{selectedSession && (
<SessionDetailModal
session={selectedSession}
onClose={() => setSelectedSession(null)}
/>
)}
</div>
</div>
);
}