587 option hide show non working days (#613)

Co-authored-by: Camille Moussu <cmoussu@linagora.com>
This commit is contained in:
Camille Moussu
2026-03-14 06:39:27 +01:00
committed by GitHub
parent 57f9693892
commit c16e59c7fa
13 changed files with 1087 additions and 404 deletions
+16 -70
View File
@@ -23,6 +23,7 @@ import "dayjs/locale/vi";
import { useI18n } from "twake-i18n";
import { ReadOnlyDateField } from "./components/ReadOnlyPickerField";
import { LONG_DATE_FORMAT } from "./utils/dateTimeFormatters";
import { FC_DAYS, WeekDaySelector } from "./WeekDaySelector";
export default function RepeatEvent({
repetition,
@@ -57,31 +58,6 @@ export default function RepeatEvent({
const defaultEndDate = dayjs(eventStart).add(1, "day").format("YYYY-MM-DD");
const handleDayChange = (dayCode: string) => {
const currentDays = repetition.byday || [];
const updatedDays = currentDays.includes(dayCode)
? currentDays.filter((d) => d !== dayCode)
: [...currentDays, dayCode];
setRepetition({
...repetition,
byday: updatedDays.length > 0 ? updatedDays : null,
});
};
const getDayLabel = (day: string) => {
const dayMap: { [key: string]: string } = {
MO: t("event.repeat.days.monday"),
TU: t("event.repeat.days.tuesday"),
WE: t("event.repeat.days.wednesday"),
TH: t("event.repeat.days.thursday"),
FR: t("event.repeat.days.friday"),
SA: t("event.repeat.days.saturday"),
SU: t("event.repeat.days.sunday"),
};
return dayMap[day] || day;
};
return (
<Box>
<Stack>
@@ -150,51 +126,21 @@ export default function RepeatEvent({
{/* Weekly selection */}
{repetition.freq === "weekly" && (
<Box mb={2}>
<Box display="flex" gap={1}>
{days.map((dayCode) => {
const isSelected = repetition.byday?.includes(dayCode) ?? false;
const fullLabel = getDayLabel(dayCode);
const label = fullLabel.charAt(0);
return (
<Box
key={dayCode}
role="button"
aria-label={fullLabel}
onClick={() => {
if (!isOwn) return;
handleDayChange(dayCode);
}}
sx={{
width: 40,
height: 40,
borderRadius: "4px",
border: "1px solid",
borderColor: isSelected ? "primary.main" : "#AEAEC0",
color: isSelected ? "#fff" : "#8C9CAF",
fontSize: 16,
fontWeight: 400,
lineHeight: "24px",
display: "flex",
alignItems: "center",
justifyContent: "center",
textAlign: "center",
bgcolor: isSelected ? "primary.main" : "transparent",
cursor: isOwn ? "pointer" : "default",
"&:hover": isOwn
? {
borderColor: "primary.main",
bgcolor: "primary.main",
color: "#fff",
}
: undefined,
}}
>
{label}
</Box>
);
})}
</Box>
<WeekDaySelector
selectedDays={(repetition.byday ?? [])
.map((ics) => FC_DAYS.find((d) => d.ics === ics)?.fc ?? -1)
.filter((d) => d !== -1)}
onChange={(fcDays) => {
const icsDays = fcDays
.map((fc) => FC_DAYS.find((d) => d.fc === fc)?.ics ?? "")
.filter(Boolean);
setRepetition({
...repetition,
byday: icsDays.length > 0 ? icsDays : null,
});
}}
disabled={!isOwn}
/>
</Box>
)}
+92
View File
@@ -0,0 +1,92 @@
import { Box } from "@linagora/twake-mui";
import { useI18n } from "twake-i18n";
interface WeekDaySelectorProps {
selectedDays: number[]; // FullCalendar format: 0=Sun, 1=Mon...
onChange: (days: number[]) => void;
disabled?: boolean;
}
export const FC_DAYS = [
{ fc: 1, ics: "MO" },
{ fc: 2, ics: "TU" },
{ fc: 3, ics: "WE" },
{ fc: 4, ics: "TH" },
{ fc: 5, ics: "FR" },
{ fc: 6, ics: "SA" },
{ fc: 0, ics: "SU" },
];
export function WeekDaySelector({
selectedDays,
onChange,
disabled,
}: WeekDaySelectorProps) {
const { t } = useI18n();
const getDayLabel = (ics: string) => {
const dayMap: Record<string, string> = {
MO: t("event.repeat.days.monday"),
TU: t("event.repeat.days.tuesday"),
WE: t("event.repeat.days.wednesday"),
TH: t("event.repeat.days.thursday"),
FR: t("event.repeat.days.friday"),
SA: t("event.repeat.days.saturday"),
SU: t("event.repeat.days.sunday"),
};
return dayMap[ics] || ics;
};
const handleToggle = (fcDay: number) => {
if (disabled) return;
const updated = selectedDays.includes(fcDay)
? selectedDays.filter((d) => d !== fcDay)
: [...selectedDays, fcDay];
onChange(updated);
};
return (
<Box display="flex" gap={1}>
{FC_DAYS.map(({ fc, ics }) => {
const isSelected = selectedDays.includes(fc);
const fullLabel = getDayLabel(ics);
return (
<Box
component="button"
type="button"
key={ics}
aria-label={fullLabel}
aria-pressed={isSelected}
onClick={() => handleToggle(fc)}
disabled={disabled}
sx={{
width: 40,
height: 40,
borderRadius: "4px",
border: "1px solid",
borderColor: isSelected ? "primary.main" : "#AEAEC0",
color: isSelected ? "#fff" : "#8C9CAF",
fontSize: 16,
fontWeight: 400,
display: "flex",
alignItems: "center",
justifyContent: "center",
bgcolor: isSelected ? "primary.main" : "transparent",
cursor: disabled ? "default" : "pointer",
"&:hover": !disabled
? {
borderColor: "primary.main",
bgcolor: "primary.main",
color: "#fff",
}
: undefined,
}}
>
{fullLabel.charAt(0)}
</Box>
);
})}
</Box>
);
}