ui phase 10

This commit is contained in:
hamid
2026-07-19 17:13:32 +03:30
parent b638e25a0e
commit b4b8c9ea79
48 changed files with 1643 additions and 290 deletions
+35
View File
@@ -41,3 +41,38 @@ export function formatShamsiDateTime(iso: string | Date, locale: string = 'fa'):
export function formatShamsiMonthYear(iso: string | Date, locale: string = 'fa'): string {
return formatShamsiDate(iso, locale, { year: 'numeric', month: 'long' });
}
/** Time only (hh:mm) — a chat bubble's stamp once its date lives on a separator instead (§3.2). */
export function formatShamsiTime(iso: string | Date, locale: string = 'fa'): string {
return formatShamsiDate(iso, locale, { hour: '2-digit', minute: '2-digit' });
}
/**
* Whole calendar days between two timestamps, comparing the **formatted date string** (not raw ms
* subtraction, which is wrong across a DST/timezone boundary) — two timestamps format identically iff
* they fall on the same calendar day in the active calendar system.
*/
function isSameCalendarDay(a: Date, b: Date, locale: string): boolean {
return formatShamsiDate(a, locale) === formatShamsiDate(b, locale);
}
/**
* A chat-style day-separator label: the caller's «امروز»/«دیروز» for the last two calendar days, else the
* plain Shamsi date (e.g. «۲۵ تیر ۱۴۰۵»). Calendar-agnostic — it never does its own Jalali arithmetic,
* only compares already-formatted date strings (see `isSameCalendarDay`).
*/
export function formatDaySeparator(
iso: string | Date,
locale: string,
todayLabel: string,
yesterdayLabel: string,
): string {
const date = iso instanceof Date ? iso : new Date(iso);
if (Number.isNaN(date.getTime())) return '';
const now = new Date();
if (isSameCalendarDay(date, now, locale)) return todayLabel;
const yesterday = new Date(now);
yesterday.setDate(yesterday.getDate() - 1);
if (isSameCalendarDay(date, yesterday, locale)) return yesterdayLabel;
return formatShamsiDate(date, locale);
}