feat(ui): improve ui for test, drills and htm screens

This commit is contained in:
shafin-r
2026-02-21 02:04:50 +06:00
parent 76d2108aec
commit 65dbe99647
10 changed files with 3325 additions and 1464 deletions

View File

@ -36,7 +36,7 @@ const STYLES = `
.home-screen {
min-height: 100vh;
background: #fffbf4;
font-family: 'Satoshi', sans-serif;
font-family: 'Nunito', sans-serif;
position: relative;
overflow-x: hidden;
}
@ -248,6 +248,30 @@ const STYLES = `
.h-tip-icon { flex-shrink:0;margin-top:1px; }
.h-tip-text { font-size:0.85rem;font-weight:700;color:#374151;line-height:1.4; }
/* ── Load more ── */
.h-load-more-btn {
width: 100%; margin-top: 0.25rem;
padding: 0.75rem;
background: white; border: 2.5px solid #f3f4f6;
border-radius: 100px; cursor: pointer;
font-family: 'Nunito', sans-serif;
font-size: 0.82rem; font-weight: 800; color: #9ca3af;
display: flex; align-items: center; justify-content: center; gap: 0.4rem;
box-shadow: 0 3px 10px rgba(0,0,0,0.04);
transition: all 0.2s ease;
}
.h-load-more-btn:hover { border-color: #c4b5fd; color: #a855f7; background: #fdf4ff; transform: translateY(-1px); box-shadow: 0 6px 14px rgba(0,0,0,0.06); }
.h-load-more-btn:active { transform: translateY(1px); }
.h-sheet-count {
text-align: center;
font-family: 'Nunito Sans', sans-serif;
font-size: 0.72rem; font-weight: 600; color: #d1d5db;
margin-top: 0.5rem;
}
.h-sheet-count span { font-weight: 800; color: #9ca3af; }
@keyframes hPopIn {
from{opacity:0;transform:scale(0.92) translateY(10px);}
to{opacity:1;transform:scale(1) translateY(0);}
@ -305,6 +329,8 @@ const TIPS = [
];
// ─── Main component ───────────────────────────────────────────────────────────
const PAGE_SIZE = 2;
export const Home = () => {
const user = useAuthStore((state) => state.user);
const navigate = useNavigate();
@ -319,6 +345,7 @@ export const Home = () => {
>("all");
const [isSearchOpen, setIsSearchOpen] = useState(false);
const [searchQuery, setSearchQuery] = useState("");
const [visibleCount, setVisibleCount] = useState(PAGE_SIZE);
useEffect(() => {
const sort = (sheets: PracticeSheet[]) => {
@ -352,13 +379,22 @@ export const Home = () => {
const handleStart = (id: string) => navigate(`/student/practice/${id}`);
const tabSheets =
const allTabSheets =
activeTab === "all"
? practiceSheets
: activeTab === "NOT_STARTED"
? notStartedSheets
: completedSheets;
const tabSheets = allTabSheets.slice(0, visibleCount);
const hasMore = visibleCount < allTabSheets.length;
const remaining = allTabSheets.length - visibleCount;
const handleTabChange = (tab: "all" | "NOT_STARTED" | "COMPLETED") => {
setActiveTab(tab);
setVisibleCount(PAGE_SIZE);
};
const greeting =
new Date().getHours() < 12
? "Good morning"
@ -414,9 +450,9 @@ export const Home = () => {
{user?.name?.slice(0, 1)}
</AvatarFallback>
</Avatar>
<div className="space-y-1">
<div>
<p className="home-user-name">
{greeting}, {user?.name?.split(" ")[0] || "Student"}
{greeting}, {user?.name?.split(" ")[0] || "Student"} 👋
</p>
<p className="home-user-role">
{user?.role === "STUDENT"
@ -513,7 +549,7 @@ export const Home = () => {
<button
key={tab}
className={`h-tab-btn${activeTab === tab ? " active" : ""}`}
onClick={() => setActiveTab(tab)}
onClick={() => handleTabChange(tab)}
>
{tab === "all"
? "All"
@ -524,12 +560,30 @@ export const Home = () => {
))}
</div>
{tabSheets.length > 0 ? (
<div className="h-sheet-grid">
{tabSheets.map((sheet) => (
<SheetCard key={sheet.id} sheet={sheet} onStart={handleStart} />
))}
</div>
{allTabSheets.length > 0 ? (
<>
<div className="h-sheet-grid">
{tabSheets.map((sheet) => (
<SheetCard
key={sheet.id}
sheet={sheet}
onStart={handleStart}
/>
))}
</div>
{hasMore ? (
<button
className="h-load-more-btn"
onClick={() => setVisibleCount((c) => c + PAGE_SIZE)}
>
Show {Math.min(remaining, PAGE_SIZE)} more
</button>
) : allTabSheets.length > PAGE_SIZE ? (
<p className="h-sheet-count">
Showing all <span>{allTabSheets.length}</span> sheets
</p>
) : null}
</>
) : (
<div className="h-empty">
<span className="h-empty-emoji">🔍</span>