[#77] added repetition proper display and editing
This commit is contained in:
@@ -6,18 +6,15 @@ import {
|
|||||||
MenuItem,
|
MenuItem,
|
||||||
Box,
|
Box,
|
||||||
Stack,
|
Stack,
|
||||||
Paper,
|
|
||||||
Typography,
|
Typography,
|
||||||
TextField,
|
TextField,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
List,
|
|
||||||
ListItem,
|
|
||||||
FormControlLabel,
|
FormControlLabel,
|
||||||
FormGroup,
|
FormGroup,
|
||||||
Radio,
|
Radio,
|
||||||
RadioGroup,
|
RadioGroup,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { RepetitionObject } from "../../features/Events/EventsTypes";
|
import { RepetitionObject } from "../../features/Events/EventsTypes";
|
||||||
|
|
||||||
export default function RepeatEvent({
|
export default function RepeatEvent({
|
||||||
@@ -29,23 +26,31 @@ export default function RepeatEvent({
|
|||||||
setRepetition: Function;
|
setRepetition: Function;
|
||||||
isOwn?: boolean;
|
isOwn?: boolean;
|
||||||
}) {
|
}) {
|
||||||
console.log(JSON.stringify(repetition));
|
|
||||||
|
|
||||||
const repetitionValues = ["day", "week", "month", "year"];
|
const repetitionValues = ["day", "week", "month", "year"];
|
||||||
const [interval, setInterval] = useState(repetition.interval ?? 0);
|
|
||||||
const [selectedDays, setSelectedDays] = useState<string[]>(
|
|
||||||
repetition.selectedDays ?? []
|
|
||||||
);
|
|
||||||
const [endOption, setEndOption] = useState("");
|
|
||||||
const [occurrences, setOccurrences] = useState(repetition.occurrences) ?? 0;
|
|
||||||
const [endDate, setEndDate] = useState(repetition.endDate ?? "");
|
|
||||||
const days = ["MO", "TU", "WE", "TH", "FR", "SA", "SU"];
|
const days = ["MO", "TU", "WE", "TH", "FR", "SA", "SU"];
|
||||||
|
|
||||||
const handleDayChange = (day: string) => {
|
// derive endOption based on repetition
|
||||||
setSelectedDays((prev: string[]) =>
|
const getEndOption = () => {
|
||||||
prev.includes(day) ? prev.filter((d) => d !== day) : [...prev, day]
|
if (repetition.occurrences && repetition.occurrences > 0) return "after";
|
||||||
);
|
if (repetition.endDate) return "on";
|
||||||
|
return "never";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const [endOption, setEndOption] = useState(getEndOption());
|
||||||
|
|
||||||
|
// keep endOption in sync if repetition changes from parent
|
||||||
|
useEffect(() => {
|
||||||
|
setEndOption(getEndOption());
|
||||||
|
}, [repetition.occurrences, repetition.endDate]);
|
||||||
|
|
||||||
|
const handleDayChange = (day: string) => {
|
||||||
|
const updatedDays = repetition.selectedDays?.includes(day)
|
||||||
|
? repetition.selectedDays.filter((d) => d !== day)
|
||||||
|
: [...(repetition.selectedDays ?? []), day];
|
||||||
|
|
||||||
|
setRepetition({ ...repetition, selectedDays: updatedDays });
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormControl fullWidth margin="dense" size="small">
|
<FormControl fullWidth margin="dense" size="small">
|
||||||
<InputLabel id="repeat">Repetition</InputLabel>
|
<InputLabel id="repeat">Repetition</InputLabel>
|
||||||
@@ -64,18 +69,24 @@ export default function RepeatEvent({
|
|||||||
<MenuItem value={"monthly"}>Repeat monthly</MenuItem>
|
<MenuItem value={"monthly"}>Repeat monthly</MenuItem>
|
||||||
<MenuItem value={"yearly"}>Repeat yearly</MenuItem>
|
<MenuItem value={"yearly"}>Repeat yearly</MenuItem>
|
||||||
</Select>
|
</Select>
|
||||||
|
|
||||||
{repetition.freq && (
|
{repetition.freq && (
|
||||||
<Stack>
|
<Stack>
|
||||||
|
{/* Interval */}
|
||||||
<Box display="flex" alignItems="center" gap={2} mb={2}>
|
<Box display="flex" alignItems="center" gap={2} mb={2}>
|
||||||
<Typography>Interval:</Typography>
|
<Typography>Interval:</Typography>
|
||||||
<TextField
|
<TextField
|
||||||
type="number"
|
type="number"
|
||||||
value={interval}
|
value={repetition.interval ?? 0}
|
||||||
onChange={(e) => setInterval(Number(e.target.value))}
|
onChange={(e) =>
|
||||||
|
setRepetition({
|
||||||
|
...repetition,
|
||||||
|
interval: Number(e.target.value),
|
||||||
|
})
|
||||||
|
}
|
||||||
size="small"
|
size="small"
|
||||||
sx={{ width: 80 }}
|
sx={{ width: 80 }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Typography>
|
<Typography>
|
||||||
{
|
{
|
||||||
repetitionValues[
|
repetitionValues[
|
||||||
@@ -84,6 +95,8 @@ export default function RepeatEvent({
|
|||||||
}
|
}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
{/* Weekly selection */}
|
||||||
{repetition.freq === "weekly" && (
|
{repetition.freq === "weekly" && (
|
||||||
<Box>
|
<Box>
|
||||||
<Typography variant="body2" gutterBottom>
|
<Typography variant="body2" gutterBottom>
|
||||||
@@ -95,7 +108,9 @@ export default function RepeatEvent({
|
|||||||
key={day}
|
key={day}
|
||||||
control={
|
control={
|
||||||
<Checkbox
|
<Checkbox
|
||||||
checked={selectedDays.includes(day)}
|
checked={
|
||||||
|
repetition.selectedDays?.includes(day) ?? false
|
||||||
|
}
|
||||||
onChange={() => handleDayChange(day)}
|
onChange={() => handleDayChange(day)}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
@@ -105,13 +120,38 @@ export default function RepeatEvent({
|
|||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* End options */}
|
||||||
<Box>
|
<Box>
|
||||||
<Typography variant="body2" gutterBottom sx={{ mt: 2 }}>
|
<Typography variant="body2" gutterBottom sx={{ mt: 2 }}>
|
||||||
End:
|
End:
|
||||||
</Typography>
|
</Typography>
|
||||||
<RadioGroup
|
<RadioGroup
|
||||||
value={endOption}
|
value={endOption}
|
||||||
onChange={(e) => setEndOption(e.target.value)}
|
onChange={(e) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
setEndOption(value);
|
||||||
|
|
||||||
|
if (value === "never") {
|
||||||
|
setRepetition({ ...repetition, occurrences: 0, endDate: "" });
|
||||||
|
}
|
||||||
|
if (value === "after") {
|
||||||
|
setRepetition({
|
||||||
|
freq: repetition.freq,
|
||||||
|
interval: repetition.interval,
|
||||||
|
occurence: Number(e.target.value),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (value === "on") {
|
||||||
|
setRepetition({
|
||||||
|
freq: repetition.freq,
|
||||||
|
interval: repetition.interval,
|
||||||
|
endDate: new Date(e.target.value)
|
||||||
|
.toISOString()
|
||||||
|
.slice(0, 16),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
value="never"
|
value="never"
|
||||||
@@ -128,8 +168,14 @@ export default function RepeatEvent({
|
|||||||
<TextField
|
<TextField
|
||||||
type="number"
|
type="number"
|
||||||
size="small"
|
size="small"
|
||||||
value={occurrences}
|
value={repetition.occurrences ?? 0}
|
||||||
onChange={(e) => setOccurrences(Number(e.target.value))}
|
onChange={(e) =>
|
||||||
|
setRepetition({
|
||||||
|
freq: repetition.freq,
|
||||||
|
interval: repetition.interval,
|
||||||
|
occurence: Number(e.target.value),
|
||||||
|
})
|
||||||
|
}
|
||||||
sx={{ width: 100 }}
|
sx={{ width: 100 }}
|
||||||
inputProps={{ min: 1 }}
|
inputProps={{ min: 1 }}
|
||||||
disabled={endOption !== "after"}
|
disabled={endOption !== "after"}
|
||||||
@@ -148,8 +194,14 @@ export default function RepeatEvent({
|
|||||||
<TextField
|
<TextField
|
||||||
type="date"
|
type="date"
|
||||||
size="small"
|
size="small"
|
||||||
value={endDate}
|
value={repetition.endDate ?? ""}
|
||||||
onChange={(e) => setEndDate(e.target.value)}
|
onChange={(e) =>
|
||||||
|
setRepetition({
|
||||||
|
freq: repetition.freq,
|
||||||
|
interval: repetition.interval,
|
||||||
|
endDate: e.target.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
disabled={endOption !== "on"}
|
disabled={endOption !== "on"}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -124,7 +124,8 @@ export default function EventDisplayModal({
|
|||||||
if (!event || !calendar) {
|
if (!event || !calendar) {
|
||||||
onClose({}, "backdropClick");
|
onClose({}, "backdropClick");
|
||||||
}
|
}
|
||||||
}, [open, eventId, dispatch, onClose]);
|
setRepetition(event.repetition ?? ({} as RepetitionObject));
|
||||||
|
}, [open, eventId, dispatch, onClose, event]);
|
||||||
|
|
||||||
if (!event || !calendar) return null;
|
if (!event || !calendar) return null;
|
||||||
|
|
||||||
@@ -224,17 +225,30 @@ export default function EventDisplayModal({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal open={open} onClose={onClose}>
|
<Modal open={open} onClose={onClose}>
|
||||||
<Card sx={{ minWidth: 300, width: "50vw", p: 2, position: "absolute" }}>
|
<Box
|
||||||
|
sx={{
|
||||||
|
position: "absolute",
|
||||||
|
top: "5vh",
|
||||||
|
left: "50%",
|
||||||
|
transform: "translate(-50%, -50%)",
|
||||||
|
width: "50vw",
|
||||||
|
maxHeight: "80vh",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Card sx={{ p: 2, position: "absolute" }}>
|
||||||
{/* Close button */}
|
{/* Close button */}
|
||||||
<Box sx={{ position: "absolute", top: 8, right: 8 }}>
|
<Box sx={{ position: "absolute", top: 8, right: 8 }}>
|
||||||
<IconButton size="small" onClick={() => onClose({}, "backdropClick")}>
|
<IconButton
|
||||||
|
size="small"
|
||||||
|
onClick={() => onClose({}, "backdropClick")}
|
||||||
|
>
|
||||||
<CloseIcon fontSize="small" />
|
<CloseIcon fontSize="small" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<CardHeader title={isOwn ? "Edit Event" : "Event Details"} />
|
<CardHeader title={isOwn ? "Edit Event" : "Event Details"} />
|
||||||
|
|
||||||
<CardContent sx={{ overflow: "auto" }}>
|
<CardContent sx={{ maxHeight: "75vh", overflow: "auto" }}>
|
||||||
{/* Title */}
|
{/* Title */}
|
||||||
<TextField
|
<TextField
|
||||||
fullWidth
|
fullWidth
|
||||||
@@ -458,7 +472,9 @@ export default function EventDisplayModal({
|
|||||||
labelId="alarm"
|
labelId="alarm"
|
||||||
value={alarm}
|
value={alarm}
|
||||||
disabled={!isOwn}
|
disabled={!isOwn}
|
||||||
onChange={(e: SelectChangeEvent) => setAlarm(e.target.value)}
|
onChange={(e: SelectChangeEvent) =>
|
||||||
|
setAlarm(e.target.value)
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<MenuItem value={""}>No Alarm</MenuItem>
|
<MenuItem value={""}>No Alarm</MenuItem>
|
||||||
<MenuItem value={"-PT1M"}>1 minute</MenuItem>
|
<MenuItem value={"-PT1M"}>1 minute</MenuItem>
|
||||||
@@ -533,6 +549,7 @@ export default function EventDisplayModal({
|
|||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
</CardActions>
|
</CardActions>
|
||||||
</Card>
|
</Card>
|
||||||
|
</Box>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,18 +84,21 @@ export function parseCalendarEvent(
|
|||||||
break;
|
break;
|
||||||
case "rrule":
|
case "rrule":
|
||||||
event.repetition = { freq: value.freq.toLowerCase() };
|
event.repetition = { freq: value.freq.toLowerCase() };
|
||||||
|
console.log(value);
|
||||||
if (value.byday) {
|
if (value.byday) {
|
||||||
|
console.log(value.byday);
|
||||||
event.repetition.selectedDays = value.byday;
|
event.repetition.selectedDays = value.byday;
|
||||||
}
|
}
|
||||||
if (value.until) {
|
if (value.until) {
|
||||||
event.repetition.selectedDays = value.endDate;
|
event.repetition.endDate = value.until;
|
||||||
}
|
}
|
||||||
if (value.count) {
|
if (value.count) {
|
||||||
event.repetition.selectedDays = value.occurrences;
|
event.repetition.occurrences = value.count;
|
||||||
}
|
}
|
||||||
if (value.interval) {
|
if (value.interval) {
|
||||||
event.repetition.interval = value.interval;
|
event.repetition.interval = value.interval;
|
||||||
}
|
}
|
||||||
|
console.log(event.repetition);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user