feat(library): enhance ui & ux

This commit is contained in:
ItzCrazyKns
2025-12-24 15:47:56 +05:30
parent 0a9641a110
commit 452180356d

View File

@@ -1,8 +1,8 @@
'use client'; 'use client';
import DeleteChat from '@/components/DeleteChat'; import DeleteChat from '@/components/DeleteChat';
import { cn, formatTimeDifference } from '@/lib/utils'; import { formatTimeDifference } from '@/lib/utils';
import { BookOpenText, ClockIcon, Delete, ScanEye } from 'lucide-react'; import { BookOpenText, ClockIcon, FileText, Globe2Icon } from 'lucide-react';
import Link from 'next/link'; import Link from 'next/link';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
@@ -10,7 +10,8 @@ export interface Chat {
id: string; id: string;
title: string; title: string;
createdAt: string; createdAt: string;
focusMode: string; sources: string[];
files: { fileId: string; name: string }[];
} }
const Page = () => { const Page = () => {
@@ -37,8 +38,38 @@ const Page = () => {
fetchChats(); fetchChats();
}, []); }, []);
return loading ? ( return (
<div className="flex flex-row items-center justify-center min-h-screen"> <div>
<div className="flex flex-col pt-10 border-b border-light-200/20 dark:border-dark-200/20 pb-6 px-2">
<div className="flex flex-col lg:flex-row lg:items-end lg:justify-between gap-3">
<div className="flex items-center justify-center">
<BookOpenText size={45} className="mb-2.5" />
<div className="flex flex-col">
<h1
className="text-5xl font-normal p-2 pb-0"
style={{ fontFamily: 'PP Editorial, serif' }}
>
Library
</h1>
<div className="px-2 text-sm text-black/60 dark:text-white/60 text-center lg:text-left">
Past chats, sources, and uploads.
</div>
</div>
</div>
<div className="flex items-center justify-center lg:justify-end gap-2 text-xs text-black/60 dark:text-white/60">
<span className="inline-flex items-center gap-1 rounded-full border border-black/20 dark:border-white/20 px-2 py-0.5">
<BookOpenText size={14} />
{loading
? 'Loading…'
: `${chats.length} ${chats.length === 1 ? 'chat' : 'chats'}`}
</span>
</div>
</div>
</div>
{loading ? (
<div className="flex flex-row items-center justify-center min-h-[60vh]">
<svg <svg
aria-hidden="true" aria-hidden="true"
className="w-8 h-8 text-light-200 fill-light-secondary dark:text-[#202020] animate-spin dark:fill-[#ffffff3b]" className="w-8 h-8 text-light-200 fill-light-secondary dark:text-[#202020] animate-spin dark:fill-[#ffffff3b]"
@@ -56,47 +87,56 @@ const Page = () => {
/> />
</svg> </svg>
</div> </div>
) : ( ) : chats.length === 0 ? (
<div> <div className="flex flex-col items-center justify-center min-h-[70vh] px-2 text-center">
<div className="flex flex-col pt-4"> <div className="flex items-center justify-center w-12 h-12 rounded-2xl border border-light-200 dark:border-dark-200 bg-light-secondary dark:bg-dark-secondary">
<div className="flex items-center"> <BookOpenText className="text-black/70 dark:text-white/70" />
<BookOpenText />
<h1 className="text-3xl font-medium p-2">Library</h1>
</div> </div>
<hr className="border-t border-[#2B2C2C] my-4 w-full" /> <p className="mt-2 text-black/70 dark:text-white/70 text-sm">
</div>
{chats.length === 0 && (
<div className="flex flex-row items-center justify-center min-h-screen">
<p className="text-black/70 dark:text-white/70 text-sm">
No chats found. No chats found.
</p> </p>
<p className="mt-1 text-black/70 dark:text-white/70 text-sm">
<Link href="/" className="text-sky-400">
Start a new chat
</Link>{' '}
to see it listed here.
</p>
</div> </div>
)} ) : (
{chats.length > 0 && ( <div className="pt-6 pb-28 px-2">
<div className="flex flex-col pb-20 lg:pb-2"> <div className="rounded-2xl border border-light-200 dark:border-dark-200 overflow-hidden bg-light-primary dark:bg-dark-primary">
{chats.map((chat, i) => ( {chats.map((chat, index) => {
const sourcesLabel =
chat.sources.length === 0
? null
: chat.sources.length <= 2
? chat.sources
.map((s) => s.charAt(0).toUpperCase() + s.slice(1))
.join(', ')
: `${chat.sources
.slice(0, 2)
.map((s) => s.charAt(0).toUpperCase() + s.slice(1))
.join(', ')} + ${chat.sources.length - 2}`;
return (
<div <div
className={cn( key={chat.id}
'flex flex-col space-y-4 py-6', className={
i !== chats.length - 1 'group flex flex-col gap-2 p-4 hover:bg-light-secondary dark:hover:bg-dark-secondary transition-colors duration-200 ' +
? 'border-b border-white-200 dark:border-dark-200' (index !== chats.length - 1
: '', ? 'border-b border-light-200 dark:border-dark-200'
)} : '')
key={i} }
> >
<div className="flex items-start justify-between gap-3">
<Link <Link
href={`/c/${chat.id}`} href={`/c/${chat.id}`}
className="text-black dark:text-white lg:text-xl font-medium truncate transition duration-200 hover:text-[#24A0ED] dark:hover:text-[#24A0ED] cursor-pointer" className="flex-1 text-black dark:text-white text-base lg:text-lg font-medium leading-snug line-clamp-2 group-hover:text-[#24A0ED] transition duration-200"
title={chat.title}
> >
{chat.title} {chat.title}
</Link> </Link>
<div className="flex flex-row items-center justify-between w-full"> <div className="pt-0.5 shrink-0">
<div className="flex flex-row items-center space-x-1 lg:space-x-1.5 text-black/70 dark:text-white/70">
<ClockIcon size={15} />
<p className="text-xs">
{formatTimeDifference(new Date(), chat.createdAt)} Ago
</p>
</div>
<DeleteChat <DeleteChat
chatId={chat.id} chatId={chat.id}
chats={chats} chats={chats}
@@ -104,7 +144,31 @@ const Page = () => {
/> />
</div> </div>
</div> </div>
))}
<div className="flex flex-wrap items-center gap-2 text-black/70 dark:text-white/70">
<span className="inline-flex items-center gap-1 text-xs">
<ClockIcon size={14} />
{formatTimeDifference(new Date(), chat.createdAt)} Ago
</span>
{sourcesLabel && (
<span className="inline-flex items-center gap-1 text-xs border border-black/20 dark:border-white/20 rounded-full px-2 py-0.5">
<Globe2Icon size={14} />
{sourcesLabel}
</span>
)}
{chat.files.length > 0 && (
<span className="inline-flex items-center gap-1 text-xs border border-black/20 dark:border-white/20 rounded-full px-2 py-0.5">
<FileText size={14} />
{chat.files.length}{' '}
{chat.files.length === 1 ? 'file' : 'files'}
</span>
)}
</div>
</div>
);
})}
</div>
</div> </div>
)} )}
</div> </div>