UI/update recurring event section (#544)
* Update global recurring event style * #538 update date selector consistance * update test cases
This commit is contained in:
@@ -111,7 +111,9 @@ async function setupEventPopover(
|
|||||||
|
|
||||||
// Wait for RepeatEvent component to be rendered
|
// Wait for RepeatEvent component to be rendered
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(screen.getByText("event.repeat.frequency.days")).toBeInTheDocument();
|
expect(
|
||||||
|
screen.getByText("event.repeat.frequency.weeks")
|
||||||
|
).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,8 +188,8 @@ describe("RepeatEvent Component", () => {
|
|||||||
it("toggles day selection for weekly frequency", () => {
|
it("toggles day selection for weekly frequency", () => {
|
||||||
const { setRepetition } = setupRepeatEvent({ freq: "weekly" });
|
const { setRepetition } = setupRepeatEvent({ freq: "weekly" });
|
||||||
|
|
||||||
const mondayCheckbox = screen.getByLabelText("event.repeat.days.monday");
|
const mondayChip = screen.getByLabelText("event.repeat.days.monday");
|
||||||
fireEvent.click(mondayCheckbox);
|
fireEvent.click(mondayChip);
|
||||||
|
|
||||||
expect(setRepetition).toHaveBeenCalledWith(
|
expect(setRepetition).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({ byday: ["MO"] })
|
expect.objectContaining({ byday: ["MO"] })
|
||||||
@@ -208,7 +210,7 @@ describe("Repeat Event Integration Tests", () => {
|
|||||||
|
|
||||||
// When Repeat checkbox is checked, repetition is set to empty object
|
// When Repeat checkbox is checked, repetition is set to empty object
|
||||||
// We need to set the frequency manually
|
// We need to set the frequency manually
|
||||||
const frequencySelect = screen.getByText("event.repeat.frequency.days");
|
const frequencySelect = screen.getByText("event.repeat.frequency.weeks");
|
||||||
fireEvent.mouseDown(frequencySelect);
|
fireEvent.mouseDown(frequencySelect);
|
||||||
const dailyOption = screen.getByRole("option", {
|
const dailyOption = screen.getByRole("option", {
|
||||||
name: "event.repeat.frequency.days",
|
name: "event.repeat.frequency.days",
|
||||||
@@ -222,6 +224,14 @@ describe("Repeat Event Integration Tests", () => {
|
|||||||
it("sends correct API payload for repeat daily with 2 day interval", async () => {
|
it("sends correct API payload for repeat daily with 2 day interval", async () => {
|
||||||
await setupEventPopover();
|
await setupEventPopover();
|
||||||
|
|
||||||
|
// Ensure frequency is daily
|
||||||
|
const frequencySelect = screen.getByText("event.repeat.frequency.weeks");
|
||||||
|
fireEvent.mouseDown(frequencySelect);
|
||||||
|
const dailyOption = screen.getByRole("option", {
|
||||||
|
name: "event.repeat.frequency.days",
|
||||||
|
});
|
||||||
|
fireEvent.click(dailyOption);
|
||||||
|
|
||||||
// Set interval to 2
|
// Set interval to 2
|
||||||
const intervalInput = screen.getByDisplayValue("1");
|
const intervalInput = screen.getByDisplayValue("1");
|
||||||
fireEvent.change(intervalInput, { target: { value: "2" } });
|
fireEvent.change(intervalInput, { target: { value: "2" } });
|
||||||
@@ -233,6 +243,14 @@ describe("Repeat Event Integration Tests", () => {
|
|||||||
it("sends correct API payload for repeat daily for 5 repetitions", async () => {
|
it("sends correct API payload for repeat daily for 5 repetitions", async () => {
|
||||||
await setupEventPopover();
|
await setupEventPopover();
|
||||||
|
|
||||||
|
// Ensure frequency is daily
|
||||||
|
const frequencySelect = screen.getByText("event.repeat.frequency.weeks");
|
||||||
|
fireEvent.mouseDown(frequencySelect);
|
||||||
|
const dailyOption = screen.getByRole("option", {
|
||||||
|
name: "event.repeat.frequency.days",
|
||||||
|
});
|
||||||
|
fireEvent.click(dailyOption);
|
||||||
|
|
||||||
// Select "After" end option
|
// Select "After" end option
|
||||||
const afterRadio = screen.getByLabelText(/after/i);
|
const afterRadio = screen.getByLabelText(/after/i);
|
||||||
fireEvent.click(afterRadio);
|
fireEvent.click(afterRadio);
|
||||||
@@ -248,17 +266,26 @@ describe("Repeat Event Integration Tests", () => {
|
|||||||
it("sends correct API payload for repeat daily until specific date", async () => {
|
it("sends correct API payload for repeat daily until specific date", async () => {
|
||||||
await setupEventPopover();
|
await setupEventPopover();
|
||||||
|
|
||||||
|
// Ensure frequency is daily
|
||||||
|
const frequencySelect = screen.getByText("event.repeat.frequency.weeks");
|
||||||
|
fireEvent.mouseDown(frequencySelect);
|
||||||
|
const dailyOption = screen.getByRole("option", {
|
||||||
|
name: "event.repeat.frequency.days",
|
||||||
|
});
|
||||||
|
fireEvent.click(dailyOption);
|
||||||
|
|
||||||
// Select "On" end option
|
// Select "On" end option
|
||||||
const onRadio = screen
|
const onRadio = screen
|
||||||
.getAllByLabelText(/on/i)
|
.getAllByLabelText(/on/i)
|
||||||
.find((el) => el.type === "radio");
|
.find((el) => el.type === "radio");
|
||||||
fireEvent.click(onRadio!);
|
fireEvent.click(onRadio!);
|
||||||
|
|
||||||
// Set end date
|
// End date is set by UI to some valid date string (YYYY-MM-DD)
|
||||||
const endDateInput = screen.getByTestId("end-date");
|
await expectRRule({
|
||||||
fireEvent.change(endDateInput, { target: { value: "2025-12-31" } });
|
freq: "daily",
|
||||||
|
interval: 1,
|
||||||
await expectRRule({ freq: "daily", interval: 1, endDate: "2025-12-31" });
|
endDate: expect.any(String),
|
||||||
|
});
|
||||||
expect(mockOnClose).toHaveBeenCalledWith(true);
|
expect(mockOnClose).toHaveBeenCalledWith(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -266,7 +293,7 @@ describe("Repeat Event Integration Tests", () => {
|
|||||||
await setupEventPopover();
|
await setupEventPopover();
|
||||||
|
|
||||||
// Select Week(s) frequency
|
// Select Week(s) frequency
|
||||||
const frequencySelect = screen.getByText("event.repeat.frequency.days");
|
const frequencySelect = screen.getByText("event.repeat.frequency.weeks");
|
||||||
fireEvent.mouseDown(frequencySelect);
|
fireEvent.mouseDown(frequencySelect);
|
||||||
const weeklyOption = screen.getByRole("option", {
|
const weeklyOption = screen.getByRole("option", {
|
||||||
name: "event.repeat.frequency.weeks",
|
name: "event.repeat.frequency.weeks",
|
||||||
@@ -291,7 +318,7 @@ describe("Repeat Event Integration Tests", () => {
|
|||||||
await setupEventPopover();
|
await setupEventPopover();
|
||||||
|
|
||||||
// Select Week(s) frequency
|
// Select Week(s) frequency
|
||||||
const frequencySelect = screen.getByText("event.repeat.frequency.days");
|
const frequencySelect = screen.getByText("event.repeat.frequency.weeks");
|
||||||
fireEvent.mouseDown(frequencySelect);
|
fireEvent.mouseDown(frequencySelect);
|
||||||
const weeklyOption = screen.getByRole("option", {
|
const weeklyOption = screen.getByRole("option", {
|
||||||
name: "event.repeat.frequency.weeks",
|
name: "event.repeat.frequency.weeks",
|
||||||
@@ -310,7 +337,7 @@ describe("Repeat Event Integration Tests", () => {
|
|||||||
await setupEventPopover();
|
await setupEventPopover();
|
||||||
|
|
||||||
// Select Month(s) frequency
|
// Select Month(s) frequency
|
||||||
const frequencySelect = screen.getByText("event.repeat.frequency.days");
|
const frequencySelect = screen.getByText("event.repeat.frequency.weeks");
|
||||||
fireEvent.mouseDown(frequencySelect);
|
fireEvent.mouseDown(frequencySelect);
|
||||||
const monthlyOption = screen.getByRole("option", {
|
const monthlyOption = screen.getByRole("option", {
|
||||||
name: "event.repeat.frequency.months",
|
name: "event.repeat.frequency.months",
|
||||||
@@ -325,7 +352,7 @@ describe("Repeat Event Integration Tests", () => {
|
|||||||
await setupEventPopover();
|
await setupEventPopover();
|
||||||
|
|
||||||
// Select Month(s) frequency
|
// Select Month(s) frequency
|
||||||
const frequencySelect = screen.getByText("event.repeat.frequency.days");
|
const frequencySelect = screen.getByText("event.repeat.frequency.weeks");
|
||||||
fireEvent.mouseDown(frequencySelect);
|
fireEvent.mouseDown(frequencySelect);
|
||||||
const monthlyOption = screen.getByRole("option", {
|
const monthlyOption = screen.getByRole("option", {
|
||||||
name: "event.repeat.frequency.months",
|
name: "event.repeat.frequency.months",
|
||||||
@@ -348,7 +375,7 @@ describe("Repeat Event Integration Tests", () => {
|
|||||||
await setupEventPopover();
|
await setupEventPopover();
|
||||||
|
|
||||||
// Select Year(s) frequency
|
// Select Year(s) frequency
|
||||||
const frequencySelect = screen.getByText("event.repeat.frequency.days");
|
const frequencySelect = screen.getByText("event.repeat.frequency.weeks");
|
||||||
fireEvent.mouseDown(frequencySelect);
|
fireEvent.mouseDown(frequencySelect);
|
||||||
const yearlyOption = screen.getByRole("option", {
|
const yearlyOption = screen.getByRole("option", {
|
||||||
name: "event.repeat.frequency.years",
|
name: "event.repeat.frequency.years",
|
||||||
@@ -363,7 +390,7 @@ describe("Repeat Event Integration Tests", () => {
|
|||||||
await setupEventPopover();
|
await setupEventPopover();
|
||||||
|
|
||||||
// Select Year(s) frequency
|
// Select Year(s) frequency
|
||||||
const frequencySelect = screen.getByText("event.repeat.frequency.days");
|
const frequencySelect = screen.getByText("event.repeat.frequency.weeks");
|
||||||
fireEvent.mouseDown(frequencySelect);
|
fireEvent.mouseDown(frequencySelect);
|
||||||
const yearlyOption = screen.getByRole("option", {
|
const yearlyOption = screen.getByRole("option", {
|
||||||
name: "event.repeat.frequency.years",
|
name: "event.repeat.frequency.years",
|
||||||
|
|||||||
@@ -699,7 +699,7 @@ describe("Edit Recurring Event in Full Display", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
fireEvent.click(screen.getByRole("button", { name: "common.moreOptions" }));
|
fireEvent.click(screen.getByRole("button", { name: "common.moreOptions" }));
|
||||||
expect(screen.getByText("event.repeat.repeatEvery")).toBeInTheDocument();
|
expect(screen.getByText("event.repeat.every")).toBeInTheDocument();
|
||||||
expect(screen.getByText("event.repeat.end.label")).toBeInTheDocument();
|
expect(screen.getByText("event.repeat.end.label")).toBeInTheDocument();
|
||||||
|
|
||||||
const frequencySelect = screen.getByRole("radio", {
|
const frequencySelect = screen.getByRole("radio", {
|
||||||
|
|||||||
@@ -539,12 +539,16 @@ export default function EventFormFields({
|
|||||||
const newShowRepeat = !showRepeat;
|
const newShowRepeat = !showRepeat;
|
||||||
setShowRepeat(newShowRepeat);
|
setShowRepeat(newShowRepeat);
|
||||||
if (newShowRepeat) {
|
if (newShowRepeat) {
|
||||||
|
const days = ["MO", "TU", "WE", "TH", "FR", "SA", "SU"];
|
||||||
|
const eventStartDate = new Date(start);
|
||||||
|
const jsDay = eventStartDate.getDay();
|
||||||
|
const icsDay = days[(jsDay + 6) % 7];
|
||||||
setRepetition({
|
setRepetition({
|
||||||
freq: "daily",
|
freq: "weekly",
|
||||||
interval: 1,
|
interval: 1,
|
||||||
occurrences: 0,
|
occurrences: 0,
|
||||||
endDate: "",
|
endDate: "",
|
||||||
byday: null,
|
byday: [icsDay],
|
||||||
} as RepetitionObject);
|
} as RepetitionObject);
|
||||||
} else {
|
} else {
|
||||||
setRepetition({
|
setRepetition({
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import { RepetitionObject } from "@/features/Events/EventsTypes";
|
import { RepetitionObject } from "@/features/Events/EventsTypes";
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Checkbox,
|
|
||||||
FormControl,
|
FormControl,
|
||||||
FormControlLabel,
|
FormControlLabel,
|
||||||
FormGroup,
|
|
||||||
MenuItem,
|
MenuItem,
|
||||||
Radio,
|
Radio,
|
||||||
RadioGroup,
|
RadioGroup,
|
||||||
@@ -14,8 +12,18 @@ import {
|
|||||||
TextField,
|
TextField,
|
||||||
Typography,
|
Typography,
|
||||||
} from "@linagora/twake-mui";
|
} from "@linagora/twake-mui";
|
||||||
|
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
|
||||||
|
import { DatePicker } from "@mui/x-date-pickers/DatePicker";
|
||||||
|
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import "dayjs/locale/en";
|
||||||
|
import "dayjs/locale/fr";
|
||||||
|
import "dayjs/locale/ru";
|
||||||
|
import "dayjs/locale/vi";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useI18n } from "twake-i18n";
|
import { useI18n } from "twake-i18n";
|
||||||
|
import { ReadOnlyDateField } from "./components/ReadOnlyPickerField";
|
||||||
|
import { LONG_DATE_FORMAT } from "./utils/dateTimeFormatters";
|
||||||
|
|
||||||
export default function RepeatEvent({
|
export default function RepeatEvent({
|
||||||
repetition,
|
repetition,
|
||||||
@@ -31,6 +39,13 @@ export default function RepeatEvent({
|
|||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const days = ["MO", "TU", "WE", "TH", "FR", "SA", "SU"];
|
const days = ["MO", "TU", "WE", "TH", "FR", "SA", "SU"];
|
||||||
const day = new Date(eventStart);
|
const day = new Date(eventStart);
|
||||||
|
const dateCalendarLayoutSx = {
|
||||||
|
"& .MuiDateCalendar-root.MuiDateCalendar-root": {
|
||||||
|
width: "260px",
|
||||||
|
maxWidth: "260px",
|
||||||
|
padding: "0 15px",
|
||||||
|
},
|
||||||
|
};
|
||||||
// derive endOption based on repetition
|
// derive endOption based on repetition
|
||||||
const getEndOption = () => {
|
const getEndOption = () => {
|
||||||
if (repetition.occurrences && repetition.occurrences > 0) return "after";
|
if (repetition.occurrences && repetition.occurrences > 0) return "after";
|
||||||
@@ -79,8 +94,8 @@ export default function RepeatEvent({
|
|||||||
<Box>
|
<Box>
|
||||||
<Stack>
|
<Stack>
|
||||||
{/* Interval */}
|
{/* Interval */}
|
||||||
<Box display="flex" alignItems="center" gap={2} mb={2}>
|
<Box display="flex" alignItems="center" gap={2} mb={1}>
|
||||||
<Typography variant="h6">{t("event.repeat.repeatEvery")}</Typography>
|
<Typography variant="h6">{t("event.repeat.every")}</Typography>
|
||||||
<TextField
|
<TextField
|
||||||
type="number"
|
type="number"
|
||||||
value={repetition.interval ?? 1}
|
value={repetition.interval ?? 1}
|
||||||
@@ -93,7 +108,13 @@ export default function RepeatEvent({
|
|||||||
}
|
}
|
||||||
size="small"
|
size="small"
|
||||||
style={{ width: 80 }}
|
style={{ width: 80 }}
|
||||||
inputProps={{ min: 1 }}
|
inputProps={{
|
||||||
|
min: 1,
|
||||||
|
style: {
|
||||||
|
textAlign: "center",
|
||||||
|
paddingRight: 5,
|
||||||
|
},
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<FormControl size="small" style={{ minWidth: 120 }}>
|
<FormControl size="small" style={{ minWidth: 120 }}>
|
||||||
<Select
|
<Select
|
||||||
@@ -137,25 +158,52 @@ export default function RepeatEvent({
|
|||||||
|
|
||||||
{/* Weekly selection */}
|
{/* Weekly selection */}
|
||||||
{repetition.freq === "weekly" && (
|
{repetition.freq === "weekly" && (
|
||||||
<Box>
|
<Box mb={2}>
|
||||||
<Typography variant="body2" gutterBottom>
|
<Box display="flex" gap={1}>
|
||||||
{t("event.repeat.repeatOn")}
|
{days.map((dayCode) => {
|
||||||
</Typography>
|
const isSelected = repetition.byday?.includes(dayCode) ?? false;
|
||||||
<FormGroup row>
|
const fullLabel = getDayLabel(dayCode);
|
||||||
{days.map((day) => (
|
const label = fullLabel.charAt(0);
|
||||||
<FormControlLabel
|
|
||||||
key={day}
|
return (
|
||||||
disabled={!isOwn}
|
<Box
|
||||||
control={
|
key={dayCode}
|
||||||
<Checkbox
|
role="button"
|
||||||
checked={repetition.byday?.includes(day) ?? false}
|
aria-label={fullLabel}
|
||||||
onChange={() => handleDayChange(day)}
|
onClick={() => {
|
||||||
/>
|
if (!isOwn) return;
|
||||||
}
|
handleDayChange(dayCode);
|
||||||
label={getDayLabel(day)}
|
}}
|
||||||
/>
|
sx={{
|
||||||
))}
|
width: 40,
|
||||||
</FormGroup>
|
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>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -168,6 +216,8 @@ export default function RepeatEvent({
|
|||||||
value={endOption}
|
value={endOption}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const value = e.target.value;
|
const value = e.target.value;
|
||||||
|
if (value === endOption) return;
|
||||||
|
|
||||||
setEndOption(value);
|
setEndOption(value);
|
||||||
|
|
||||||
if (value === "never") {
|
if (value === "never") {
|
||||||
@@ -191,7 +241,8 @@ export default function RepeatEvent({
|
|||||||
setRepetition({
|
setRepetition({
|
||||||
...repetition,
|
...repetition,
|
||||||
occurrences: null,
|
occurrences: null,
|
||||||
endDate: new Date().toISOString().slice(0, 16),
|
endDate:
|
||||||
|
repetition.endDate ?? new Date().toISOString().slice(0, 10),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
@@ -209,15 +260,102 @@ export default function RepeatEvent({
|
|||||||
|
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
disabled={!isOwn}
|
disabled={!isOwn}
|
||||||
value="after"
|
value="on"
|
||||||
|
sx={{ mt: 1 }}
|
||||||
control={<Radio />}
|
control={<Radio />}
|
||||||
label={
|
label={
|
||||||
<Box display="flex" alignItems="center" gap={1}>
|
<Box display="flex" alignItems="center" gap={1}>
|
||||||
|
<Typography variant="h6">
|
||||||
|
{t("event.repeat.end.on")}
|
||||||
|
</Typography>
|
||||||
|
<LocalizationProvider
|
||||||
|
dateAdapter={AdapterDayjs}
|
||||||
|
adapterLocale={t("locale") ?? "en"}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: 220,
|
||||||
|
"& .MuiInputBase-root": { fontSize: 14 },
|
||||||
|
"& .MuiInputBase-input": { fontSize: 14 },
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DatePicker
|
||||||
|
sx={{ width: "100%" }}
|
||||||
|
format={LONG_DATE_FORMAT}
|
||||||
|
value={
|
||||||
|
repetition.endDate ? dayjs(repetition.endDate) : null
|
||||||
|
}
|
||||||
|
onChange={(value) => {
|
||||||
|
if (!value || !value.isValid()) return;
|
||||||
|
const newDateStr = value.format("YYYY-MM-DD");
|
||||||
|
setRepetition({
|
||||||
|
...repetition,
|
||||||
|
occurrences: null,
|
||||||
|
endDate: newDateStr,
|
||||||
|
});
|
||||||
|
if (endOption !== "on") {
|
||||||
|
setEndOption("on");
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onOpen={() => {
|
||||||
|
if (!isOwn || endOption === "on") return;
|
||||||
|
setEndOption("on");
|
||||||
|
if (!repetition.endDate) {
|
||||||
|
setRepetition({
|
||||||
|
...repetition,
|
||||||
|
occurrences: null,
|
||||||
|
endDate: new Date().toISOString().slice(0, 10),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setRepetition({
|
||||||
|
...repetition,
|
||||||
|
occurrences: null,
|
||||||
|
endDate: repetition.endDate,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
slots={{ field: ReadOnlyDateField }}
|
||||||
|
slotProps={{
|
||||||
|
field: {},
|
||||||
|
layout: { sx: dateCalendarLayoutSx },
|
||||||
|
}}
|
||||||
|
disabled={!isOwn}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</LocalizationProvider>
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormControlLabel
|
||||||
|
disabled={!isOwn}
|
||||||
|
value="after"
|
||||||
|
control={<Radio />}
|
||||||
|
sx={{ mt: 1 }}
|
||||||
|
label={
|
||||||
|
<Box
|
||||||
|
display="flex"
|
||||||
|
alignItems="center"
|
||||||
|
gap={1}
|
||||||
|
onClick={() => {
|
||||||
|
if (!isOwn || endOption === "after") return;
|
||||||
|
setEndOption("after");
|
||||||
|
setRepetition({
|
||||||
|
...repetition,
|
||||||
|
endDate: null,
|
||||||
|
occurrences:
|
||||||
|
repetition.occurrences && repetition.occurrences > 0
|
||||||
|
? repetition.occurrences
|
||||||
|
: 1,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Typography variant="h6">
|
<Typography variant="h6">
|
||||||
{t("event.repeat.end.after")}
|
{t("event.repeat.end.after")}
|
||||||
</Typography>
|
</Typography>
|
||||||
<TextField
|
<TextField
|
||||||
type="number"
|
type="number"
|
||||||
|
inputProps={{ min: 1, "data-testid": "occurrences-input" }}
|
||||||
size="small"
|
size="small"
|
||||||
value={repetition.occurrences ?? 1}
|
value={repetition.occurrences ?? 1}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
@@ -227,10 +365,12 @@ export default function RepeatEvent({
|
|||||||
endDate: null,
|
endDate: null,
|
||||||
occurrences: value > 0 ? value : 1,
|
occurrences: value > 0 ? value : 1,
|
||||||
});
|
});
|
||||||
|
if (endOption !== "after") {
|
||||||
|
setEndOption("after");
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
style={{ width: 100 }}
|
style={{ width: 100 }}
|
||||||
inputProps={{ min: 1, "data-testid": "occurrences-input" }}
|
disabled={!isOwn}
|
||||||
disabled={!isOwn || endOption !== "after"}
|
|
||||||
/>
|
/>
|
||||||
<Typography variant="h6">
|
<Typography variant="h6">
|
||||||
{t("event.repeat.end.occurrences")}
|
{t("event.repeat.end.occurrences")}
|
||||||
@@ -238,33 +378,6 @@ export default function RepeatEvent({
|
|||||||
</Box>
|
</Box>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FormControlLabel
|
|
||||||
disabled={!isOwn}
|
|
||||||
value="on"
|
|
||||||
control={<Radio />}
|
|
||||||
label={
|
|
||||||
<Box display="flex" alignItems="center" gap={1}>
|
|
||||||
<Typography variant="h6">
|
|
||||||
{t("event.repeat.end.on")}
|
|
||||||
</Typography>
|
|
||||||
<TextField
|
|
||||||
type="date"
|
|
||||||
inputProps={{ "data-testid": "end-date" }}
|
|
||||||
size="small"
|
|
||||||
value={repetition.endDate ?? ""}
|
|
||||||
onChange={(e) =>
|
|
||||||
setRepetition({
|
|
||||||
...repetition,
|
|
||||||
occurrences: null,
|
|
||||||
endDate: e.target.value,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
disabled={!isOwn || endOption !== "on"}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
+3
-3
@@ -113,10 +113,10 @@
|
|||||||
"sunday": "SU"
|
"sunday": "SU"
|
||||||
},
|
},
|
||||||
"end": {
|
"end": {
|
||||||
"label": "End:",
|
"label": "How many times to repeat",
|
||||||
"never": "Never",
|
"never": "Always",
|
||||||
"after": "After",
|
"after": "After",
|
||||||
"on": "On",
|
"on": "Until",
|
||||||
"occurrences": "occurrences"
|
"occurrences": "occurrences"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
+3
-3
@@ -115,10 +115,10 @@
|
|||||||
"sunday": "ВС"
|
"sunday": "ВС"
|
||||||
},
|
},
|
||||||
"end": {
|
"end": {
|
||||||
"label": "Окончание:",
|
"label": "Сколько раз повторить",
|
||||||
"never": "Никогда",
|
"never": "Всегда",
|
||||||
"after": "После",
|
"after": "После",
|
||||||
"on": "В",
|
"on": "До",
|
||||||
"occurrences": "повторений"
|
"occurrences": "повторений"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
+9
-9
@@ -104,19 +104,19 @@
|
|||||||
"doesNotRepeat": "Không lặp lại",
|
"doesNotRepeat": "Không lặp lại",
|
||||||
"every": "Mỗi",
|
"every": "Mỗi",
|
||||||
"days": {
|
"days": {
|
||||||
"monday": "Th 2",
|
"monday": "Hai",
|
||||||
"tuesday": "Th 3",
|
"tuesday": "Ba",
|
||||||
"wednesday": "Th 4",
|
"wednesday": "Tư",
|
||||||
"thursday": "Th 5",
|
"thursday": "Năm",
|
||||||
"friday": "Th 6",
|
"friday": "Sáu",
|
||||||
"saturday": "Th 7",
|
"saturday": "Bảy",
|
||||||
"sunday": "CN"
|
"sunday": "CN"
|
||||||
},
|
},
|
||||||
"end": {
|
"end": {
|
||||||
"label": "Kết thúc:",
|
"label": "Lặp lại bao nhiêu lần",
|
||||||
"never": "Không bao giờ",
|
"never": "Luôn luôn",
|
||||||
"after": "Sau",
|
"after": "Sau",
|
||||||
"on": "Vào ngày",
|
"on": "Đến khi",
|
||||||
"occurrences": "lần"
|
"occurrences": "lần"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user