feat(i18n): Hebrew locale + full RTL support
This commit is contained in:
@@ -131,7 +131,7 @@ export function CalendarAgendaView({
|
||||
)}>
|
||||
{formatDateHeader(group.date)}
|
||||
</span>
|
||||
<span className="text-xs text-muted-foreground ml-2">
|
||||
<span className="text-xs text-muted-foreground ms-2">
|
||||
{intlFormatter.dateTime(group.date, { month: "short", day: "numeric", year: "numeric" })}
|
||||
</span>
|
||||
</div>
|
||||
@@ -163,7 +163,7 @@ export function CalendarAgendaView({
|
||||
onMouseLeave={() => onHoverLeave?.()}
|
||||
onContextMenu={onContextMenuEvent ? (e) => onContextMenuEvent(e, ev) : undefined}
|
||||
className={cn(
|
||||
"w-full flex items-start px-4 hover:bg-muted/50 transition-colors text-left",
|
||||
"w-full flex items-start px-4 hover:bg-muted/50 transition-colors text-start",
|
||||
isCancelled && "opacity-60"
|
||||
)}
|
||||
style={{ gap: 'var(--density-item-gap)', paddingBlock: 'var(--density-item-py)' }}
|
||||
|
||||
@@ -218,7 +218,7 @@ export function CalendarDayView({
|
||||
{HOURS.map((h) => (
|
||||
<div
|
||||
key={h}
|
||||
className="relative text-muted-foreground text-right pr-2"
|
||||
className="relative text-muted-foreground text-end pe-2"
|
||||
style={{ height: HOUR_HEIGHT }}
|
||||
>
|
||||
{h > 0 && (
|
||||
@@ -231,7 +231,7 @@ export function CalendarDayView({
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="flex-1 relative border-l border-border"
|
||||
className="flex-1 relative border-s border-border"
|
||||
role="row"
|
||||
aria-label={t("views.day")}
|
||||
onPointerDown={(e) => handleGridPointerDown(e, dayKey, selectedDate)}
|
||||
@@ -312,7 +312,7 @@ export function CalendarDayView({
|
||||
style={{ top: (nowMinutes / 60) * HOUR_HEIGHT }}
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<div className="w-2.5 h-2.5 rounded-full bg-destructive -ml-1" />
|
||||
<div className="w-2.5 h-2.5 rounded-full bg-destructive -ms-1" />
|
||||
<div className="flex-1 h-px bg-destructive" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -346,7 +346,7 @@ export function CalendarDayView({
|
||||
style={{ top: (dropTarget.minutes / 60) * HOUR_HEIGHT }}
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<div className="w-2.5 h-2.5 rounded-full bg-primary -ml-1" />
|
||||
<div className="w-2.5 h-2.5 rounded-full bg-primary -ms-1" />
|
||||
<div className="flex-1 h-0.5 bg-primary rounded-full" />
|
||||
</div>
|
||||
<div className="absolute -top-4 left-2 text-[10px] font-medium text-primary bg-background/90 px-1 rounded shadow-sm">
|
||||
|
||||
@@ -145,7 +145,7 @@ export function CalendarMonthView({
|
||||
<div className="grid grid-cols-7 border-b border-border" role="row">
|
||||
{dayHeaders.map((d) => (
|
||||
<div key={d} role="columnheader" className={cn(
|
||||
"text-center text-xs font-medium text-muted-foreground py-2 border-r border-border last:border-r-0",
|
||||
"text-center text-xs font-medium text-muted-foreground py-2 border-e border-border last:border-e-0",
|
||||
isMobile && "py-1.5 text-[11px]"
|
||||
)}>
|
||||
{isMobile ? t(`days.${d}`).slice(0, 2) : t(`days.${d}`)}
|
||||
@@ -181,7 +181,7 @@ export function CalendarMonthView({
|
||||
onDragLeave={handleCellDragLeave}
|
||||
onDrop={(e) => handleCellDrop(e, day)}
|
||||
className={cn(
|
||||
"border-r border-border last:border-r-0 p-1 cursor-pointer transition-colors touch-manipulation",
|
||||
"border-e border-border last:border-e-0 p-1 cursor-pointer transition-colors touch-manipulation",
|
||||
!inMonth && "bg-muted/30",
|
||||
"hover:bg-muted/50",
|
||||
selected && isMobile && "bg-primary/10",
|
||||
|
||||
@@ -397,7 +397,7 @@ export function CalendarSidebarPanel({
|
||||
<ListTodo className="w-4 h-4 text-muted-foreground" />
|
||||
<span>{t('tasks.label')}</span>
|
||||
{pendingTaskCount > 0 && (
|
||||
<span className="ml-auto text-xs text-muted-foreground">{pendingTaskCount}</span>
|
||||
<span className="ms-auto text-xs text-muted-foreground">{pendingTaskCount}</span>
|
||||
)}
|
||||
{overdueTaskCount > 0 && (
|
||||
<span className="text-xs text-destructive font-medium">{overdueTaskCount} {t('tasks.filter_overdue').toLowerCase()}</span>
|
||||
@@ -437,7 +437,7 @@ export function CalendarSidebarPanel({
|
||||
onCreateCalendar();
|
||||
}
|
||||
}}
|
||||
className="ml-auto p-0.5 rounded text-muted-foreground/70 opacity-0 group-hover:opacity-100 hover:text-foreground hover:bg-muted transition-colors cursor-pointer"
|
||||
className="ms-auto p-0.5 rounded text-muted-foreground/70 opacity-0 group-hover:opacity-100 hover:text-foreground hover:bg-muted transition-colors cursor-pointer"
|
||||
title={tMgmt('add_calendar')}
|
||||
>
|
||||
<Plus className="w-3 h-3" />
|
||||
@@ -445,7 +445,7 @@ export function CalendarSidebarPanel({
|
||||
)}
|
||||
</button>
|
||||
{expanded && (
|
||||
<div className="mt-1 pl-3">
|
||||
<div className="mt-1 ps-3">
|
||||
{owned.length > 0 && (
|
||||
<div>
|
||||
<div className="px-1 mb-1 text-[10px] font-medium text-muted-foreground/80 uppercase tracking-wider">
|
||||
|
||||
@@ -124,7 +124,7 @@ export function CalendarToolbar({
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={onMenuClick}
|
||||
className="h-8 w-8 -ml-1 mr-1"
|
||||
className="h-8 w-8 -ms-1 me-1"
|
||||
aria-label={t("nav_open_menu")}
|
||||
>
|
||||
<Menu className="w-4 h-4" />
|
||||
@@ -138,7 +138,7 @@ export function CalendarToolbar({
|
||||
{onMenuClick && (
|
||||
<button
|
||||
onClick={onMenuClick}
|
||||
className="p-1.5 -ml-1 rounded-md hover:bg-muted transition-colors touch-manipulation"
|
||||
className="p-1.5 -ms-1 rounded-md hover:bg-muted transition-colors touch-manipulation"
|
||||
aria-label={t("nav_open_menu")}
|
||||
>
|
||||
<Menu className="w-4 h-4" />
|
||||
@@ -147,7 +147,7 @@ export function CalendarToolbar({
|
||||
{onNavigateBack && (
|
||||
<button
|
||||
onClick={onNavigateBack}
|
||||
className="p-1.5 -ml-1 rounded-md hover:bg-muted transition-colors touch-manipulation"
|
||||
className="p-1.5 -ms-1 rounded-md hover:bg-muted transition-colors touch-manipulation"
|
||||
aria-label={t("back_to_month")}
|
||||
>
|
||||
<ArrowLeft className="w-4 h-4" />
|
||||
@@ -162,7 +162,7 @@ export function CalendarToolbar({
|
||||
<button onClick={onNext} className="p-1.5 rounded-md hover:bg-muted transition-colors touch-manipulation" aria-label={t("nav_next")}>
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</button>
|
||||
<Button variant="ghost" size="sm" onClick={onToday} className="touch-manipulation text-xs h-7 px-2 ml-0.5">
|
||||
<Button variant="ghost" size="sm" onClick={onToday} className="touch-manipulation text-xs h-7 px-2 ms-0.5">
|
||||
{t("views.today")}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -284,7 +284,7 @@ export function CalendarToolbar({
|
||||
{/* ── DESKTOP TOOLBAR ── */}
|
||||
{!isMobile && (
|
||||
<div className="flex items-center gap-1">
|
||||
<Button variant="outline" size="sm" onClick={onToday} className="h-8 mr-1">
|
||||
<Button variant="outline" size="sm" onClick={onToday} className="h-8 me-1">
|
||||
{t("views.today")}
|
||||
</Button>
|
||||
<Button variant="ghost" size="icon" className="h-8 w-8" onClick={onPrev} aria-label={t("nav_prev")}>
|
||||
@@ -293,7 +293,7 @@ export function CalendarToolbar({
|
||||
<Button variant="ghost" size="icon" className="h-8 w-8" onClick={onNext} aria-label={t("nav_next")}>
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</Button>
|
||||
<span className="text-base font-semibold ml-2 select-none">
|
||||
<span className="text-base font-semibold ms-2 select-none">
|
||||
{getDateLabel()}
|
||||
</span>
|
||||
</div>
|
||||
@@ -328,9 +328,9 @@ export function CalendarToolbar({
|
||||
{(onImport || onSubscribe) && !isMobile && (
|
||||
<div className="relative" ref={importDropdownRef}>
|
||||
<Button variant="outline" size="sm" className="h-8" onClick={() => setShowImportDropdown((v) => !v)}>
|
||||
<Upload className="w-4 h-4 mr-1" />
|
||||
<Upload className="w-4 h-4 me-1" />
|
||||
{t("import.title")}
|
||||
<ChevronDown className="w-3 h-3 ml-1" />
|
||||
<ChevronDown className="w-3 h-3 ms-1" />
|
||||
</Button>
|
||||
{showImportDropdown && (
|
||||
<div className="absolute top-full right-0 mt-1 z-50 bg-background border border-border rounded-lg shadow-lg p-1 min-w-[180px]">
|
||||
@@ -359,7 +359,7 @@ export function CalendarToolbar({
|
||||
|
||||
{!isMobile && (
|
||||
<Button size="sm" className="h-8" onClick={onCreateEvent} data-tour="create-event-button">
|
||||
<Plus className="w-4 h-4 mr-1" />
|
||||
<Plus className="w-4 h-4 me-1" />
|
||||
{t("events.create")}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
@@ -211,7 +211,7 @@ export function CalendarWeekView({
|
||||
<div className={cn("flex min-h-0 flex-col flex-1", isMobile && "min-w-[880px]")}> {hasAllDay && (
|
||||
<div className="flex border-b border-border">
|
||||
<div
|
||||
className={cn("flex-shrink-0 text-[10px] text-muted-foreground p-1 text-right", isMobile ? "w-10 sticky left-0 z-10 bg-background" : "w-14")}
|
||||
className={cn("flex-shrink-0 text-[10px] text-muted-foreground p-1 text-end", isMobile ? "w-10 sticky left-0 z-10 bg-background" : "w-14")}
|
||||
style={{ minHeight: Math.max(28, (allDayRowCount + taskRowCount) * 24 + 4) }}
|
||||
>
|
||||
{t("events.all_day")}
|
||||
@@ -306,7 +306,7 @@ export function CalendarWeekView({
|
||||
|
||||
<div className="flex border-b border-border" role="row">
|
||||
<div className={cn("flex-shrink-0", isMobile ? "w-10 sticky left-0 z-10 bg-background" : "w-14")} />
|
||||
<div className="flex-1 border-l border-border grid grid-cols-7">
|
||||
<div className="flex-1 border-s border-border grid grid-cols-7">
|
||||
{weekDays.map((day) => {
|
||||
const todayCol = isToday(day);
|
||||
const selected = isSameDay(day, selectedDate);
|
||||
@@ -318,7 +318,7 @@ export function CalendarWeekView({
|
||||
role="columnheader"
|
||||
aria-label={fullLabel}
|
||||
className={cn(
|
||||
"text-center py-2 text-sm border-r border-border last:border-r-0 transition-colors touch-manipulation",
|
||||
"text-center py-2 text-sm border-e border-border last:border-e-0 transition-colors touch-manipulation",
|
||||
"hover:bg-muted/50",
|
||||
todayCol && "font-bold",
|
||||
)}
|
||||
@@ -345,7 +345,7 @@ export function CalendarWeekView({
|
||||
{HOURS.map((h) => (
|
||||
<div
|
||||
key={h}
|
||||
className="relative text-muted-foreground text-right pr-2"
|
||||
className="relative text-muted-foreground text-end pe-2"
|
||||
style={{ height: HOUR_HEIGHT }}
|
||||
>
|
||||
{h > 0 && (
|
||||
@@ -357,7 +357,7 @@ export function CalendarWeekView({
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="flex-1 border-l border-border relative grid grid-cols-7">
|
||||
<div className="flex-1 border-s border-border relative grid grid-cols-7">
|
||||
{weekDays.map((day) => {
|
||||
const key = format(day, "yyyy-MM-dd");
|
||||
const dayEvents = timedEvents.get(key) || [];
|
||||
@@ -367,7 +367,7 @@ export function CalendarWeekView({
|
||||
return (
|
||||
<div
|
||||
key={key}
|
||||
className="relative border-r border-border last:border-r-0"
|
||||
className="relative border-e border-border last:border-e-0"
|
||||
role="row"
|
||||
aria-label={intlFormatter.dateTime(day, { weekday: "long", month: "long", day: "numeric" })}
|
||||
onPointerDown={(e) => handleGridPointerDown(e, key, day)}
|
||||
@@ -448,7 +448,7 @@ export function CalendarWeekView({
|
||||
style={{ top: (nowMinutes / 60) * HOUR_HEIGHT }}
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<div className="w-2 h-2 rounded-full bg-destructive -ml-1" />
|
||||
<div className="w-2 h-2 rounded-full bg-destructive -ms-1" />
|
||||
<div className="flex-1 h-px bg-destructive" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -482,7 +482,7 @@ export function CalendarWeekView({
|
||||
style={{ top: (dropTarget.minutes / 60) * HOUR_HEIGHT }}
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<div className="w-2 h-2 rounded-full bg-primary -ml-1" />
|
||||
<div className="w-2 h-2 rounded-full bg-primary -ms-1" />
|
||||
<div className="flex-1 h-0.5 bg-primary rounded-full" />
|
||||
</div>
|
||||
<div className="absolute -top-4 left-2 text-[10px] font-medium text-primary bg-background/90 px-1 rounded shadow-sm">
|
||||
|
||||
@@ -137,7 +137,7 @@ export function CreateCalendarModal({ client, onClose }: CreateCalendarModalProp
|
||||
<Button onClick={handleSubmit} disabled={!isValid || isSubmitting}>
|
||||
{isSubmitting ? (
|
||||
<>
|
||||
<Loader2 className="w-4 h-4 animate-spin mr-2" />
|
||||
<Loader2 className="w-4 h-4 animate-spin me-2" />
|
||||
{tCommon("loading")}
|
||||
</>
|
||||
) : (
|
||||
|
||||
@@ -134,7 +134,7 @@ export function EventCard({ event, calendar, variant, onClick, onMouseEnter, onM
|
||||
aria-label={ariaLabel}
|
||||
{...dragProps}
|
||||
className={cn(
|
||||
"flex items-center gap-1 w-full text-left text-xs px-1 py-0.5 rounded truncate",
|
||||
"flex items-center gap-1 w-full text-start text-xs px-1 py-0.5 rounded truncate",
|
||||
"min-h-[44px] sm:min-h-0",
|
||||
"hover:opacity-80 transition-opacity",
|
||||
isSelected && "ring-2 ring-primary",
|
||||
@@ -163,10 +163,10 @@ export function EventCard({ event, calendar, variant, onClick, onMouseEnter, onM
|
||||
aria-label={ariaLabel}
|
||||
{...dragProps}
|
||||
className={cn(
|
||||
"w-full h-full text-left rounded-r px-1.5 py-0.5 text-xs overflow-hidden",
|
||||
"w-full h-full text-start rounded-r px-1.5 py-0.5 text-xs overflow-hidden",
|
||||
"hover:opacity-90 transition-opacity cursor-pointer",
|
||||
continuesAfter && "rounded-r-sm",
|
||||
continuesAfter && "pr-2",
|
||||
continuesAfter && "pe-2",
|
||||
isSelected && "ring-2 ring-primary",
|
||||
isBeingDragged && "opacity-50",
|
||||
isCancelled && !isBeingDragged && "opacity-60",
|
||||
@@ -194,7 +194,7 @@ export function EventCard({ event, calendar, variant, onClick, onMouseEnter, onM
|
||||
{...dragProps}
|
||||
data-calendar-event
|
||||
className={cn(
|
||||
"w-full h-full text-left rounded-r px-1.5 py-0.5 text-xs overflow-hidden",
|
||||
"w-full h-full text-start rounded-r px-1.5 py-0.5 text-xs overflow-hidden",
|
||||
"hover:opacity-90 transition-opacity cursor-pointer",
|
||||
isSelected && "ring-2 ring-primary",
|
||||
isBeingDragged && "opacity-50",
|
||||
|
||||
@@ -298,15 +298,15 @@ export function EventDetailPopover({
|
||||
</h3>
|
||||
</div>
|
||||
{calendar && (
|
||||
<p className="text-xs text-muted-foreground mt-0.5 pl-[18px]">
|
||||
<p className="text-xs text-muted-foreground mt-0.5 ps-[18px]">
|
||||
{calendar.name}
|
||||
{event.status === "tentative" && (
|
||||
<span className="ml-2 inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-warning/15 text-warning">
|
||||
<span className="ms-2 inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-warning/15 text-warning">
|
||||
{t("detail.tentative")}
|
||||
</span>
|
||||
)}
|
||||
{event.status === "cancelled" && (
|
||||
<span className="ml-2 inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400">
|
||||
<span className="ms-2 inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400 line-through">
|
||||
{t("detail.cancelled")}
|
||||
</span>
|
||||
)}
|
||||
@@ -346,13 +346,13 @@ export function EventDetailPopover({
|
||||
<>
|
||||
<div className="font-medium text-foreground">
|
||||
{formatEventDate(startDate)}
|
||||
<span className="ml-1.5 font-normal text-muted-foreground">
|
||||
<span className="ms-1.5 font-normal text-muted-foreground">
|
||||
{formatTime(startDate)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="font-medium text-foreground">
|
||||
{formatEventDate(endDate)}
|
||||
<span className="ml-1.5 font-normal text-muted-foreground">
|
||||
<span className="ms-1.5 font-normal text-muted-foreground">
|
||||
{formatTime(endDate)}
|
||||
</span>
|
||||
</div>
|
||||
@@ -367,11 +367,11 @@ export function EventDetailPopover({
|
||||
{formatEventDate(startDate)}
|
||||
</span>
|
||||
{event.showWithoutTime ? (
|
||||
<span className="text-muted-foreground ml-1.5">{t("events.all_day")}</span>
|
||||
<span className="text-muted-foreground ms-1.5">{t("events.all_day")}</span>
|
||||
) : (
|
||||
<div className="text-muted-foreground">
|
||||
{formatTime(startDate)} – {formatTime(endDate)}
|
||||
<span className="ml-1.5 text-xs">({formatDurationDisplay(durationMinutes)})</span>
|
||||
<span className="ms-1.5 text-xs">({formatDurationDisplay(durationMinutes)})</span>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
@@ -437,7 +437,7 @@ export function EventDetailPopover({
|
||||
<span className="truncate text-foreground">
|
||||
{p.name || p.email}
|
||||
{p.isOrganizer && (
|
||||
<span className="text-muted-foreground ml-1">
|
||||
<span className="text-muted-foreground ms-1">
|
||||
({t("participants.organizer").toLowerCase()})
|
||||
</span>
|
||||
)}
|
||||
@@ -515,7 +515,7 @@ export function EventDetailPopover({
|
||||
disabled={!noteText.trim() || isSavingNote}
|
||||
className="h-7 text-xs"
|
||||
>
|
||||
<Send className="w-3 h-3 mr-1" />
|
||||
<Send className="w-3 h-3 me-1" />
|
||||
{t("detail.save_note")}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -549,7 +549,7 @@ export function EventDetailPopover({
|
||||
: "text-success border-success/30 hover:bg-success/10"
|
||||
}
|
||||
>
|
||||
{userCurrentStatus === "accepted" && <Check className="w-3.5 h-3.5 mr-1" />}
|
||||
{userCurrentStatus === "accepted" && <Check className="w-3.5 h-3.5 me-1" />}
|
||||
{t("participants.accepted")}
|
||||
</Button>
|
||||
<Button
|
||||
@@ -562,7 +562,7 @@ export function EventDetailPopover({
|
||||
: "border border-warning/30 text-warning hover:bg-warning/10"
|
||||
}
|
||||
>
|
||||
{userCurrentStatus === "tentative" && <Check className="w-3.5 h-3.5 mr-1" />}
|
||||
{userCurrentStatus === "tentative" && <Check className="w-3.5 h-3.5 me-1" />}
|
||||
{t("participants.tentative")}
|
||||
</Button>
|
||||
<Button
|
||||
@@ -575,7 +575,7 @@ export function EventDetailPopover({
|
||||
: "text-destructive hover:bg-destructive/10"
|
||||
}
|
||||
>
|
||||
{userCurrentStatus === "declined" && <Check className="w-3.5 h-3.5 mr-1" />}
|
||||
{userCurrentStatus === "declined" && <Check className="w-3.5 h-3.5 me-1" />}
|
||||
{t("participants.declined")}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -609,7 +609,7 @@ export function EventDetailPopover({
|
||||
) : (
|
||||
<>
|
||||
<Button variant="default" size="sm" onClick={onEdit} className="h-7 text-xs">
|
||||
<Pencil className="w-3.5 h-3.5 mr-1" />
|
||||
<Pencil className="w-3.5 h-3.5 me-1" />
|
||||
{t("events.edit")}
|
||||
</Button>
|
||||
<Button
|
||||
@@ -619,7 +619,7 @@ export function EventDetailPopover({
|
||||
className="h-7 text-xs"
|
||||
title={t("events.duplicate")}
|
||||
>
|
||||
<Copy className="w-3.5 h-3.5 mr-1" />
|
||||
<Copy className="w-3.5 h-3.5 me-1" />
|
||||
{t("events.duplicate")}
|
||||
</Button>
|
||||
<div className="flex-1" />
|
||||
|
||||
@@ -666,11 +666,11 @@ export function EventModal({
|
||||
<div className="text-sm">
|
||||
<div>
|
||||
<span className="font-medium">{formatEventDate(startD)}</span>
|
||||
<span className="text-muted-foreground ml-2">{format(startD, timeDisplayFmt)}</span>
|
||||
<span className="text-muted-foreground ms-2">{format(startD, timeDisplayFmt)}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="font-medium">{formatEventDate(endD)}</span>
|
||||
<span className="text-muted-foreground ml-2">{format(endD, timeDisplayFmt)}</span>
|
||||
<span className="text-muted-foreground ms-2">{format(endD, timeDisplayFmt)}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -679,7 +679,7 @@ export function EventModal({
|
||||
<div className="text-sm">
|
||||
<span className="font-medium">{formatEventDate(startD)}</span>
|
||||
{!event.showWithoutTime && (
|
||||
<span className="text-muted-foreground ml-2">
|
||||
<span className="text-muted-foreground ms-2">
|
||||
{format(startD, timeDisplayFmt)} – {format(endD, timeDisplayFmt)}
|
||||
</span>
|
||||
)}
|
||||
@@ -701,7 +701,7 @@ export function EventModal({
|
||||
<Users className="w-4 h-4" />
|
||||
{t("participants.title")}
|
||||
</div>
|
||||
<div className="space-y-1 pl-5">
|
||||
<div className="space-y-1 ps-5">
|
||||
{participants.map(p => (
|
||||
<div key={p.id} className="flex items-center justify-between text-sm">
|
||||
<span className="truncate">{p.name || p.email}</span>
|
||||
@@ -726,7 +726,7 @@ export function EventModal({
|
||||
? "bg-success hover:bg-success/80 text-success-foreground"
|
||||
: "text-success border-success/30 hover:bg-success/10"}
|
||||
>
|
||||
{userCurrentStatus === "accepted" && <Check className="w-4 h-4 mr-1" />}
|
||||
{userCurrentStatus === "accepted" && <Check className="w-4 h-4 me-1" />}
|
||||
{t("participants.accepted")}
|
||||
</Button>
|
||||
<Button
|
||||
@@ -737,7 +737,7 @@ export function EventModal({
|
||||
? "bg-warning hover:bg-warning/80 text-warning-foreground"
|
||||
: "border border-warning/30 text-warning hover:bg-warning/10"}
|
||||
>
|
||||
{userCurrentStatus === "tentative" && <Check className="w-4 h-4 mr-1" />}
|
||||
{userCurrentStatus === "tentative" && <Check className="w-4 h-4 me-1" />}
|
||||
{t("participants.tentative")}
|
||||
</Button>
|
||||
<Button
|
||||
@@ -748,7 +748,7 @@ export function EventModal({
|
||||
? "bg-destructive hover:bg-destructive/80 text-destructive-foreground"
|
||||
: "text-destructive hover:bg-destructive/10"}
|
||||
>
|
||||
{userCurrentStatus === "declined" && <Check className="w-4 h-4 mr-1" />}
|
||||
{userCurrentStatus === "declined" && <Check className="w-4 h-4 me-1" />}
|
||||
{t("participants.declined")}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -784,7 +784,7 @@ export function EventModal({
|
||||
<h2 className="text-lg font-semibold truncate">{event.title || t("events.no_title")}</h2>
|
||||
</div>
|
||||
{eventCalendar && (
|
||||
<p className="text-xs text-muted-foreground mt-0.5 pl-[18px]">{eventCalendar.name}</p>
|
||||
<p className="text-xs text-muted-foreground mt-0.5 ps-[18px]">{eventCalendar.name}</p>
|
||||
)}
|
||||
</div>
|
||||
<button onClick={onClose} className="p-1.5 rounded-md hover:bg-muted transition-colors duration-150 flex-shrink-0 mt-0.5 text-muted-foreground hover:text-foreground" aria-label={t("form.cancel")}>
|
||||
@@ -816,13 +816,13 @@ export function EventModal({
|
||||
<>
|
||||
<div className="font-medium text-foreground">
|
||||
{formatEventDate(startD)}
|
||||
<span className="ml-1.5 font-normal text-muted-foreground">
|
||||
<span className="ms-1.5 font-normal text-muted-foreground">
|
||||
{format(startD, timeDisplayFmt)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="font-medium text-foreground">
|
||||
{formatEventDate(endD)}
|
||||
<span className="ml-1.5 font-normal text-muted-foreground">
|
||||
<span className="ms-1.5 font-normal text-muted-foreground">
|
||||
{format(endD, timeDisplayFmt)}
|
||||
</span>
|
||||
</div>
|
||||
@@ -838,11 +838,11 @@ export function EventModal({
|
||||
{formatEventDate(startD)}
|
||||
</span>
|
||||
{event.showWithoutTime ? (
|
||||
<span className="text-muted-foreground ml-1.5">{t("events.all_day")}</span>
|
||||
<span className="text-muted-foreground ms-1.5">{t("events.all_day")}</span>
|
||||
) : (
|
||||
<div className="text-muted-foreground">
|
||||
{format(startD, timeDisplayFmt)} – {format(endD, timeDisplayFmt)}
|
||||
<span className="ml-1.5 text-xs">({formatDurationDisplay(durMin)})</span>
|
||||
<span className="ms-1.5 text-xs">({formatDurationDisplay(durMin)})</span>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
@@ -889,7 +889,7 @@ export function EventModal({
|
||||
<span className="truncate text-foreground">
|
||||
{p.name || p.email}
|
||||
{p.isOrganizer && (
|
||||
<span className="text-muted-foreground ml-1">({t("participants.organizer").toLowerCase()})</span>
|
||||
<span className="text-muted-foreground ms-1">({t("participants.organizer").toLowerCase()})</span>
|
||||
)}
|
||||
</span>
|
||||
<StatusBadge status={p.status} isOrganizer={p.isOrganizer} t={t} />
|
||||
@@ -942,21 +942,21 @@ export function EventModal({
|
||||
</div>
|
||||
) : (
|
||||
<Button variant="ghost" size="sm" onClick={() => setShowDeleteConfirm(true)} className="text-destructive">
|
||||
<Trash2 className="w-4 h-4 mr-1" />
|
||||
<Trash2 className="w-4 h-4 me-1" />
|
||||
{t("events.delete")}
|
||||
</Button>
|
||||
)
|
||||
)}
|
||||
{onDuplicate && !showDeleteConfirm && (
|
||||
<Button variant="ghost" size="sm" onClick={handleDuplicate} aria-label={t("events.duplicate")}>
|
||||
<Copy className="w-4 h-4 mr-1" />
|
||||
<Copy className="w-4 h-4 me-1" />
|
||||
{t("events.duplicate")}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
{!showDeleteConfirm && (
|
||||
<Button onClick={() => setMode("edit")}>
|
||||
<Pencil className="w-4 h-4 mr-1" />
|
||||
<Pencil className="w-4 h-4 me-1" />
|
||||
{t("events.edit")}
|
||||
</Button>
|
||||
)}
|
||||
@@ -1320,7 +1320,7 @@ export function EventModal({
|
||||
onClick={() => setShowDeleteConfirm(true)}
|
||||
className="text-red-600 dark:text-red-400"
|
||||
>
|
||||
<Trash2 className="w-4 h-4 mr-1" />
|
||||
<Trash2 className="w-4 h-4 me-1" />
|
||||
{t("events.delete")}
|
||||
</Button>
|
||||
)
|
||||
@@ -1332,7 +1332,7 @@ export function EventModal({
|
||||
onClick={handleDuplicate}
|
||||
aria-label={t("events.duplicate")}
|
||||
>
|
||||
<Copy className="w-4 h-4 mr-1" />
|
||||
<Copy className="w-4 h-4 me-1" />
|
||||
{t("events.duplicate")}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
@@ -444,7 +444,7 @@ export function ICalImportModal({ calendars, client, onClose, initialUrl }: ICal
|
||||
onClick={handleImport}
|
||||
disabled={selectedIndices.size === 0}
|
||||
>
|
||||
<Check className="w-4 h-4 mr-1" />
|
||||
<Check className="w-4 h-4 me-1" />
|
||||
{t("import_button")} ({selectedIndices.size})
|
||||
</Button>
|
||||
)}
|
||||
|
||||
@@ -208,7 +208,7 @@ export function ICalSubscriptionModal({ client, onClose, editSubscription, initi
|
||||
<Button onClick={handleSubmit} disabled={!isValid || isSubmitting}>
|
||||
{isSubmitting ? (
|
||||
<>
|
||||
<Loader2 className="w-4 h-4 animate-spin mr-2" />
|
||||
<Loader2 className="w-4 h-4 animate-spin me-2" />
|
||||
{isEdit ? t("saving") : t("subscribing")}
|
||||
</>
|
||||
) : (
|
||||
|
||||
@@ -302,7 +302,7 @@ export function TaskModal({
|
||||
className="text-destructive hover:text-destructive"
|
||||
onClick={() => onDelete(task.id)}
|
||||
>
|
||||
<Trash2 className="h-4 w-4 mr-1" />
|
||||
<Trash2 className="h-4 w-4 me-1" />
|
||||
{t("tasks.delete")}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
@@ -44,7 +44,7 @@ export function TaskToolbar({
|
||||
))}
|
||||
</div>
|
||||
|
||||
<label className="flex items-center gap-1.5 text-xs text-muted-foreground cursor-pointer select-none ml-2">
|
||||
<label className="flex items-center gap-1.5 text-xs text-muted-foreground cursor-pointer select-none ms-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={showCompleted}
|
||||
@@ -57,7 +57,7 @@ export function TaskToolbar({
|
||||
<div className="flex-1" />
|
||||
|
||||
<Button size="sm" onClick={onCreateTask}>
|
||||
<Plus className="w-4 h-4 mr-1" />
|
||||
<Plus className="w-4 h-4 me-1" />
|
||||
{t("tasks.create")}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user