From ee50d47bcfc73d66a524c1963dc25eea1ddecf0b Mon Sep 17 00:00:00 2001 From: Christian Gawron Date: Mon, 7 Oct 2024 10:06:44 +0200 Subject: [PATCH] fix: sonarqube issues - fixed various issues spotted by sonarqube --- client/public/locales/de/translation.json | 6 +- client/public/locales/en/translation.json | 4 +- client/src/index.tsx | 5 - client/src/pages/Booking.tsx | 12 +- client/src/pages/CalendarInt.tsx | 16 +- client/src/pages/EditEvent.tsx | 6 +- client/src/pages/Schedule.tsx | 487 ---------------------- 7 files changed, 23 insertions(+), 513 deletions(-) delete mode 100644 client/src/pages/Schedule.tsx diff --git a/client/public/locales/de/translation.json b/client/public/locales/de/translation.json index 9d0681c..c546053 100644 --- a/client/public/locales/de/translation.json +++ b/client/public/locales/de/translation.json @@ -48,6 +48,8 @@ "careful_misty_bullock_splash": "Schritt 3: Teilen Sie Ihren Link", "game_frail_vole_treasure": "Erledigt! Glückwunsch!", "still_helpful_koala_trust": "Sobald ein Benutzer einen Termin bucht, wird das Ereignis Ihrem Kalender hinzugefügt.", + "steep_fine_lobster_inspire": "Terminart konnte nicht gespeichert werden", + "best_due_parakeet_zip": "Terminart angelegt", "Name": "Name", "Please provide your name": "Bitte geben Sie Ihren Namen an", "Email": "E-Mail-Adresse", @@ -66,6 +68,6 @@ "Choose date": "Datum wählen", "Choose time": "Uhrzeit wählen", "Provide details": "Details angeben", - "steep_fine_lobster_inspire": "Terminart konnte nicht gespeichert werden", - "best_due_parakeet_zip": "Terminart angelegt" + "happy_caring_fox_spur": "Terminart gespeichert", + "tasty_witty_stingray_hope": "Fehler beim Speichern der Terminart" } diff --git a/client/public/locales/en/translation.json b/client/public/locales/en/translation.json index 0f8036c..9ae4b48 100644 --- a/client/public/locales/en/translation.json +++ b/client/public/locales/en/translation.json @@ -54,5 +54,7 @@ "game_frail_vole_treasure": "Done! Congrats!", "still_helpful_koala_trust": "Once a user books an appointment, the event is added to your calendar.", "steep_fine_lobster_inspire": "Failed to save event type", - "best_due_parakeet_zip": "Event type created!" + "best_due_parakeet_zip": "Event type created!", + "happy_caring_fox_spur": "Event saved", + "tasty_witty_stingray_hope": "Error saving event" } diff --git a/client/src/index.tsx b/client/src/index.tsx index d5c3301..31d452d 100644 --- a/client/src/index.tsx +++ b/client/src/index.tsx @@ -8,7 +8,6 @@ import Login from "./pages/Login"; import Landing from "./pages/Landing"; import AddEvent from "./pages/AddEvent"; import Planning from "./pages/Planning"; -import Schedule from "./pages/Schedule"; import NotFound from "./pages/NotFound"; import Booking from "./pages/Booking"; import EditEvent from "./pages/EditEvent"; @@ -142,10 +141,6 @@ root.render( path="/landing" element={} /> - } - /> } diff --git a/client/src/pages/Booking.tsx b/client/src/pages/Booking.tsx index 6082136..9a56b27 100644 --- a/client/src/pages/Booking.tsx +++ b/client/src/pages/Booking.tsx @@ -85,11 +85,11 @@ const Booking = (props: any) => { const [skipped, setSkipped] = React.useState(new Set()); const [event, setEvent] = useState(EMPTY_EVENT); const [selectedDate, setDate] = useState(); - const [beginDate, setBeginDate] = useState(new Date()); + const [beginDate] = useState(new Date()); const [slots, setSlots] = useState(); - const [selectedTime, setTime] = useState(); + const [selectedTime, setSelectedTime] = useState(); const [details, setDetails] = useState
(); - const [isPending, startTransition] = useTransition() + const [, startTransition] = useTransition() const updateSlots = (startDate: Date) => { getAvailableTimes( @@ -180,9 +180,7 @@ const Booking = (props: any) => { }; const handleMonthChange = (date: Date) => { - //setBeginDate(date); console.log("handleMonthChange: %o", date); - //updateSlots(date); }; const handleDateChange = (newValue: Date) => { @@ -194,7 +192,6 @@ const Booking = (props: any) => { const steps = ["Choose date", "Choose time", "Provide details"].map((label) => t(label)); const checkDay = (date: Date) => { - //console.log("checkDay: %o %o", slots, event.available); if (!event.available) { return false; } else { @@ -221,7 +218,6 @@ const Booking = (props: any) => { const renderPickerDay = ( props: PickersDayProps & { selectedDate: Date | null }) => { const { day } = props; - //console.log("rendering day: %o %o", day, props); return ( { (time: Date) => (event: React.MouseEvent) => { console.log("time: %o", time); setActiveStep(2); - setTime(time); + setSelectedTime(time); }; const renderSlots = () => { diff --git a/client/src/pages/CalendarInt.tsx b/client/src/pages/CalendarInt.tsx index 08b9a61..904ed02 100644 --- a/client/src/pages/CalendarInt.tsx +++ b/client/src/pages/CalendarInt.tsx @@ -20,14 +20,13 @@ import { FormControl, FormControlLabel, FormGroup, - Grid, InputLabel, MenuItem, Select, Typography, IconButton, } from "@mui/material"; - +import Grid from "@mui/material/Grid2"; //import { Button, Modal } from "react-bootstrap"; @@ -50,7 +49,7 @@ const renderCalendarList = (calendarList, state, setState, single = false) => { console.log("selected: %o", selected); const items = calendarList.items.map((item) => { return ( - + {item.summaryOverride ? item.summaryOverride : item.summary} ); @@ -77,6 +76,7 @@ const renderCalendarList = (calendarList, state, setState, single = false) => { } else { const items = calendarList.items.map((item) => ( { ? calendarList.items .filter((item) => user.pull_calendars.includes(item.id)) .map((cal) => ( -
  • {cal.summaryOverride ? cal.summaryOverride : cal.summary}
  • +
  • {cal.summaryOverride ? cal.summaryOverride : cal.summary}
  • )) : undefined; @@ -261,7 +261,7 @@ const PullCalendars = ({ user, calendarList }) => { }; const Calendarintegration = () => { - const token = JSON.parse(localStorage.getItem("access_token") as string); + const token = JSON.parse(localStorage.getItem("access_token")); const navigate = useNavigate(); const [connected, setConnected] = useState(false); const [url, setUrl] = useState(""); @@ -280,7 +280,7 @@ const Calendarintegration = () => { }; useEffect(() => { - if (!user || !user.google_tokens || !user.google_tokens.access_token) { + if (!user?.google_tokens?.access_token) { setConnected(false); console.log("no user or no access token: %o", user); } else { @@ -351,7 +351,7 @@ const Calendarintegration = () => { justifyContent="space-between" alignItems="center" > - + Google Calendar { />{" "} Google Calendar - {renderConnectButton()} + {renderConnectButton()} diff --git a/client/src/pages/EditEvent.tsx b/client/src/pages/EditEvent.tsx index a1eb745..a727a73 100644 --- a/client/src/pages/EditEvent.tsx +++ b/client/src/pages/EditEvent.tsx @@ -8,6 +8,7 @@ import { signout } from "../helpers/helpers"; import { EventForm } from "../components/EventForm"; import { EMPTY_EVENT, Event } from "common"; import { useTranslation } from "react-i18next"; +import { useSnackbar } from "notistack"; export type EventFormProps = { event: Event; @@ -22,6 +23,7 @@ const EditEvent = (): JSX.Element => { const navigate = useNavigate(); const [formData, setFormData] = useState(EMPTY_EVENT); const { t } = useTranslation(); + const { enqueueSnackbar } = useSnackbar(); useEffect(() => { getEventByID(token, eventID).then((res) => { @@ -42,13 +44,13 @@ const EditEvent = (): JSX.Element => { signout(); navigate("/landing"); } else { - //toast.success(res.data.msg); + enqueueSnackbar(t("happy_caring_fox_spur"), { variant: "success" }); navigate("/app"); } }) .catch((err) => { console.log(err); - //toast.error("Failed to save event type"); + enqueueSnackbar(t("tasty_witty_stingray_hope"), { variant: "error" }); }); }; diff --git a/client/src/pages/Schedule.tsx b/client/src/pages/Schedule.tsx deleted file mode 100644 index 9b2b6e0..0000000 --- a/client/src/pages/Schedule.tsx +++ /dev/null @@ -1,487 +0,0 @@ -import { useState, useEffect, FormEvent } from "react"; -import { useNavigate, useParams } from "react-router-dom"; -import { DateCalendar, PickersDay, PickersDayProps } from '@mui/x-date-pickers'; - -import { - Alert, Avatar, Box, Button, Container, Grid, - Snackbar, - Typography, - Link, - CircularProgress -} from '@mui/material'; - - -import { LocalizationProvider } from '@mui/x-date-pickers'; -import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFnsV3' - -import { getUserByUrl } from "../helpers/services/user_services"; -import { getEventByUrlAndUser } from "../helpers/services/event_services"; -import { getAvailableTimes } from "../helpers/services/event_services"; -import clsx from "clsx"; -import { - addDays, - addMonths, - isBefore, - isAfter, - isSameDay, - startOfDay, - endOfDay, -} from "date-fns"; - -import BookDetails, { BookingFormData } from "../components/BookDetails"; -import { insertIntoGoogle } from "../helpers/services/google_services"; -import { Event, IntervalSet, TimeRange } from "common"; -import { UserDocument } from "../helpers/UserDocument"; -import ChooseTime from "../components/ChooseTime"; -import { useTranslation, Trans } from "react-i18next"; -import { HourglassTop, Room } from "@mui/icons-material"; -import ReactMarkdown from "react-markdown"; - - - -/* -const useStyles = makeStyles((theme) => ({ - picker: { - "& button": { - borderRadius: "50%", - "&.highlight": { - "&.selected": { - backgroundColor: theme.palette.primary.main, - color: theme.palette.primary.contrastText, - "&:hover, &:focus": { - backgroundColor: theme.palette.primary.light, - }, - }, - fontWeight: "bold", - "&:hover, &:focus": { - backgroundColor: theme.palette.primary.light, - color: theme.palette.primary.contrastText, - }, - }, - }, - }, - - date: { - borderRadius: "50%", - }, - header: { - "&.MuiTypography-root": { - marginTop: "16px", - marginBottom: "8px", - }, - }, - grid: { - display: "grid", - [theme.breakpoints.down("sm")]: { - gridTemplateColumns: "1fr", - gridTemplateAreas: `"header_l" "picker_l" "header_r" "picker_r"`, - }, - gridTemplateColumns: "1fr 1fr", - gridTemplateAreas: `"header_l header_r" "picker_l picker_r"`, - gap: 2, - alignItems: "start", - padding: 2, - }, - root: { - width: "100%", - }, - buttonWrapper: { - display: "flex", - flexDirection: "row", - padding: "16px 0 0", - }, - button: { - marginRight: theme.spacing(1), - }, - spacer: { - flex: "1 1 auto", - }, - instructions: { - marginTop: theme.spacing(2), - marginBottom: theme.spacing(1), - }, - description: { - display: "inline-block", - "&p": { - display: "inline-block", - }, - }, - textBottom: { - verticalAlign: "text-bottom", - }, - container: { - display: "grid", - gridTemplateColumns: "1.5em 1fr", - gridGap: theme.spacing(1), - alignItems: "center", - paddingBottom: "16px", - }, - item: {}, - slots: { - maxHeight: "300px", - }, -})); -*/ - -type Error = { - message: string; - details: any; -}; - -const Schedule = (props: any) => { - const param = useParams<{ user_url: string; url: string }>(); - const navigate = useNavigate(); - const { t, i18n } = useTranslation(); - - const [user, setUser] = useState(); - const [event, setEvent] = useState(); - //let user: UserDocument = null; - //let event: Event = null; - - const [selectedDate, setSelectedDate] = useState(null); - const [selectedTime, setSelectedTime] = useState(null); - const [beginDate, setBeginDate] = useState(new Date()); - const [slots, setSlots] = useState(new IntervalSet()); - const [daySlots, setDaySlots] = useState(new IntervalSet()); - const [details, setDetails] = useState(null); - const [error, setError] = useState(null); - const [validationErrors, setValidationErrors] = useState({}); - - if (!user) { - getUserByUrl(param.user_url) - .then((res) => { - if (res.data.length === 0) { - navigate("/notfound"); - } else { - setUser(res.data); - } - }) - .catch((err) => { - setError({ - message: "could not get user data", - details: err, - }); - }); - } - - if (user && !event) { - getEventByUrlAndUser(user._id, param.url) - .then((res) => { - if (res.data == null) { - navigate("/notfound"); - } - if (res.data.isActive === false) { - navigate("/notfound"); - } else { - setEvent(res.data); - } - }) - .catch((err) => { - setError({ - message: "could not get event data", - details: err, - }); - }); - } - - useEffect(() => { - if (user && event && event.url) { - getAvailableTimes( - beginDate, - addDays(addMonths(beginDate, 1), 1), - event.url, - user._id - ) - .then((slots) => { - console.log("slots %o", slots); - setSlots(slots); - }) - .catch((err) => { - setError({ - message: "could not get available time slots", - details: err, - }); - }); - } - }, [beginDate, event, user]); - - useEffect(() => { - if (slots && slots.length > 0) { - if (selectedDate == null) { - console.log("setDate: %o", slots[0].start); - let dayInt = new IntervalSet( - startOfDay(slots[0].start), - endOfDay(slots[0].start) - ); - setDaySlots(dayInt.intersect(slots)); - setSelectedDate(slots[0].start); - } - } - }, [selectedDate, slots]); - - const handleErrorClose = () => { - navigate("/"); - }; - - const checkDay = (date: Date) => { - if (date < new Date()) { - return false; - } - let available = false; - if (slots) { - slots.forEach((slot) => { - if ( - isSameDay(slot.start, date) || - isSameDay(slot.end, date) || - (isBefore(slot.start, date) && isAfter(slot.end, date)) - ) { - available = true; - } - }); - } - return available; - }; - - const renderPickerDay = ( - props: PickersDayProps & { selectedDate: Date | null }) => { - const { day, selectedDate } = props; - return ( - - ); - }; - - const handleMonthChange = (date: Date) => { - setBeginDate(date); - }; - - const handleDateChange = (newValue: Date) => { - console.log("selected date: %o", startOfDay(newValue)); - if (user) { - let dayInt = new IntervalSet(startOfDay(newValue), endOfDay(newValue)); - setDaySlots(dayInt.intersect(slots)); - setSelectedDate(newValue); - } - }; - - const handleTimeChange = (time: TimeRange) => { - console.log("select slot: %o", time); - //history.push(window.location.pathname, { selectedTime }); - window.history.pushState({ time }, "Enter Details"); - setSelectedTime(time); - }; - - window.onpopstate = (evt) => { - console.log("popState: %o %o", evt, evt.state); - if (evt.state) { - setSelectedTime(evt.state.time); - } else { - setSelectedTime(null); - } - }; - - const handleDetailChange = (data: BookingFormData) => { - console.log("detailchange: %o", data); - setDetails(data); - }; - - const handleInvalid = (e: FormEvent) => { - e.preventDefault(); - console.log("formInvalid: %o", e); - - if (e.target instanceof HTMLElement) { - const element = e.target; - if (element.id) { - setValidationErrors({ ...validationErrors, [element.id]: e.type }); - } - } - }; - - const handleSubmit = (e) => { - console.log("submit: %o", details); - e.preventDefault(); - - insertIntoGoogle( - user._id, - event, - selectedTime.start, - details.name, - details.email, - details.description - ) - .then(() => { - navigate('/booked', { - state: { user, event, time: selectedTime }, - }); - }) - .catch((err) => - setError({ message: "failed to schedule appointment", details: err }) - ); - }; - - //const userName = user ? user.name : ""; - - console.log("langue: %s", i18n.language); - - return ( - <> - - {user && event ? ( - selectedTime ? ( - <> - {t("Confirm meeting")} - - {selectedDate.toLocaleDateString(i18n.language, { - weekday: "long", - day: "numeric", - month: "long", - })}{" "} - {selectedTime.start.toLocaleTimeString(i18n.language, { - timeStyle: "short", - })}{" "} - –{" "} - {selectedTime.end.toLocaleTimeString(i18n.language, { - timeStyle: "short", - })}{" "} - setSelectedTime(null)}>{t("Change")} - - -
    - - - - - - - - ) : ( - - - - - - {t("Meeting with")} {user.name} - - - - {event.description} - - - - - {" "} - {event.duration} {t("minutes")} - - - - {event.location} - - - - - - - - - - - - {selectedDate ? ( - <> - - The following times are available on - {{ - date: selectedDate.toLocaleDateString(i18n.language, { - day: "numeric", - month: "long", - }), - }} - . You may pick one or choose a different date. - - - ) : ( - <>Please choose a date to check available times. - )} - - - - - ) - ) : ( - - Loading user - - - )} -
    - - {error ? ( - - Error: {error.message}{" "} - {"details" in error && "message" in error.details - ? ": " + error.details.message - : ""} - - ) : ( - <> - )} - - - ); -}; - -export default Schedule;