style: run prettier on entire codebase
This commit is contained in:
@@ -1,102 +1,109 @@
|
||||
let showSessionExpiredAlert = false
|
||||
let showLogoutAlert = false
|
||||
let getTokenFn: (() => string | null) | null = null
|
||||
let refreshFn: (() => Promise<boolean>) | null = null
|
||||
let refreshPromise: Promise<boolean> | null = null
|
||||
let showSessionExpiredAlert = false;
|
||||
let showLogoutAlert = false;
|
||||
let getTokenFn: (() => string | null) | null = null;
|
||||
let refreshFn: (() => Promise<boolean>) | null = null;
|
||||
let refreshPromise: Promise<boolean> | null = null;
|
||||
|
||||
export const shouldShowSessionExpiredAlert = (): boolean => {
|
||||
if (showSessionExpiredAlert) {
|
||||
showSessionExpiredAlert = false
|
||||
return true
|
||||
showSessionExpiredAlert = false;
|
||||
return true;
|
||||
}
|
||||
return false
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
export const setSessionExpired = (): void => {
|
||||
showSessionExpiredAlert = true
|
||||
}
|
||||
showSessionExpiredAlert = true;
|
||||
};
|
||||
|
||||
export const shouldShowLogoutAlert = (): boolean => {
|
||||
if (showLogoutAlert) {
|
||||
showLogoutAlert = false
|
||||
return true
|
||||
showLogoutAlert = false;
|
||||
return true;
|
||||
}
|
||||
return false
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
export const setLogoutAlert = (): void => {
|
||||
showLogoutAlert = true
|
||||
}
|
||||
showLogoutAlert = true;
|
||||
};
|
||||
|
||||
export const setTokenGetter = (fn: () => string | null): void => {
|
||||
getTokenFn = fn
|
||||
}
|
||||
getTokenFn = fn;
|
||||
};
|
||||
|
||||
export const setRefreshFn = (fn: () => Promise<boolean>): void => {
|
||||
refreshFn = fn
|
||||
}
|
||||
refreshFn = fn;
|
||||
};
|
||||
|
||||
export const apiFetch = async (url: string, options: RequestInit = {}): Promise<Response> => {
|
||||
let token: string | null = null
|
||||
export const apiFetch = async (
|
||||
url: string,
|
||||
options: RequestInit = {},
|
||||
): Promise<Response> => {
|
||||
let token: string | null = null;
|
||||
try {
|
||||
token = getTokenFn ? getTokenFn() : null
|
||||
token = getTokenFn ? getTokenFn() : null;
|
||||
} catch {
|
||||
// token retrieval failed
|
||||
}
|
||||
|
||||
const headers: Record<string, string> = {
|
||||
...(options.headers as Record<string, string>),
|
||||
}
|
||||
};
|
||||
|
||||
if (!headers['Content-Type'] && options.body && !(options.body instanceof FormData)) {
|
||||
headers['Content-Type'] = 'application/json'
|
||||
if (
|
||||
!headers["Content-Type"] &&
|
||||
options.body &&
|
||||
!(options.body instanceof FormData)
|
||||
) {
|
||||
headers["Content-Type"] = "application/json";
|
||||
}
|
||||
|
||||
if (token) {
|
||||
headers['Authorization'] = `Bearer ${token}`
|
||||
headers["Authorization"] = `Bearer ${token}`;
|
||||
}
|
||||
|
||||
let response = await fetch(url, {
|
||||
...options,
|
||||
headers,
|
||||
credentials: 'include',
|
||||
})
|
||||
credentials: "include",
|
||||
});
|
||||
|
||||
if (response.status === 401 && refreshFn) {
|
||||
try {
|
||||
if (!refreshPromise) {
|
||||
refreshPromise = refreshFn().finally(() => {
|
||||
refreshPromise = null
|
||||
})
|
||||
refreshPromise = null;
|
||||
});
|
||||
}
|
||||
const refreshed = await refreshPromise
|
||||
const refreshed = await refreshPromise;
|
||||
if (refreshed) {
|
||||
token = getTokenFn ? getTokenFn() : null
|
||||
token = getTokenFn ? getTokenFn() : null;
|
||||
if (token) {
|
||||
headers['Authorization'] = `Bearer ${token}`
|
||||
headers["Authorization"] = `Bearer ${token}`;
|
||||
}
|
||||
response = await fetch(url, {
|
||||
...options,
|
||||
headers,
|
||||
credentials: 'include',
|
||||
})
|
||||
credentials: "include",
|
||||
});
|
||||
} else {
|
||||
setSessionExpired()
|
||||
setSessionExpired();
|
||||
}
|
||||
} catch {
|
||||
setSessionExpired()
|
||||
setSessionExpired();
|
||||
}
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
return response;
|
||||
};
|
||||
|
||||
export const getAccessToken = (): string | null => {
|
||||
try {
|
||||
return getTokenFn ? getTokenFn() : null
|
||||
return getTokenFn ? getTokenFn() : null;
|
||||
} catch {
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default apiFetch
|
||||
export default apiFetch;
|
||||
|
||||
@@ -1,169 +1,189 @@
|
||||
interface AttendanceRecord {
|
||||
arrival_time?: string | null
|
||||
departure_time?: string | null
|
||||
break_start?: string | null
|
||||
break_end?: string | null
|
||||
leave_type?: string
|
||||
leave_hours?: number
|
||||
shift_date?: string
|
||||
notes?: string
|
||||
arrival_time?: string | null;
|
||||
departure_time?: string | null;
|
||||
break_start?: string | null;
|
||||
break_end?: string | null;
|
||||
leave_type?: string;
|
||||
leave_hours?: number;
|
||||
shift_date?: string;
|
||||
notes?: string;
|
||||
project_logs?: Array<{
|
||||
id?: number
|
||||
project_id?: number
|
||||
project_name?: string
|
||||
started_at?: string
|
||||
ended_at?: string | null
|
||||
hours?: string | number | null
|
||||
minutes?: string | number | null
|
||||
}>
|
||||
id?: number;
|
||||
project_id?: number;
|
||||
project_name?: string;
|
||||
started_at?: string;
|
||||
ended_at?: string | null;
|
||||
hours?: string | number | null;
|
||||
minutes?: string | number | null;
|
||||
}>;
|
||||
}
|
||||
|
||||
export const formatDate = (dateStr: string | null | undefined): string => {
|
||||
if (!dateStr) return '—'
|
||||
const d = new Date(dateStr)
|
||||
return d.toLocaleDateString('cs-CZ')
|
||||
}
|
||||
if (!dateStr) return "—";
|
||||
const d = new Date(dateStr);
|
||||
return d.toLocaleDateString("cs-CZ");
|
||||
};
|
||||
|
||||
/** Extract time as HH:MM from a datetime string without timezone conversion */
|
||||
const extractTime = (datetime: string): string => {
|
||||
// Try ISO format: "2026-03-23T08:00:00.000Z" or "2026-03-23T08:00:00"
|
||||
const tMatch = datetime.match(/T(\d{2}):(\d{2})/)
|
||||
if (tMatch) return `${tMatch[1]}:${tMatch[2]}`
|
||||
const tMatch = datetime.match(/T(\d{2}):(\d{2})/);
|
||||
if (tMatch) return `${tMatch[1]}:${tMatch[2]}`;
|
||||
// Try space format: "2026-03-23 08:00:00"
|
||||
const sMatch = datetime.match(/\s(\d{2}):(\d{2})/)
|
||||
if (sMatch) return `${sMatch[1]}:${sMatch[2]}`
|
||||
const sMatch = datetime.match(/\s(\d{2}):(\d{2})/);
|
||||
if (sMatch) return `${sMatch[1]}:${sMatch[2]}`;
|
||||
// Fallback: try parsing time-only "08:00"
|
||||
const hMatch = datetime.match(/^(\d{2}):(\d{2})/)
|
||||
if (hMatch) return `${hMatch[1]}:${hMatch[2]}`
|
||||
return datetime
|
||||
}
|
||||
const hMatch = datetime.match(/^(\d{2}):(\d{2})/);
|
||||
if (hMatch) return `${hMatch[1]}:${hMatch[2]}`;
|
||||
return datetime;
|
||||
};
|
||||
|
||||
export const formatDatetime = (datetime: string | null | undefined): string => {
|
||||
if (!datetime) return '—'
|
||||
if (!datetime) return "—";
|
||||
// Extract date part without timezone conversion
|
||||
const dMatch = datetime.match(/(\d{4})-(\d{2})-(\d{2})/)
|
||||
const datePart = dMatch ? `${parseInt(dMatch[3])}.${parseInt(dMatch[2])}.` : ''
|
||||
return `${datePart} ${extractTime(datetime)}`
|
||||
}
|
||||
const dMatch = datetime.match(/(\d{4})-(\d{2})-(\d{2})/);
|
||||
const datePart = dMatch
|
||||
? `${parseInt(dMatch[3])}.${parseInt(dMatch[2])}.`
|
||||
: "";
|
||||
return `${datePart} ${extractTime(datetime)}`;
|
||||
};
|
||||
|
||||
export const formatTime = (datetime: string | null | undefined): string => {
|
||||
if (!datetime) return '—'
|
||||
return extractTime(datetime)
|
||||
}
|
||||
if (!datetime) return "—";
|
||||
return extractTime(datetime);
|
||||
};
|
||||
|
||||
export const calculateWorkMinutes = (record: AttendanceRecord): number => {
|
||||
if (!record.arrival_time || !record.departure_time) return 0
|
||||
const arrival = new Date(record.arrival_time).getTime()
|
||||
const departure = new Date(record.departure_time).getTime()
|
||||
let minutes = (departure - arrival) / 60000
|
||||
if (!record.arrival_time || !record.departure_time) return 0;
|
||||
const arrival = new Date(record.arrival_time).getTime();
|
||||
const departure = new Date(record.departure_time).getTime();
|
||||
let minutes = (departure - arrival) / 60000;
|
||||
|
||||
if (record.break_start && record.break_end) {
|
||||
const breakStart = new Date(record.break_start).getTime()
|
||||
const breakEnd = new Date(record.break_end).getTime()
|
||||
minutes -= (breakEnd - breakStart) / 60000
|
||||
const breakStart = new Date(record.break_start).getTime();
|
||||
const breakEnd = new Date(record.break_end).getTime();
|
||||
minutes -= (breakEnd - breakStart) / 60000;
|
||||
}
|
||||
|
||||
return Math.max(0, Math.floor(minutes))
|
||||
}
|
||||
return Math.max(0, Math.floor(minutes));
|
||||
};
|
||||
|
||||
export const formatMinutes = (minutes: number, withUnit = false): string => {
|
||||
const h = Math.floor(minutes / 60)
|
||||
const m = minutes % 60
|
||||
return `${h}:${String(m).padStart(2, '0')}${withUnit ? ' h' : ''}`
|
||||
}
|
||||
const h = Math.floor(minutes / 60);
|
||||
const m = minutes % 60;
|
||||
return `${h}:${String(m).padStart(2, "0")}${withUnit ? " h" : ""}`;
|
||||
};
|
||||
|
||||
export const getLeaveTypeName = (type: string): string => {
|
||||
const types: Record<string, string> = {
|
||||
work: 'Práce',
|
||||
vacation: 'Dovolená',
|
||||
sick: 'Nemoc',
|
||||
holiday: 'Svátek',
|
||||
unpaid: 'Neplacené volno',
|
||||
}
|
||||
return types[type] || 'Práce'
|
||||
}
|
||||
work: "Práce",
|
||||
vacation: "Dovolená",
|
||||
sick: "Nemoc",
|
||||
holiday: "Svátek",
|
||||
unpaid: "Neplacené volno",
|
||||
};
|
||||
return types[type] || "Práce";
|
||||
};
|
||||
|
||||
export const getLeaveTypeBadgeClass = (type: string): string => {
|
||||
const classes: Record<string, string> = {
|
||||
vacation: 'badge-vacation',
|
||||
sick: 'badge-sick',
|
||||
holiday: 'badge-holiday',
|
||||
unpaid: 'badge-unpaid',
|
||||
}
|
||||
return classes[type] || ''
|
||||
}
|
||||
vacation: "badge-vacation",
|
||||
sick: "badge-sick",
|
||||
holiday: "badge-holiday",
|
||||
unpaid: "badge-unpaid",
|
||||
};
|
||||
return classes[type] || "";
|
||||
};
|
||||
|
||||
export const getDatePart = (datetime: string | null | undefined): string => {
|
||||
if (!datetime) return ''
|
||||
if (datetime.includes('T')) {
|
||||
return datetime.split('T')[0]
|
||||
if (!datetime) return "";
|
||||
if (datetime.includes("T")) {
|
||||
return datetime.split("T")[0];
|
||||
}
|
||||
return datetime.split(' ')[0]
|
||||
}
|
||||
return datetime.split(" ")[0];
|
||||
};
|
||||
|
||||
export const getTimePart = (datetime: string | null | undefined): string => {
|
||||
if (!datetime) return ''
|
||||
const d = new Date(datetime)
|
||||
return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`
|
||||
}
|
||||
if (!datetime) return "";
|
||||
const d = new Date(datetime);
|
||||
return `${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`;
|
||||
};
|
||||
|
||||
export const calcProjectMinutesTotal = (logs: Array<{ project_id?: number; hours?: string | number; minutes?: string | number }>): number => {
|
||||
return logs.filter(l => l.project_id).reduce((sum, l) => {
|
||||
return sum + (parseInt(String(l.hours)) || 0) * 60 + (parseInt(String(l.minutes)) || 0)
|
||||
}, 0)
|
||||
}
|
||||
export const calcProjectMinutesTotal = (
|
||||
logs: Array<{
|
||||
project_id?: number;
|
||||
hours?: string | number;
|
||||
minutes?: string | number;
|
||||
}>,
|
||||
): number => {
|
||||
return logs
|
||||
.filter((l) => l.project_id)
|
||||
.reduce((sum, l) => {
|
||||
return (
|
||||
sum +
|
||||
(parseInt(String(l.hours)) || 0) * 60 +
|
||||
(parseInt(String(l.minutes)) || 0)
|
||||
);
|
||||
}, 0);
|
||||
};
|
||||
|
||||
interface ShiftForm {
|
||||
arrival_time?: string
|
||||
departure_time?: string
|
||||
arrival_date?: string
|
||||
departure_date?: string
|
||||
break_start_time?: string
|
||||
break_end_time?: string
|
||||
break_start_date?: string
|
||||
break_end_date?: string
|
||||
arrival_time?: string;
|
||||
departure_time?: string;
|
||||
arrival_date?: string;
|
||||
departure_date?: string;
|
||||
break_start_time?: string;
|
||||
break_end_time?: string;
|
||||
break_start_date?: string;
|
||||
break_end_date?: string;
|
||||
}
|
||||
|
||||
export const calcFormWorkMinutes = (form: ShiftForm): number => {
|
||||
if (!form.arrival_time || !form.departure_time) return 0
|
||||
const arrivalStr = `${form.arrival_date}T${form.arrival_time}`
|
||||
const departureStr = `${form.departure_date}T${form.departure_time}`
|
||||
let mins = (new Date(departureStr).getTime() - new Date(arrivalStr).getTime()) / 60000
|
||||
if (!form.arrival_time || !form.departure_time) return 0;
|
||||
const arrivalStr = `${form.arrival_date}T${form.arrival_time}`;
|
||||
const departureStr = `${form.departure_date}T${form.departure_time}`;
|
||||
let mins =
|
||||
(new Date(departureStr).getTime() - new Date(arrivalStr).getTime()) / 60000;
|
||||
if (form.break_start_time && form.break_end_time) {
|
||||
const bsStr = `${form.break_start_date}T${form.break_start_time}`
|
||||
const beStr = `${form.break_end_date}T${form.break_end_time}`
|
||||
mins -= (new Date(beStr).getTime() - new Date(bsStr).getTime()) / 60000
|
||||
const bsStr = `${form.break_start_date}T${form.break_start_time}`;
|
||||
const beStr = `${form.break_end_date}T${form.break_end_time}`;
|
||||
mins -= (new Date(beStr).getTime() - new Date(bsStr).getTime()) / 60000;
|
||||
}
|
||||
return Math.max(0, Math.floor(mins))
|
||||
}
|
||||
return Math.max(0, Math.floor(mins));
|
||||
};
|
||||
|
||||
export const formatTimeOrDatetimePrint = (datetime: string | null | undefined, shiftDate: string): string => {
|
||||
if (!datetime) return '—'
|
||||
export const formatTimeOrDatetimePrint = (
|
||||
datetime: string | null | undefined,
|
||||
shiftDate: string,
|
||||
): string => {
|
||||
if (!datetime) return "—";
|
||||
// Extract date from the datetime string directly (no timezone conversion)
|
||||
const dateMatch = datetime.match(/(\d{4})-(\d{2})-(\d{2})/)
|
||||
const timeDate = dateMatch ? `${dateMatch[1]}-${dateMatch[2]}-${dateMatch[3]}` : ''
|
||||
const dateMatch = datetime.match(/(\d{4})-(\d{2})-(\d{2})/);
|
||||
const timeDate = dateMatch
|
||||
? `${dateMatch[1]}-${dateMatch[2]}-${dateMatch[3]}`
|
||||
: "";
|
||||
if (timeDate && timeDate !== shiftDate) {
|
||||
const datePart = `${parseInt(dateMatch![3])}.${parseInt(dateMatch![2])}.`
|
||||
return `${datePart} ${extractTime(datetime)}`
|
||||
const datePart = `${parseInt(dateMatch![3])}.${parseInt(dateMatch![2])}.`;
|
||||
return `${datePart} ${extractTime(datetime)}`;
|
||||
}
|
||||
return extractTime(datetime)
|
||||
}
|
||||
return extractTime(datetime);
|
||||
};
|
||||
|
||||
export const calculateWorkMinutesPrint = (record: AttendanceRecord): number => {
|
||||
const leaveType = record.leave_type || 'work'
|
||||
if (leaveType !== 'work') {
|
||||
return (Number(record.leave_hours) || 8) * 60
|
||||
const leaveType = record.leave_type || "work";
|
||||
if (leaveType !== "work") {
|
||||
return (Number(record.leave_hours) || 8) * 60;
|
||||
}
|
||||
if (!record.arrival_time || !record.departure_time) return 0
|
||||
const arrival = new Date(record.arrival_time).getTime()
|
||||
const departure = new Date(record.departure_time).getTime()
|
||||
let minutes = (departure - arrival) / 60000
|
||||
if (!record.arrival_time || !record.departure_time) return 0;
|
||||
const arrival = new Date(record.arrival_time).getTime();
|
||||
const departure = new Date(record.departure_time).getTime();
|
||||
let minutes = (departure - arrival) / 60000;
|
||||
|
||||
if (record.break_start && record.break_end) {
|
||||
const breakStart = new Date(record.break_start).getTime()
|
||||
const breakEnd = new Date(record.break_end).getTime()
|
||||
minutes -= (breakEnd - breakStart) / 60000
|
||||
const breakStart = new Date(record.break_start).getTime();
|
||||
const breakEnd = new Date(record.break_end).getTime();
|
||||
minutes -= (breakEnd - breakStart) / 60000;
|
||||
}
|
||||
|
||||
return Math.max(0, Math.floor(minutes))
|
||||
}
|
||||
return Math.max(0, Math.floor(minutes));
|
||||
};
|
||||
|
||||
@@ -1,79 +1,114 @@
|
||||
export const LEAVE_TYPE_LABELS: Record<string, string> = {
|
||||
vacation: 'Dovolená',
|
||||
sick: 'Nemoc',
|
||||
holiday: 'Svátek',
|
||||
unpaid: 'Neplacené volno',
|
||||
}
|
||||
vacation: "Dovolená",
|
||||
sick: "Nemoc",
|
||||
holiday: "Svátek",
|
||||
unpaid: "Neplacené volno",
|
||||
};
|
||||
|
||||
export const STATUS_DOT_CLASS: Record<string, string> = {
|
||||
in: 'dash-status-in',
|
||||
away: 'dash-status-away',
|
||||
out: 'dash-status-out',
|
||||
leave: 'dash-status-leave',
|
||||
}
|
||||
in: "dash-status-in",
|
||||
away: "dash-status-away",
|
||||
out: "dash-status-out",
|
||||
leave: "dash-status-leave",
|
||||
};
|
||||
|
||||
export const STATUS_LABELS: Record<string, string> = {
|
||||
in: 'Přítomen',
|
||||
away: 'Přestávka',
|
||||
out: 'Nepřihlášen',
|
||||
leave: 'Nepřítomen',
|
||||
}
|
||||
in: "Přítomen",
|
||||
away: "Přestávka",
|
||||
out: "Nepřihlášen",
|
||||
leave: "Nepřítomen",
|
||||
};
|
||||
|
||||
export const ENTITY_TYPE_LABELS: Record<string, string> = {
|
||||
user: 'Uživatel',
|
||||
attendance: 'Docházka',
|
||||
leave_request: 'Žádost o nepřítomnost',
|
||||
offers_quotation: 'Nabídka',
|
||||
offers_customer: 'Zákazník',
|
||||
offers_item_template: 'Šablona položky',
|
||||
offers_scope_template: 'Šablona rozsahu',
|
||||
offers_settings: 'Nastavení nabídek',
|
||||
orders_order: 'Objednávka',
|
||||
invoices_invoice: 'Faktura',
|
||||
projects_project: 'Projekt',
|
||||
role: 'Role',
|
||||
trips: 'Jízda',
|
||||
vehicles: 'Vozidlo',
|
||||
bank_account: 'Bankovní účet',
|
||||
}
|
||||
user: "Uživatel",
|
||||
attendance: "Docházka",
|
||||
leave_request: "Žádost o nepřítomnost",
|
||||
offers_quotation: "Nabídka",
|
||||
offers_customer: "Zákazník",
|
||||
offers_item_template: "Šablona položky",
|
||||
offers_scope_template: "Šablona rozsahu",
|
||||
offers_settings: "Nastavení nabídek",
|
||||
orders_order: "Objednávka",
|
||||
invoices_invoice: "Faktura",
|
||||
projects_project: "Projekt",
|
||||
role: "Role",
|
||||
trips: "Jízda",
|
||||
vehicles: "Vozidlo",
|
||||
bank_account: "Bankovní účet",
|
||||
};
|
||||
|
||||
export const ACTION_LABELS: Record<string, string> = {
|
||||
create: 'Vytvořil',
|
||||
update: 'Upravil',
|
||||
delete: 'Smazal',
|
||||
login: 'Přihlášení',
|
||||
}
|
||||
create: "Vytvořil",
|
||||
update: "Upravil",
|
||||
delete: "Smazal",
|
||||
login: "Přihlášení",
|
||||
};
|
||||
|
||||
export function getCzechDate(): string {
|
||||
const now = new Date()
|
||||
const days = ['Neděle', 'Pondělí', 'Úterý', 'Středa', 'Čtvrtek', 'Pátek', 'Sobota']
|
||||
const months = ['ledna', 'února', 'března', 'dubna', 'května', 'června', 'července', 'srpna', 'září', 'října', 'listopadu', 'prosince']
|
||||
const day = days[now.getDay()]
|
||||
const oneJan = new Date(now.getFullYear(), 0, 1)
|
||||
const week = Math.ceil(((now.getTime() - oneJan.getTime()) / 86400000 + oneJan.getDay() + 1) / 7)
|
||||
return `${day}, ${now.getDate()}. ${months[now.getMonth()]} ${now.getFullYear()} · Týden ${week}`
|
||||
const now = new Date();
|
||||
const days = [
|
||||
"Neděle",
|
||||
"Pondělí",
|
||||
"Úterý",
|
||||
"Středa",
|
||||
"Čtvrtek",
|
||||
"Pátek",
|
||||
"Sobota",
|
||||
];
|
||||
const months = [
|
||||
"ledna",
|
||||
"února",
|
||||
"března",
|
||||
"dubna",
|
||||
"května",
|
||||
"června",
|
||||
"července",
|
||||
"srpna",
|
||||
"září",
|
||||
"října",
|
||||
"listopadu",
|
||||
"prosince",
|
||||
];
|
||||
const day = days[now.getDay()];
|
||||
const oneJan = new Date(now.getFullYear(), 0, 1);
|
||||
const week = Math.ceil(
|
||||
((now.getTime() - oneJan.getTime()) / 86400000 + oneJan.getDay() + 1) / 7,
|
||||
);
|
||||
return `${day}, ${now.getDate()}. ${months[now.getMonth()]} ${now.getFullYear()} · Týden ${week}`;
|
||||
}
|
||||
|
||||
export function getActivityIconClass(action: string): string {
|
||||
const map: Record<string, string> = { create: 'success', update: 'info', delete: 'danger', login: 'accent' }
|
||||
return map[action] || 'muted'
|
||||
const map: Record<string, string> = {
|
||||
create: "success",
|
||||
update: "info",
|
||||
delete: "danger",
|
||||
login: "accent",
|
||||
};
|
||||
return map[action] || "muted";
|
||||
}
|
||||
|
||||
export function formatActivityTime(dateString: string): string {
|
||||
const date = new Date(dateString)
|
||||
const now = new Date()
|
||||
const diff = now.getTime() - date.getTime()
|
||||
if (diff < 60000) return 'Právě teď'
|
||||
if (diff < 3600000) return `${Math.floor(diff / 60000)} min`
|
||||
const date = new Date(dateString);
|
||||
const now = new Date();
|
||||
const diff = now.getTime() - date.getTime();
|
||||
if (diff < 60000) return "Právě teď";
|
||||
if (diff < 3600000) return `${Math.floor(diff / 60000)} min`;
|
||||
if (date.toDateString() === now.toDateString()) {
|
||||
return date.toLocaleTimeString('cs-CZ', { hour: '2-digit', minute: '2-digit' })
|
||||
return date.toLocaleTimeString("cs-CZ", {
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
});
|
||||
}
|
||||
return date.toLocaleDateString('cs-CZ', { day: '2-digit', month: '2-digit' })
|
||||
return date.toLocaleDateString("cs-CZ", { day: "2-digit", month: "2-digit" });
|
||||
}
|
||||
|
||||
export function formatSessionDate(dateString: string): string {
|
||||
const date = new Date(dateString)
|
||||
return date.toLocaleDateString('cs-CZ', {
|
||||
day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit',
|
||||
})
|
||||
const date = new Date(dateString);
|
||||
return date.toLocaleDateString("cs-CZ", {
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,26 +1,39 @@
|
||||
export function formatCurrency(amount: number | string, currency: string): string {
|
||||
const num = Number(amount) || 0
|
||||
export function formatCurrency(
|
||||
amount: number | string,
|
||||
currency: string,
|
||||
): string {
|
||||
const num = Number(amount) || 0;
|
||||
switch (currency) {
|
||||
case 'EUR': return `${num.toLocaleString('cs-CZ', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} €`
|
||||
case 'USD': return `$${num.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`
|
||||
case 'CZK': return `${num.toLocaleString('cs-CZ', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} Kč`
|
||||
case 'GBP': return `£${num.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`
|
||||
default: return `${num.toFixed(2)} ${currency}`
|
||||
case "EUR":
|
||||
return `${num.toLocaleString("cs-CZ", { minimumFractionDigits: 2, maximumFractionDigits: 2 })} €`;
|
||||
case "USD":
|
||||
return `$${num.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
|
||||
case "CZK":
|
||||
return `${num.toLocaleString("cs-CZ", { minimumFractionDigits: 2, maximumFractionDigits: 2 })} Kč`;
|
||||
case "GBP":
|
||||
return `£${num.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
|
||||
default:
|
||||
return `${num.toFixed(2)} ${currency}`;
|
||||
}
|
||||
}
|
||||
|
||||
export function formatDate(dateStr: string | null | undefined): string {
|
||||
if (!dateStr) return '—'
|
||||
const d = new Date(dateStr)
|
||||
return d.toLocaleDateString('cs-CZ')
|
||||
if (!dateStr) return "—";
|
||||
const d = new Date(dateStr);
|
||||
return d.toLocaleDateString("cs-CZ");
|
||||
}
|
||||
|
||||
export function formatKm(km: number | string): string {
|
||||
return new Intl.NumberFormat('cs-CZ').format(Number(km) || 0)
|
||||
return new Intl.NumberFormat("cs-CZ").format(Number(km) || 0);
|
||||
}
|
||||
|
||||
export function czechPlural(n: number, one: string, few: string, many: string): string {
|
||||
if (n === 1) return one
|
||||
if (n >= 2 && n <= 4) return few
|
||||
return many
|
||||
export function czechPlural(
|
||||
n: number,
|
||||
one: string,
|
||||
few: string,
|
||||
many: string,
|
||||
): string {
|
||||
if (n === 1) return one;
|
||||
if (n >= 2 && n <= 4) return few;
|
||||
return many;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user