feat(timesheet): improve empty state copy and layout

This commit is contained in:
2026-04-29 12:17:08 +03:30
parent a2bc1aa91f
commit 4ac0fd22e5
3 changed files with 497 additions and 478 deletions

View File

@@ -411,6 +411,8 @@ export const en = {
orderingNewest: "Newest first", orderingNewest: "Newest first",
orderingOldest: "Oldest first", orderingOldest: "Oldest first",
emptyState: "No time entries found", emptyState: "No time entries found",
emptyStateDescription: "Start the timer or add a manual entry to get started.",
noEntriesSearch: "Try adjusting your search query or filters.",
emptyDescription: "No description", emptyDescription: "No description",
createTitle: "Add Time Entry", createTitle: "Add Time Entry",
startTitle: "Start Timer", startTitle: "Start Timer",

View File

@@ -409,6 +409,8 @@ export const fa = {
orderingOldest: "قدیمی‌ترین", orderingOldest: "قدیمی‌ترین",
emptyState: "ورودی زمانی یافت نشد", emptyState: "ورودی زمانی یافت نشد",
emptyDescription: "بدون توضیح", emptyDescription: "بدون توضیح",
emptyStateDescription: "برای شروع، تایمر را اجرا کنید یا یک ورودی دستی اضافه کنید.",
noEntriesSearch: "عبارت جست‌وجو یا فیلترهای خود را تغییر دهید.",
createTitle: "افزودن ورودی زمان", createTitle: "افزودن ورودی زمان",
startTitle: "شروع تایمر", startTitle: "شروع تایمر",
editTitle: "ویرایش ورودی زمان", editTitle: "ویرایش ورودی زمان",

View File

@@ -18,6 +18,7 @@ import {
} from "../api/timeEntries"; } from "../api/timeEntries";
import { getTags, type Tag } from "../api/tags"; import { getTags, type Tag } from "../api/tags";
import { Modal } from "../components/Modal"; import { Modal } from "../components/Modal";
import EmptyStateCard from "../components/EmptyStateCard";
import { InfiniteScroll } from "../components/InfiniteScroll"; import { InfiniteScroll } from "../components/InfiniteScroll";
import TimesheetFilterBar, { type TimeEntryFilters } from "../components/timesheet/TimesheetFilterBar"; import TimesheetFilterBar, { type TimeEntryFilters } from "../components/timesheet/TimesheetFilterBar";
import JalaliDatePicker from "../components/ui/JalaliDatePicker"; import JalaliDatePicker from "../components/ui/JalaliDatePicker";
@@ -2066,6 +2067,14 @@ export default function Timesheet() {
}), }),
[searchParams], [searchParams],
); );
const hasActiveHistoryFilters = Boolean(
searchQuery ||
filters.projectId ||
filters.clientId ||
filters.tagIds.length ||
filters.startedAfter ||
filters.startedBefore,
);
const [hasMoreHistory, setHasMoreHistory] = useState(false); const [hasMoreHistory, setHasMoreHistory] = useState(false);
const [nextOffset, setNextOffset] = useState<number | null>(0); const [nextOffset, setNextOffset] = useState<number | null>(0);
const [limit] = useState(20); const [limit] = useState(20);
@@ -2949,10 +2958,16 @@ export default function Timesheet() {
))} ))}
{groupedHistory.length === 0 && ( {groupedHistory.length === 0 && (
<div className="flex flex-col items-center justify-center border-2 border-dashed border-slate-200 bg-white/60 py-16 text-slate-500 dark:border-slate-700 dark:bg-slate-900/60 dark:text-slate-400"> <EmptyStateCard
<Clock3 className="mb-3 h-10 w-10" /> icon={Clock3}
<p>{t.timesheet?.emptyState || "No time entries found"}</p> title={t.timesheet?.emptyState || "No time entries found"}
</div> description={
hasActiveHistoryFilters
? t.timesheet?.noEntriesSearch || "Try adjusting your search query or filters."
: t.timesheet?.emptyStateDescription || "Start the timer to get started."
}
className="min-h-[50vh] border-slate-200 bg-white/60 py-16 dark:border-slate-700 dark:bg-slate-900/60"
/>
)} )}
</div> </div>
</InfiniteScroll> </InfiniteScroll>