From e8c202ddd036f1942a276f18955dd9fb58cd3d91 Mon Sep 17 00:00:00 2001 From: DiegoZaff Date: Tue, 11 Jul 2023 23:17:25 +0200 Subject: [PATCH 01/31] calendario draft --- package.json | 2 + src/components/Home/MainMenu.tsx | 2 +- src/navigation/MainStackNavigator.tsx | 2 + src/navigation/NavigationTypes.ts | 1 + src/pages/Calendar.tsx | 211 ++++++++++++++++++++ src/utils/calendar.ts | 272 ++++++++++++++++++++++++++ yarn.lock | 51 ++++- 7 files changed, 536 insertions(+), 5 deletions(-) create mode 100644 src/pages/Calendar.tsx create mode 100644 src/utils/calendar.ts diff --git a/package.json b/package.json index 7fd11d64..cd7fc474 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "react-i18next": "^12.2.0", "react-native": "0.71.8", "react-native-app-intro-slider": "^4.0.4", + "react-native-calendars": "https://github.com/DiegoZaff/react-native-calendars", "react-native-dropdown-select-list": "^2.0.4", "react-native-fit-image": "^1.5.5", "react-native-gesture-handler": "~2.9.0", @@ -87,6 +88,7 @@ "react-navigation-shared-element": "^3.1.3", "rn-slick-bottom-tabs": "^1.1.1", "styled-components": "^5.3.6", + "xdate": "^0.8.2", "yarn": "^1.22.19" }, "devDependencies": { diff --git a/src/components/Home/MainMenu.tsx b/src/components/Home/MainMenu.tsx index 7ef71bba..c423c74b 100644 --- a/src/components/Home/MainMenu.tsx +++ b/src/components/Home/MainMenu.tsx @@ -33,7 +33,7 @@ export const MainMenu: FC<{ filter?: string }> = ({ filter }) => { type: ButtonType.CALENDAR, title: "menu_calendar", icon: calendar, - onClick: () => navigate("Error404"), + onClick: () => navigate("Calendar"), }, { type: ButtonType.TIMETABLE, diff --git a/src/navigation/MainStackNavigator.tsx b/src/navigation/MainStackNavigator.tsx index 2432c379..d5e3d31d 100644 --- a/src/navigation/MainStackNavigator.tsx +++ b/src/navigation/MainStackNavigator.tsx @@ -22,6 +22,7 @@ import { NotificationsCategory } from "pages/notifications/NotificationsCategory import { NotificationDetails } from "pages/notifications/NotificationDetails" import { createSharedElementStackNavigator } from "react-navigation-shared-element" import { HeadquarterChoice } from "pages/FreeClass/HeadquarterChoice" +import { CalendarPage } from "pages/Calendar" // eslint-disable-next-line @typescript-eslint/naming-convention const MainStackNavigator = @@ -106,6 +107,7 @@ export const MainStack: FC = () => { } }} /> + ) } diff --git a/src/navigation/NavigationTypes.ts b/src/navigation/NavigationTypes.ts index 3cf8d0f0..b884d8f5 100644 --- a/src/navigation/NavigationTypes.ts +++ b/src/navigation/NavigationTypes.ts @@ -86,6 +86,7 @@ export type MainStackNavigatorParams = { channelId: ValidChannelId } NotificationDetails: { notification: NotificationStorage; category?: string } + Calendar: undefined } export type SettingsStackNavigatorParams = { diff --git a/src/pages/Calendar.tsx b/src/pages/Calendar.tsx new file mode 100644 index 00000000..866fd5fd --- /dev/null +++ b/src/pages/Calendar.tsx @@ -0,0 +1,211 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import { MainStackScreen } from "navigation/NavigationTypes" +import { useTranslation } from "react-i18next" +import { BoxShadowView } from "components/BoxShadow" +import { NavBar } from "components/NavBar" +import { ScrollView, View } from "react-native" +import { usePalette } from "utils/colors" +import { StyleSheet } from "react-native" +import { Calendar } from "react-native-calendars" +import { useEffect, useRef, useState } from "react" +import { + CalendarPeriod, + CalendarSingletonWrapper, + dotColorGold, + months, +} from "utils/calendar" +import { MarkedDates } from "react-native-calendars/src/types" +import { Text } from "components/Text" +import { ToggleSwitch } from "components/ToggleSwitch" + +/* import { Markings } from "react-native-calendars/src/calendar/day/marking" */ + +export const CalendarPage: MainStackScreen<"Calendar"> = () => { + const { homeBackground, background, isLight, palette } = usePalette() + const { t } = useTranslation() + + const [selectedDay, setSelectedDay] = useState( + new Date().toISOString().slice(0, 10) + ) + + const [month, setMonth] = useState(new Date().getMonth()) + + const [year, setYear] = useState(new Date().getFullYear()) + + const [markedDates, setMarkedDates] = useState({}) + + const [calendarPeriods, setCalendarPeriods] = useState< + CalendarPeriod[] | undefined + >() + + useEffect(() => { + console.log(selectedDay) + }, [selectedDay]) + + const calendarObj = useRef() + + useEffect(() => { + const initCalendar = () => { + if (!calendarObj.current) { + calendarObj.current = CalendarSingletonWrapper.getInstance() + calendarObj.current.addListener("markedDatesSet", () => { + if (calendarObj.current?.markedDatesPeriods) { + console.log("updating marked dates") + setMarkedDates(calendarObj.current?.markedDatesPeriods) + setCalendarPeriods(calendarObj.current?.calendarPeriods) + } + }) + + calendarObj.current.addListener("calendarPeriodsChanged", () => { + console.log("updating periods") + if (calendarObj.current?.calendarPeriods) { + console.log("inside if") + setCalendarPeriods(calendarObj.current?.calendarPeriods) + } + }) + } + } + + initCalendar() + + return () => { + calendarObj?.current?.removeAllListeners("markedDatesSet") + calendarObj?.current?.removeAllListeners("calendarPeriodsChanged") + } + }, []) + + return ( + + {/* */} + { + console.log(day) + }} + style={{ + marginTop: 106, + height: 340, + backgroundColor: homeBackground, + }} + markedDates={markedDates} + customHeaderTitle={undefined} + hideExtraDays={true} + renderHeader={() => null} + renderArrow={() => null} + enableSwipeMonths={true} + showSixWeeks={true} + hideDayNames={true} + markingType="period" + current={selectedDay} + onMonthChange={month => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + setMonth(month.month - 1) + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access + setYear(month.year) + }} + /> + {/* */} + + {calendarPeriods && ( + + + {months[month] + " " + year} + + {calendarPeriods.map(period => { + return ( + + + + {period.title} + + + {period.subtitle} + + + + calendarObj.current?.updatePeriods(period.title, value) + } + /> + + ) + })} + + )} + + + + ) +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, + boxShadow: { + flex: 1, + overflow: "visible", + }, + boxShadowContainer: { + flex: 1, + borderTopLeftRadius: 30, + borderTopRightRadius: 30, + overflow: "visible", + }, + periodTitle: { + fontSize: 16, + fontWeight: "700", + }, + periodSubTitle: { + fontSize: 12, + fontWeight: "400", + }, + monthTitle: { + fontSize: 20, + fontWeight: "900", + }, +}) diff --git a/src/utils/calendar.ts b/src/utils/calendar.ts new file mode 100644 index 00000000..75f67ab4 --- /dev/null +++ b/src/utils/calendar.ts @@ -0,0 +1,272 @@ +import { MarkedDates } from "react-native-calendars/src/types" +import * as FileSystem from "expo-file-system" +import { EventEmitter } from "events" + +export const dotColorGold = "rgba(242, 186, 82, 1)" +export const purpleBerry = "rgba(98, 96, 166, 1)" + +export interface Period { + start?: string + end?: string +} + +export interface CalendarPeriod { + dates: Period[] + title: string + subtitle?: string + color: string + shown: boolean +} + +export interface CalendarEvent { + title: string + + //start and end are on the same day. iso dates for convenience + start: string + end: string + + //also a iso date + reminder?: string + + //if remainder is every day? + repeats?: boolean + + //this is weird + mood?: string + + status: CalendarEventStatus +} + +export enum CalendarEventStatus { + INITIAL, + PROGRESS, + COMPLETED, +} + +const calendarPeriods: CalendarPeriod[] = [ + { + dates: [{ start: "2023-08-01", end: "2023-08-22" }], + title: "Vacanze", + subtitle: "1/08 - 22/08", + color: dotColorGold, + shown: true, + }, + { + dates: [{ start: "2023-08-23", end: "2023-08-31" }], + title: "Esami di profitto", + subtitle: "23/08 - 31/08", + color: purpleBerry, + shown: true, + }, +] + +export declare interface CalendarSingletonWrapper { + on(event: "calendarPeriodsChanged", listener: () => void): this + + on(event: "markedDatesSet", listener: () => void): this +} + +export class CalendarSingletonWrapper extends EventEmitter { + private static classInstance?: CalendarSingletonWrapper + + private _markedDatesPeriods: MarkedDates | undefined + + public get markedDatesPeriods(): MarkedDates | undefined { + return this._markedDatesPeriods + } + private _calendarPeriods?: CalendarPeriod[] + + public get calendarPeriods(): CalendarPeriod[] | undefined { + return this._calendarPeriods + } + + private _calendarEvents: CalendarEvent[] = [] + + public static getInstance() { + if (!this.classInstance) { + this.classInstance = new CalendarSingletonWrapper() + } + + return this.classInstance + } + + private constructor() { + super() + void this._initializeCalendar() + } + private async _initializeCalendar() { + await this._readEvents() + await this._readCalendarPeriods() + this._applyPeriods() + /* this._markedDatesMerging() */ + } + private _readEvents = async () => { + try { + const calendarEventsJSON = await FileSystem.readAsStringAsync( + FileSystem.documentDirectory + "calendar_events.json" + ) + const calendarEvents = JSON.parse(calendarEventsJSON) as CalendarEvent[] + this._calendarEvents = calendarEvents + } catch (err) { + console.log(err) + console.log("Error reading calendarEvents") + } + } + + private _writeEvents = async (events: CalendarEvent[]): Promise => { + const calendarEventsJSON = JSON.stringify(events) + try { + this._calendarEvents = events + await FileSystem.writeAsStringAsync( + FileSystem.documentDirectory + "calendar_events.json", + calendarEventsJSON + ) + + return true + } catch (err) { + console.log(err) + console.log("Error storing calendar events") + return false + } + } + + private _readCalendarPeriods = async () => { + try { + const calendarPeriodsJSON = await FileSystem.readAsStringAsync( + FileSystem.documentDirectory + "calendar_periods.json" + ) + const calendarPeriods = JSON.parse( + calendarPeriodsJSON + ) as CalendarPeriod[] + this._calendarPeriods = calendarPeriods + } catch (err) { + console.log(err) + console.log("Error reading calendarPeriods") + this._calendarPeriods = calendarPeriods + void this._writeCalendarPeriods(calendarPeriods) + } + } + + private _writeCalendarPeriods = async ( + periods: CalendarPeriod[] + ): Promise => { + const calendarPeriodsJSON = JSON.stringify(periods) + try { + this._calendarPeriods = periods + await FileSystem.writeAsStringAsync( + FileSystem.documentDirectory + "calendar_periods.json", + calendarPeriodsJSON + ) + + return true + } catch (err) { + console.log(err) + console.log("Error storing periods ") + return false + } + } + + private _applyPeriods() { + this._markedDatesPeriods = {} + this._calendarPeriods?.forEach(period => { + if (!period.shown) return + period.dates.forEach(date => { + const periodTmp: MarkedDates = {} + let tmpDate: string + let tmpDateObj: Date + let tmpDateEndObj: Date + + if (date.start && date.end) { + if (date.start === date.end) { + periodTmp[date.start] = { + color: period.color, + startingDay: true, + endingDay: true, + } + } else { + tmpDate = date.start + tmpDateObj = new Date(tmpDate) + tmpDateEndObj = new Date(date.end) + + //add first day + periodTmp[tmpDate] = { + color: period.color, + startingDay: true, + } + + const res = getNextDayFormattedDate(tmpDateObj) + tmpDate = res.dateString + tmpDateObj = res.dateObj + + while (tmpDateObj.getTime() < tmpDateEndObj.getTime()) { + //add day in the middle + periodTmp[tmpDate] = { + color: period.color, + } + const res = getNextDayFormattedDate(tmpDateObj) + tmpDate = res.dateString + tmpDateObj = res.dateObj + } + + //add last day + periodTmp[tmpDate] = { + color: period.color, + endingDay: true, + } + } + } + + this._markedDatesPeriods = { ...this._markedDatesPeriods, ...periodTmp } + + this.emit("markedDatesSet") + return + }) + }) + this.emit("markedDatesSet") + } + + public updatePeriods = (title: string, val: boolean) => { + console.log(val) + const periods = this._calendarPeriods ?? [] + for (let i = 0; i < periods.length; i++) { + if (periods[i].title === title) { + periods[i].shown = val + break + } + } + + this._calendarPeriods = periods.slice() + + this.emit("calendarPeriodsChanged") + void this._writeCalendarPeriods(periods) + this._applyPeriods() + } + /* private _markedDatesMerging() { + throw new Error("Method not implemented.") + } */ +} + +const getNextDayFormattedDate = ( + date: Date +): { dateString: string; dateObj: Date } => { + const dateObj = new Date(date.getTime() + 86400000) + + const dateString = dateObj.toISOString().split("T")[0] + + return { dateString, dateObj } +} + +export const months = [ + "Gennaio", + "Febbraio", + "Marzo", + "Aprile", + "Maggio", + "Giugno", + "Luglio", + "Agosto", + "Settembre", + "Ottobre", + "Novembre", + "Dicembre", +] diff --git a/yarn.lock b/yarn.lock index 07a124dc..27ec63c7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5883,7 +5883,7 @@ hoist-non-react-statics@^2.3.1: resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47" integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw== -hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: +hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -6946,7 +6946,7 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -lodash.debounce@^4.0.8: +lodash.debounce@4.0.8, lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== @@ -7130,7 +7130,7 @@ memfs@^3.4.3: dependencies: fs-monkey "^1.0.3" -memoize-one@^5.0.0: +memoize-one@^5.0.0, memoize-one@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== @@ -7710,6 +7710,11 @@ mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +moment@^2.29.4: + version "2.29.4" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" + integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -8795,7 +8800,7 @@ prompts@^2.3.2, prompts@^2.4.0: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@*, prop-types@^15.5.10, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@*, prop-types@15.8.1, prop-types@^15.5.10, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -8960,6 +8965,20 @@ react-native-app-intro-slider@^4.0.4: resolved "https://registry.yarnpkg.com/react-native-app-intro-slider/-/react-native-app-intro-slider-4.0.4.tgz#fa5cda7057db62c448ac975ffd2ba0cff94cc8d8" integrity sha512-Zkjaol6X3BbZkHUpVDj2LjdidpS6rCgKi0fx80xgGKa0pHxBRd4swWTv2bHnnvu5k1/HXwYk0mY2TbK+2jHl5w== +"react-native-calendars@https://github.com/DiegoZaff/react-native-calendars": + version "1.22.0" + resolved "https://github.com/DiegoZaff/react-native-calendars#7cb31fc24624d82e49045fea9de80fabfbd7f685" + dependencies: + hoist-non-react-statics "^3.3.1" + lodash "^4.17.15" + memoize-one "^5.2.1" + prop-types "^15.5.10" + react-native-swipe-gestures "^1.0.5" + recyclerlistview "^4.0.0" + xdate "^0.8.0" + optionalDependencies: + moment "^2.29.4" + react-native-codegen@^0.71.5: version "0.71.5" resolved "https://registry.yarnpkg.com/react-native-codegen/-/react-native-codegen-0.71.5.tgz#454a42a891cd4ca5fc436440d301044dc1349c14" @@ -9091,6 +9110,11 @@ react-native-svg@13.4.0: css-select "^5.1.0" css-tree "^1.1.3" +react-native-swipe-gestures@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/react-native-swipe-gestures/-/react-native-swipe-gestures-1.0.5.tgz#a172cb0f3e7478ccd681fd36b8bfbcdd098bde7c" + integrity sha512-Ns7Bn9H/Tyw278+5SQx9oAblDZ7JixyzeOczcBK8dipQk2pD7Djkcfnf1nB/8RErAmMLL9iXgW0QHqiII8AhKw== + react-native-switch@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/react-native-switch/-/react-native-switch-1.5.1.tgz#da032f66547053aa004c7a159422dbca8fadd944" @@ -9286,6 +9310,15 @@ recast@^0.20.4: source-map "~0.6.1" tslib "^2.0.1" +recyclerlistview@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/recyclerlistview/-/recyclerlistview-4.2.0.tgz#a140149aaa470c9787a1426452651934240d69ef" + integrity sha512-uuBCi0c+ggqHKwrzPX4Z/mJOzsBbjZEAwGGmlwpD/sD7raXixdAbdJ6BTcAmuWG50Cg4ru9p12M94Njwhr/27A== + dependencies: + lodash.debounce "4.0.8" + prop-types "15.8.1" + ts-object-utils "0.0.5" + regenerate-unicode-properties@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c" @@ -10526,6 +10559,11 @@ ts-interface-checker@^0.1.9: resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== +ts-object-utils@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/ts-object-utils/-/ts-object-utils-0.0.5.tgz#95361cdecd7e52167cfc5e634c76345e90a26077" + integrity sha512-iV0GvHqOmilbIKJsfyfJY9/dNHCs969z3so90dQWsO1eMMozvTpnB1MEaUbb3FYtZTGjv5sIy/xmslEz0Rg2TA== + tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" @@ -11130,6 +11168,11 @@ xcode@^3.0.0, xcode@^3.0.1: simple-plist "^1.1.0" uuid "^7.0.3" +xdate@^0.8.0, xdate@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/xdate/-/xdate-0.8.2.tgz#d7b033c00485d02695baf0044f4eacda3fc961a3" + integrity sha512-sNBlLfOC8S3V0vLDEUianQOXcTsc9j4lfeKU/klHe0RjHAYn0CXsSttumTot8dzalboV8gZbH38B+WcCIBjhFQ== + xml-js@^1.6.11: version "1.6.11" resolved "https://registry.yarnpkg.com/xml-js/-/xml-js-1.6.11.tgz#927d2f6947f7f1c19a316dd8eea3614e8b18f8e9" From 36b2323c1dada5c8d8080edeb17204263747ab42 Mon Sep 17 00:00:00 2001 From: DiegoZaff Date: Sat, 15 Jul 2023 15:43:05 +0200 Subject: [PATCH 02/31] new approach for borders period --- package.json | 3 +- src/pages/Calendar.tsx | 8 +- src/utils/{calendar.ts => calendar.tsx} | 185 +++++++++++++++++++++++- yarn.lock | 7 +- 4 files changed, 193 insertions(+), 10 deletions(-) rename src/utils/{calendar.ts => calendar.tsx} (60%) diff --git a/package.json b/package.json index cd7fc474..11c27ef3 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "react-i18next": "^12.2.0", "react-native": "0.71.8", "react-native-app-intro-slider": "^4.0.4", - "react-native-calendars": "https://github.com/DiegoZaff/react-native-calendars", + "react-native-calendars": "^1.1299.0", "react-native-dropdown-select-list": "^2.0.4", "react-native-fit-image": "^1.5.5", "react-native-gesture-handler": "~2.9.0", @@ -88,7 +88,6 @@ "react-navigation-shared-element": "^3.1.3", "rn-slick-bottom-tabs": "^1.1.1", "styled-components": "^5.3.6", - "xdate": "^0.8.2", "yarn": "^1.22.19" }, "devDependencies": { diff --git a/src/pages/Calendar.tsx b/src/pages/Calendar.tsx index 866fd5fd..d426f09a 100644 --- a/src/pages/Calendar.tsx +++ b/src/pages/Calendar.tsx @@ -11,6 +11,7 @@ import { useEffect, useRef, useState } from "react" import { CalendarPeriod, CalendarSingletonWrapper, + dayComponentCustom, dotColorGold, months, } from "utils/calendar" @@ -84,9 +85,6 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { todayTextColor: "yellow", dayTextColor: "#fff", dotStyle: { width: 6, height: 6, borderRadius: 3 }, - dotRightPos: -2, - dotTopPos: 2, - blockerColor: palette.primary, dotColor: dotColorGold, }} onDayPress={day => { @@ -97,7 +95,7 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { height: 340, backgroundColor: homeBackground, }} - markedDates={markedDates} + markedDates={{ ...markedDates, "2023-07-15": { marked: true } }} customHeaderTitle={undefined} hideExtraDays={true} renderHeader={() => null} @@ -113,6 +111,8 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access setYear(month.year) }} + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + dayComponent={dayComponentCustom} /> {/* */} = props => { + const { + theme, + marking, + date, + onPress, + onLongPress, + state, + accessibilityLabel, + testID, + children, + } = props + + const dateData = dateToDateData(date) + + /* const containerStyle = useMemo(() => { + const containerStyle = [] + + containerStyle.push({ + width: 38, + height: FILLER_HEIGHT, + alignItems: "center", + justifyContent: "center", + }) + + if (state === "today") { + containerStyle.push({ + backgroundColor: "000", + }) + } + + if (marking) { + containerStyle.push({ + borderRadius: 17, + overflow: "hidden", + }) + + if (markingStyle.containerStyle) { + containerStyle.push(markingStyle.containerStyle) + } + + const start = markingStyle.startingDay + const end = markingStyle.endingDay + if (start && !end) { + containerStyle.push({ + backgroundColor: markingStyle.startingDay?.backgroundColor, + }) + } else if ((end && !start) || (end && start)) { + containerStyle.push({ + backgroundColor: markingStyle.endingDay?.backgroundColor, + }) + } + } + return containerStyle + }, [marking, state]) */ + + const path = useMemo(() => { + let startAngle + let sweepAngle + + if (marking?.startingDay && marking.endingDay) { + startAngle = 90 + sweepAngle = 360 + } else if (marking?.startingDay) { + startAngle = 90 + sweepAngle = 180 + } else if (marking?.endingDay) { + startAngle = 270 + sweepAngle = 180 + } else { + return undefined + } + + const path = Skia.Path.Make() + path.moveTo(19, 0) + path.addArc({ height: 32, width: 36, y: 1, x: 1 }, startAngle, sweepAngle) + + return path + }, [marking]) + + return ( + + + + + + + {path && ( + + + + )} + + + {String(children)} + + + {marking?.marked && ( + + )} + + + + + ) +} + +const dateToDateData = ( + date: (string & DateData) | undefined +): DateData | undefined => { + if (date) { + if (typeof date === "string") { + const d = new Date(date) + + return { + day: d.getDate(), + month: d.getMonth() + 1, + year: d.getFullYear(), + dateString: d.toISOString().substring(0, 10), + timestamp: d.getTime(), + } + } + } + return undefined +} diff --git a/yarn.lock b/yarn.lock index 27ec63c7..892d007d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8965,9 +8965,10 @@ react-native-app-intro-slider@^4.0.4: resolved "https://registry.yarnpkg.com/react-native-app-intro-slider/-/react-native-app-intro-slider-4.0.4.tgz#fa5cda7057db62c448ac975ffd2ba0cff94cc8d8" integrity sha512-Zkjaol6X3BbZkHUpVDj2LjdidpS6rCgKi0fx80xgGKa0pHxBRd4swWTv2bHnnvu5k1/HXwYk0mY2TbK+2jHl5w== -"react-native-calendars@https://github.com/DiegoZaff/react-native-calendars": - version "1.22.0" - resolved "https://github.com/DiegoZaff/react-native-calendars#7cb31fc24624d82e49045fea9de80fabfbd7f685" +react-native-calendars@^1.1299.0: + version "1.1299.0" + resolved "https://registry.yarnpkg.com/react-native-calendars/-/react-native-calendars-1.1299.0.tgz#aef65562046c5dc44bedcae9bd4577dba5d74249" + integrity sha512-b59svUAIDMPy5mYpwdyBFkyv3Fne897O7TB99AjALKs5s3ciR3cuH5GGMbD6e+M79r4cY78xiauZH3eCS2u1uw== dependencies: hoist-non-react-statics "^3.3.1" lodash "^4.17.15" From e71619bd99c790466b28d839db1c44684c0c3deb Mon Sep 17 00:00:00 2001 From: DiegoZaff Date: Sat, 15 Jul 2023 23:16:03 +0200 Subject: [PATCH 03/31] adjustaments --- src/pages/Calendar.tsx | 68 ++++++++++++---- src/utils/calendar.tsx | 172 ++++++++++++++++++++++++----------------- 2 files changed, 153 insertions(+), 87 deletions(-) diff --git a/src/pages/Calendar.tsx b/src/pages/Calendar.tsx index d426f09a..d424c76e 100644 --- a/src/pages/Calendar.tsx +++ b/src/pages/Calendar.tsx @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import { MainStackScreen } from "navigation/NavigationTypes" import { useTranslation } from "react-i18next" import { BoxShadowView } from "components/BoxShadow" @@ -10,17 +9,16 @@ import { Calendar } from "react-native-calendars" import { useEffect, useRef, useState } from "react" import { CalendarPeriod, - CalendarSingletonWrapper, + CalendarSingletonWrapper as CalendarManager, dayComponentCustom, dotColorGold, months, + daysOfWeekLetters, } from "utils/calendar" import { MarkedDates } from "react-native-calendars/src/types" import { Text } from "components/Text" import { ToggleSwitch } from "components/ToggleSwitch" -/* import { Markings } from "react-native-calendars/src/calendar/day/marking" */ - export const CalendarPage: MainStackScreen<"Calendar"> = () => { const { homeBackground, background, isLight, palette } = usePalette() const { t } = useTranslation() @@ -43,27 +41,29 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { console.log(selectedDay) }, [selectedDay]) - const calendarObj = useRef() + const calendarObj = useRef() useEffect(() => { const initCalendar = () => { if (!calendarObj.current) { - calendarObj.current = CalendarSingletonWrapper.getInstance() + calendarObj.current = new CalendarManager() calendarObj.current.addListener("markedDatesSet", () => { if (calendarObj.current?.markedDatesPeriods) { - console.log("updating marked dates") setMarkedDates(calendarObj.current?.markedDatesPeriods) setCalendarPeriods(calendarObj.current?.calendarPeriods) } }) calendarObj.current.addListener("calendarPeriodsChanged", () => { - console.log("updating periods") if (calendarObj.current?.calendarPeriods) { - console.log("inside if") setCalendarPeriods(calendarObj.current?.calendarPeriods) } }) + } else { + if (calendarObj.current?.markedDatesPeriods) { + setMarkedDates(calendarObj.current?.markedDatesPeriods) + setCalendarPeriods(calendarObj.current?.calendarPeriods) + } } } @@ -77,7 +77,35 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { return ( - {/* */} + + + {daysOfWeekLetters.map(day => ( + + {day} + + ))} + + + = () => { console.log(day) }} style={{ - marginTop: 106, - height: 340, + marginTop: 130, + height: 290, backgroundColor: homeBackground, }} - markedDates={{ ...markedDates, "2023-07-15": { marked: true } }} + markedDates={{ + ...markedDates, + // eslint-disable-next-line @typescript-eslint/naming-convention + "2023-07-15": { + marked: true, + startingDay: true, + endingDay: true, + color: "orange", + }, + }} customHeaderTitle={undefined} hideExtraDays={true} renderHeader={() => null} @@ -132,8 +169,9 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { = () => { calendarObj.current?.updatePeriods(period.title, value) @@ -174,6 +213,7 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { ) })} + {/* */} )} diff --git a/src/utils/calendar.tsx b/src/utils/calendar.tsx index 49a320df..5a81dfe2 100644 --- a/src/utils/calendar.tsx +++ b/src/utils/calendar.tsx @@ -2,7 +2,7 @@ import { DateData, MarkedDates } from "react-native-calendars/src/types" import * as FileSystem from "expo-file-system" import { EventEmitter } from "events" import { ComponentType, useMemo } from "react" -import { TouchableOpacity, View } from "react-native" +import { TouchableOpacity, View, ViewStyle } from "react-native" import { DayProps } from "react-native-calendars/src/calendar/day" import { Text } from "components/Text" import { Canvas, Path, Skia } from "@shopify/react-native-skia" @@ -50,19 +50,38 @@ export enum CalendarEventStatus { const calendarPeriods: CalendarPeriod[] = [ { - dates: [{ start: "2023-08-01", end: "2023-08-22" }], + dates: [{ start: "2023-08-01", end: "2023-08-24" }], title: "Vacanze", - subtitle: "1/08 - 22/08", + subtitle: "1/08 - 24/08", color: dotColorGold, shown: true, }, { - dates: [{ start: "2023-08-23", end: "2023-08-31" }], + dates: [{ start: "2023-08-25", end: "2023-09-09" }], title: "Esami di profitto", subtitle: "23/08 - 31/08", color: purpleBerry, shown: true, }, + { + dates: [ + { start: "2023-11-04", end: "2023-11-08" }, + { start: "2023-04-19", end: "2023-04-22" }, + ], + title: "Prove in Itinere", + color: "#F29999", + shown: true, + }, + { + dates: [ + { start: "2023-09-28", end: "2023-09-30" }, + { start: "2023-03-08", end: "2023-03-09" }, + { start: "2023-09-19", end: "2023-09-21" }, + ], + title: "Lauree 1° Livello", + color: "#F28C52", + shown: true, + }, ] export declare interface CalendarSingletonWrapper { @@ -72,9 +91,7 @@ export declare interface CalendarSingletonWrapper { } export class CalendarSingletonWrapper extends EventEmitter { - private static classInstance?: CalendarSingletonWrapper - - private _markedDatesPeriods: MarkedDates | undefined + private _markedDatesPeriods: MarkedDates = {} public get markedDatesPeriods(): MarkedDates | undefined { return this._markedDatesPeriods @@ -87,15 +104,7 @@ export class CalendarSingletonWrapper extends EventEmitter { private _calendarEvents: CalendarEvent[] = [] - public static getInstance() { - if (!this.classInstance) { - this.classInstance = new CalendarSingletonWrapper() - } - - return this.classInstance - } - - private constructor() { + public constructor() { super() void this._initializeCalendar() } @@ -222,9 +231,6 @@ export class CalendarSingletonWrapper extends EventEmitter { } this._markedDatesPeriods = { ...this._markedDatesPeriods, ...periodTmp } - - this.emit("markedDatesSet") - return }) }) this.emit("markedDatesSet") @@ -246,6 +252,24 @@ export class CalendarSingletonWrapper extends EventEmitter { void this._writeCalendarPeriods(periods) this._applyPeriods() } + + // ! non testata + public addEvent = (event: CalendarEvent) => { + this._calendarEvents.push(event) + + void this._writeEvents(this._calendarEvents) + } + + // ! non testata + public applyMarkers = () => { + for (let i = 0; i < this._calendarEvents.length; i++) { + const dateString = this._calendarEvents[i].start.substring(0, 10) + + this._markedDatesPeriods[dateString].marked = true + } + this._calendarEvents + } + /* private _markedDatesMerging() { throw new Error("Method not implemented.") } */ @@ -276,7 +300,7 @@ export const months = [ "Dicembre", ] -const FILLER_HEIGHT = 34 +const FILLER_HEIGHT = 26 export const dayComponentCustom: ComponentType< DayProps & { @@ -297,46 +321,34 @@ export const dayComponentCustom: ComponentType< const dateData = dateToDateData(date) - /* const containerStyle = useMemo(() => { - const containerStyle = [] - - containerStyle.push({ - width: 38, - height: FILLER_HEIGHT, - alignItems: "center", - justifyContent: "center", - }) - - if (state === "today") { - containerStyle.push({ - backgroundColor: "000", - }) - } - - if (marking) { - containerStyle.push({ - borderRadius: 17, - overflow: "hidden", - }) - - if (markingStyle.containerStyle) { - containerStyle.push(markingStyle.containerStyle) - } - - const start = markingStyle.startingDay - const end = markingStyle.endingDay - if (start && !end) { - containerStyle.push({ - backgroundColor: markingStyle.startingDay?.backgroundColor, - }) - } else if ((end && !start) || (end && start)) { - containerStyle.push({ - backgroundColor: markingStyle.endingDay?.backgroundColor, - }) + const fillerStyles = useMemo(() => { + const leftFillerStyle: ViewStyle = { flex: 1 } + const rightFillerStyle: ViewStyle = { flex: 1 } + let globalfiller: ViewStyle = {} + + const start = marking?.startingDay + const end = marking?.endingDay + + if (start && !end) { + rightFillerStyle.borderBottomColor = marking?.color + rightFillerStyle.borderBottomWidth = 2 + rightFillerStyle.borderTopColor = marking?.color + rightFillerStyle.borderTopWidth = 2 + } else if (end && !start) { + leftFillerStyle.borderBottomColor = marking?.color + leftFillerStyle.borderBottomWidth = 2 + leftFillerStyle.borderTopColor = marking?.color + leftFillerStyle.borderTopWidth = 2 + } else if (marking?.color && !start && !end) { + globalfiller = { + borderBottomColor: marking?.color, + borderBottomWidth: 2, + borderTopColor: marking?.color, + borderTopWidth: 2, } } - return containerStyle - }, [marking, state]) */ + return { leftFillerStyle, rightFillerStyle, globalfiller } + }, [marking]) const path = useMemo(() => { let startAngle @@ -356,14 +368,23 @@ export const dayComponentCustom: ComponentType< } const path = Skia.Path.Make() - path.moveTo(19, 0) - path.addArc({ height: 32, width: 36, y: 1, x: 1 }, startAngle, sweepAngle) + path.moveTo(19, 1) + //this looks kinda random + path.addArc( + { height: FILLER_HEIGHT - 2, width: 30, y: 1, x: 4 }, + startAngle, + sweepAngle + ) return path }, [marking]) return ( - + onPress(dateData) : undefined} + onLongPress={onLongPress ? () => onLongPress(dateData) : undefined} + > - - + + + {path && ( {String(children)} - + {marking?.marked && ( Date: Sun, 16 Jul 2023 10:01:23 +0200 Subject: [PATCH 04/31] icons --- assets/calendar/calendar.svg | 17 +++++++++++++++++ assets/calendar/cape_calendar.svg | 4 ++++ assets/calendar/user_calendar.svg | 4 ++++ src/pages/Calendar.tsx | 25 +++++++++++++++++++++---- 4 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 assets/calendar/calendar.svg create mode 100644 assets/calendar/cape_calendar.svg create mode 100644 assets/calendar/user_calendar.svg diff --git a/assets/calendar/calendar.svg b/assets/calendar/calendar.svg new file mode 100644 index 00000000..034b4901 --- /dev/null +++ b/assets/calendar/calendar.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/assets/calendar/cape_calendar.svg b/assets/calendar/cape_calendar.svg new file mode 100644 index 00000000..5f99d40c --- /dev/null +++ b/assets/calendar/cape_calendar.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/calendar/user_calendar.svg b/assets/calendar/user_calendar.svg new file mode 100644 index 00000000..b097412a --- /dev/null +++ b/assets/calendar/user_calendar.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/pages/Calendar.tsx b/src/pages/Calendar.tsx index d424c76e..d5b85964 100644 --- a/src/pages/Calendar.tsx +++ b/src/pages/Calendar.tsx @@ -18,6 +18,10 @@ import { import { MarkedDates } from "react-native-calendars/src/types" import { Text } from "components/Text" import { ToggleSwitch } from "components/ToggleSwitch" +import { Icon } from "components/Icon" +import calendarIcon from "assets/calendar/calendar.svg" +import capeIcon from "assets/calendar/cape_calendar.svg" +import userIcon from "assets/calendar/user_calendar.svg" export const CalendarPage: MainStackScreen<"Calendar"> = () => { const { homeBackground, background, isLight, palette } = usePalette() @@ -81,12 +85,25 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { style={{ position: "absolute", top: 120, - height: 24, + height: 40, width: "100%", zIndex: 2, paddingHorizontal: 28, }} > + + + + + + + = () => { justifyContent: "space-between", }} > - {daysOfWeekLetters.map(day => ( + {daysOfWeekLetters.map((day, index) => ( {day} @@ -119,7 +136,7 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { console.log(day) }} style={{ - marginTop: 130, + marginTop: 150, height: 290, backgroundColor: homeBackground, }} From b7680e775a5641e42787f00419b8af356f5758d3 Mon Sep 17 00:00:00 2001 From: DiegoZaff Date: Fri, 4 Aug 2023 18:03:57 +0200 Subject: [PATCH 05/31] Calendar bottomSheet Flow --- assets/calendar/emoticons/boom.svg | 5 + assets/calendar/emoticons/broken_heart.svg | 4 + assets/calendar/emoticons/cry_face.svg | 8 + assets/calendar/emoticons/desperate.svg | 6 + assets/calendar/emoticons/fall_in_love.svg | 5 + assets/calendar/emoticons/grinning.svg | 7 + assets/calendar/emoticons/heart.svg | 3 + assets/calendar/emoticons/laughing.svg | 7 + assets/calendar/emoticons/look_aside.svg | 6 + assets/calendar/emoticons/normal_smile.svg | 6 + assets/calendar/emoticons/one_hundred.svg | 3 + assets/calendar/emoticons/sick_face.svg | 4 + assets/calendar/emoticons/smile.svg | 6 + .../calendar/emoticons/smile_eyes_closed.svg | 5 + assets/calendar/emoticons/smile_eyes_open.svg | 7 + .../emoticons/smile_eyes_triangle.svg | 6 + .../calendar/emoticons/smile_water_drop.svg | 6 + assets/calendar/emoticons/star_eyes.svg | 6 + src/components/Calendar/Button.tsx | 33 ++++ src/components/Calendar/CalendarAddEvent.tsx | 57 ++++++ .../Calendar/CalendarMonthlyEvents.tsx | 128 +++++++++++++ .../Calendar/CalendarPeriodsSwitches.tsx | 84 ++++++++ src/pages/Calendar.tsx | 149 ++++++++------- src/utils/calendar.tsx | 180 +++++++++++++++++- src/utils/colors.ts | 8 + 25 files changed, 666 insertions(+), 73 deletions(-) create mode 100644 assets/calendar/emoticons/boom.svg create mode 100644 assets/calendar/emoticons/broken_heart.svg create mode 100644 assets/calendar/emoticons/cry_face.svg create mode 100644 assets/calendar/emoticons/desperate.svg create mode 100644 assets/calendar/emoticons/fall_in_love.svg create mode 100644 assets/calendar/emoticons/grinning.svg create mode 100644 assets/calendar/emoticons/heart.svg create mode 100644 assets/calendar/emoticons/laughing.svg create mode 100644 assets/calendar/emoticons/look_aside.svg create mode 100644 assets/calendar/emoticons/normal_smile.svg create mode 100644 assets/calendar/emoticons/one_hundred.svg create mode 100644 assets/calendar/emoticons/sick_face.svg create mode 100644 assets/calendar/emoticons/smile.svg create mode 100644 assets/calendar/emoticons/smile_eyes_closed.svg create mode 100644 assets/calendar/emoticons/smile_eyes_open.svg create mode 100644 assets/calendar/emoticons/smile_eyes_triangle.svg create mode 100644 assets/calendar/emoticons/smile_water_drop.svg create mode 100644 assets/calendar/emoticons/star_eyes.svg create mode 100644 src/components/Calendar/Button.tsx create mode 100644 src/components/Calendar/CalendarAddEvent.tsx create mode 100644 src/components/Calendar/CalendarMonthlyEvents.tsx create mode 100644 src/components/Calendar/CalendarPeriodsSwitches.tsx diff --git a/assets/calendar/emoticons/boom.svg b/assets/calendar/emoticons/boom.svg new file mode 100644 index 00000000..e7628655 --- /dev/null +++ b/assets/calendar/emoticons/boom.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/calendar/emoticons/broken_heart.svg b/assets/calendar/emoticons/broken_heart.svg new file mode 100644 index 00000000..70a21c4d --- /dev/null +++ b/assets/calendar/emoticons/broken_heart.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/calendar/emoticons/cry_face.svg b/assets/calendar/emoticons/cry_face.svg new file mode 100644 index 00000000..d3b7a08b --- /dev/null +++ b/assets/calendar/emoticons/cry_face.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/assets/calendar/emoticons/desperate.svg b/assets/calendar/emoticons/desperate.svg new file mode 100644 index 00000000..20ed65f2 --- /dev/null +++ b/assets/calendar/emoticons/desperate.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/calendar/emoticons/fall_in_love.svg b/assets/calendar/emoticons/fall_in_love.svg new file mode 100644 index 00000000..18ee1a90 --- /dev/null +++ b/assets/calendar/emoticons/fall_in_love.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/calendar/emoticons/grinning.svg b/assets/calendar/emoticons/grinning.svg new file mode 100644 index 00000000..e633f020 --- /dev/null +++ b/assets/calendar/emoticons/grinning.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/calendar/emoticons/heart.svg b/assets/calendar/emoticons/heart.svg new file mode 100644 index 00000000..6ba56415 --- /dev/null +++ b/assets/calendar/emoticons/heart.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/calendar/emoticons/laughing.svg b/assets/calendar/emoticons/laughing.svg new file mode 100644 index 00000000..755b0755 --- /dev/null +++ b/assets/calendar/emoticons/laughing.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/calendar/emoticons/look_aside.svg b/assets/calendar/emoticons/look_aside.svg new file mode 100644 index 00000000..216a3a61 --- /dev/null +++ b/assets/calendar/emoticons/look_aside.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/calendar/emoticons/normal_smile.svg b/assets/calendar/emoticons/normal_smile.svg new file mode 100644 index 00000000..5b96470c --- /dev/null +++ b/assets/calendar/emoticons/normal_smile.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/calendar/emoticons/one_hundred.svg b/assets/calendar/emoticons/one_hundred.svg new file mode 100644 index 00000000..e09c4e2f --- /dev/null +++ b/assets/calendar/emoticons/one_hundred.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/calendar/emoticons/sick_face.svg b/assets/calendar/emoticons/sick_face.svg new file mode 100644 index 00000000..aa5eb970 --- /dev/null +++ b/assets/calendar/emoticons/sick_face.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/calendar/emoticons/smile.svg b/assets/calendar/emoticons/smile.svg new file mode 100644 index 00000000..f3ac3c0a --- /dev/null +++ b/assets/calendar/emoticons/smile.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/calendar/emoticons/smile_eyes_closed.svg b/assets/calendar/emoticons/smile_eyes_closed.svg new file mode 100644 index 00000000..9d37a9a8 --- /dev/null +++ b/assets/calendar/emoticons/smile_eyes_closed.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/calendar/emoticons/smile_eyes_open.svg b/assets/calendar/emoticons/smile_eyes_open.svg new file mode 100644 index 00000000..705080a8 --- /dev/null +++ b/assets/calendar/emoticons/smile_eyes_open.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/calendar/emoticons/smile_eyes_triangle.svg b/assets/calendar/emoticons/smile_eyes_triangle.svg new file mode 100644 index 00000000..d4a56e3e --- /dev/null +++ b/assets/calendar/emoticons/smile_eyes_triangle.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/calendar/emoticons/smile_water_drop.svg b/assets/calendar/emoticons/smile_water_drop.svg new file mode 100644 index 00000000..9058b0eb --- /dev/null +++ b/assets/calendar/emoticons/smile_water_drop.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/calendar/emoticons/star_eyes.svg b/assets/calendar/emoticons/star_eyes.svg new file mode 100644 index 00000000..d06c0958 --- /dev/null +++ b/assets/calendar/emoticons/star_eyes.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/components/Calendar/Button.tsx b/src/components/Calendar/Button.tsx new file mode 100644 index 00000000..f2906c0a --- /dev/null +++ b/src/components/Calendar/Button.tsx @@ -0,0 +1,33 @@ +import { FC } from "react" +import { Pressable, ViewStyle } from "react-native" +import { usePalette } from "utils/colors" + +interface CalendarButton { + children: React.ReactNode + onPress?: () => void + + style?: ViewStyle +} + +export const CalendarButton: FC = props => { + const { palette } = usePalette() + + return ( + + {props.children} + + ) +} diff --git a/src/components/Calendar/CalendarAddEvent.tsx b/src/components/Calendar/CalendarAddEvent.tsx new file mode 100644 index 00000000..4b87f1cd --- /dev/null +++ b/src/components/Calendar/CalendarAddEvent.tsx @@ -0,0 +1,57 @@ +import { FC } from "react" +import { View, ScrollView, StyleSheet } from "react-native" +import { CalendarEvent } from "utils/calendar" +import { Text } from "components/Text" +import { usePalette } from "utils/colors" +import { CalendarButton } from "./Button" + +interface CalendarAddEventProps { + addEvent: (event: CalendarEvent) => void + date: string +} + +export const CalendarAddEvent: FC = props => { + const { homeBackground, dotColor } = usePalette() + + const dateObj = new Date(props.date) + + // ! WIP + return ( + + + + Nuovo Evento + + + + Ok + + + Annulla + + + + + ) +} + +//stylesheet +const styles = StyleSheet.create({ + mediumSizeText: { + fontSize: 16, + fontWeight: "700", + }, + smallSizeText: { fontSize: 12, fontWeight: "400" }, + title: { + fontSize: 20, + fontWeight: "900", + }, +}) diff --git a/src/components/Calendar/CalendarMonthlyEvents.tsx b/src/components/Calendar/CalendarMonthlyEvents.tsx new file mode 100644 index 00000000..b4b04326 --- /dev/null +++ b/src/components/Calendar/CalendarMonthlyEvents.tsx @@ -0,0 +1,128 @@ +import { FC } from "react" +import { View, ScrollView, StyleSheet } from "react-native" +import { + CalendarEvent, + formatCalendarEventDay, + getSourceEmoticon, +} from "utils/calendar" +import { Text } from "components/Text" +import { usePalette } from "utils/colors" +import { Icon } from "components/Icon" +import { Divider } from "components/Divider" + +interface CalendarMonthlyEventsProps { + events: CalendarEvent[] + month: string + year: number + lan: string +} + +export const CalendarMonthlyEvents: FC = props => { + const { events, month, year, lan } = props + + const { homeBackground, dotColor } = usePalette() + + return ( + + + {month + " " + year} + + + + {events.length > 0 && ( + + )} + + {events.length > 0 + ? events.length + " eventi in programma" + : "Nessun evento in programma"} + + + {events.map(event => { + return ( + + + + + + + + {event.title} + + + {formatCalendarEventDay(event, lan)} + + + + Note + + + + ) + })} + + ) +} + +//stylesheet +const styles = StyleSheet.create({ + mediumSizeText: { + fontSize: 16, + fontWeight: "700", + }, + smallSizeText: { fontSize: 12, fontWeight: "400" }, + monthTitle: { + fontSize: 20, + fontWeight: "900", + }, +}) diff --git a/src/components/Calendar/CalendarPeriodsSwitches.tsx b/src/components/Calendar/CalendarPeriodsSwitches.tsx new file mode 100644 index 00000000..c7e13845 --- /dev/null +++ b/src/components/Calendar/CalendarPeriodsSwitches.tsx @@ -0,0 +1,84 @@ +import { FC } from "react" +import { View, ScrollView, StyleSheet } from "react-native" +import { CalendarPeriod } from "utils/calendar" +import { ToggleSwitch } from "components/ToggleSwitch" +import { Text } from "components/Text" +import { usePalette } from "utils/colors" + +interface CalendarPeriodsSwitchesProps { + calendarPeriods?: CalendarPeriod[] + month: string + year: number + onSwitchChange: (value: boolean, title: string) => void +} + +export const CalendarPeriodsSwitches: FC< + CalendarPeriodsSwitchesProps +> = props => { + const { calendarPeriods, month, year } = props + + const { homeBackground } = usePalette() + + if (!calendarPeriods) return null + + return ( + + + {month + " " + year} + + {calendarPeriods.map(period => { + return ( + + + + {period.title} + + + {period.subtitle} + + + props.onSwitchChange(value, period.title)} + /> + + ) + })} + + ) +} + +//stylesheet +const styles = StyleSheet.create({ + periodTitle: { + fontSize: 16, + fontWeight: "700", + }, + periodSubTitle: { + fontSize: 12, + fontWeight: "400", + }, + monthTitle: { + fontSize: 20, + fontWeight: "900", + }, +}) diff --git a/src/pages/Calendar.tsx b/src/pages/Calendar.tsx index d5b85964..880afabc 100644 --- a/src/pages/Calendar.tsx +++ b/src/pages/Calendar.tsx @@ -2,7 +2,7 @@ import { MainStackScreen } from "navigation/NavigationTypes" import { useTranslation } from "react-i18next" import { BoxShadowView } from "components/BoxShadow" import { NavBar } from "components/NavBar" -import { ScrollView, View } from "react-native" +import { Pressable, View } from "react-native" import { usePalette } from "utils/colors" import { StyleSheet } from "react-native" import { Calendar } from "react-native-calendars" @@ -11,26 +11,35 @@ import { CalendarPeriod, CalendarSingletonWrapper as CalendarManager, dayComponentCustom, - dotColorGold, months, daysOfWeekLetters, + CalendarBottomSheetStatus, + CalendarEvent, } from "utils/calendar" import { MarkedDates } from "react-native-calendars/src/types" import { Text } from "components/Text" -import { ToggleSwitch } from "components/ToggleSwitch" import { Icon } from "components/Icon" import calendarIcon from "assets/calendar/calendar.svg" import capeIcon from "assets/calendar/cape_calendar.svg" import userIcon from "assets/calendar/user_calendar.svg" +import { CalendarPeriodsSwitches } from "components/Calendar/CalendarPeriodsSwitches" +import { CalendarMonthlyEvents } from "components/Calendar/CalendarMonthlyEvents" +import { useCurrentLanguage } from "utils/articles" +import { CalendarAddEvent } from "components/Calendar/CalendarAddEvent" export const CalendarPage: MainStackScreen<"Calendar"> = () => { - const { homeBackground, background, isLight, palette } = usePalette() + const { homeBackground, background, dotColor } = usePalette() const { t } = useTranslation() + const lan = useCurrentLanguage() + const [selectedDay, setSelectedDay] = useState( new Date().toISOString().slice(0, 10) ) + const [bottomSheetStatus, setBottomSheetStatus] = + useState(CalendarBottomSheetStatus.PERIODS) + const [month, setMonth] = useState(new Date().getMonth()) const [year, setYear] = useState(new Date().getFullYear()) @@ -41,6 +50,12 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { CalendarPeriod[] | undefined >() + const [calendarEvents, setCalendarEvents] = useState([]) + + const [calendarEventsMonth, setCalendarEventsMonth] = useState< + CalendarEvent[] + >([]) + useEffect(() => { console.log(selectedDay) }, [selectedDay]) @@ -63,6 +78,14 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { setCalendarPeriods(calendarObj.current?.calendarPeriods) } }) + + calendarObj.current.addListener("calendarEventsChanged", () => { + console.log("calendarEventsChanged") + if (calendarObj.current?.calendarEvents) { + /* console.log(calendarObj.current?.calendarEvents) */ + setCalendarEvents(calendarObj.current?.calendarEvents) + } + }) } else { if (calendarObj.current?.markedDatesPeriods) { setMarkedDates(calendarObj.current?.markedDatesPeriods) @@ -76,9 +99,22 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { return () => { calendarObj?.current?.removeAllListeners("markedDatesSet") calendarObj?.current?.removeAllListeners("calendarPeriodsChanged") + calendarObj?.current?.removeAllListeners("calendarEventsChanged") } }, []) + useEffect(() => { + if (calendarEvents.length > 0) { + const filteredEvents = calendarEvents.filter( + event => + new Date(event.start).getMonth() === month && + new Date(event.start).getFullYear() === year + ) + /* console.log(filteredEvents) */ + setCalendarEventsMonth(filteredEvents) + } + }, [calendarEvents, month, year]) + return ( = () => { marginBottom: 8, }} > - + { + if (bottomSheetStatus === CalendarBottomSheetStatus.PERIODS) { + setBottomSheetStatus(CalendarBottomSheetStatus.MONTHLY_EVENTS) + } else { + setBottomSheetStatus(CalendarBottomSheetStatus.PERIODS) + } + }} + > + + + @@ -130,10 +177,12 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { todayTextColor: "yellow", dayTextColor: "#fff", dotStyle: { width: 6, height: 6, borderRadius: 3 }, - dotColor: dotColorGold, + dotColor: dotColor, }} onDayPress={day => { - console.log(day) + setSelectedDay(day.dateString) + + setBottomSheetStatus(CalendarBottomSheetStatus.ADD_EVENT) }} style={{ marginTop: 150, @@ -168,7 +217,6 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment dayComponent={dayComponentCustom} /> - {/* */} = () => { styles.boxShadowContainer, ]} > - {calendarPeriods && ( - + calendarObj.current?.updatePeriods(title, value) + } + /> + )} + {bottomSheetStatus === CalendarBottomSheetStatus.MONTHLY_EVENTS && ( + + )} + {bottomSheetStatus === CalendarBottomSheetStatus.ADD_EVENT && ( + { + return }} - style={{ marginBottom: 90 }} - > - - {months[month] + " " + year} - - {calendarPeriods.map(period => { - return ( - - - - {period.title} - - - {period.subtitle} - - - - calendarObj.current?.updatePeriods(period.title, value) - } - /> - - ) - })} - {/* */} - + date={selectedDay} + /> )} @@ -253,16 +276,4 @@ const styles = StyleSheet.create({ borderTopRightRadius: 30, overflow: "visible", }, - periodTitle: { - fontSize: 16, - fontWeight: "700", - }, - periodSubTitle: { - fontSize: 12, - fontWeight: "400", - }, - monthTitle: { - fontSize: 20, - fontWeight: "900", - }, }) diff --git a/src/utils/calendar.tsx b/src/utils/calendar.tsx index 5a81dfe2..e54027d6 100644 --- a/src/utils/calendar.tsx +++ b/src/utils/calendar.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/naming-convention */ import { DateData, MarkedDates } from "react-native-calendars/src/types" import * as FileSystem from "expo-file-system" import { EventEmitter } from "events" @@ -6,10 +7,36 @@ import { TouchableOpacity, View, ViewStyle } from "react-native" import { DayProps } from "react-native-calendars/src/calendar/day" import { Text } from "components/Text" import { Canvas, Path, Skia } from "@shopify/react-native-skia" +import { palette } from "./colors" +import boomSvg from "assets/calendar/emoticons/boom.svg" +import brokenHeartSvg from "assets/calendar/emoticons/broken_heart.svg" +import cryFaceSvg from "assets/calendar/emoticons/cry_face.svg" +import desperateSvg from "assets/calendar/emoticons/desperate.svg" +import fallInLoveSvg from "assets/calendar/emoticons/fall_in_love.svg" +import grinningSvg from "assets/calendar/emoticons/grinning.svg" +import heartSvg from "assets/calendar/emoticons/heart.svg" +import laughingSvg from "assets/calendar/emoticons/laughing.svg" +import lookAsideSvg from "assets/calendar/emoticons/look_aside.svg" +import normalSmileSvg from "assets/calendar/emoticons/normal_smile.svg" +import oneHundredSvg from "assets/calendar/emoticons/one_hundred.svg" +import sickFaceSvg from "assets/calendar/emoticons/sick_face.svg" +import smileEyesClosedSvg from "assets/calendar/emoticons/smile_eyes_closed.svg" +import smileEyesOpenSvg from "assets/calendar/emoticons/smile_eyes_open.svg" +import smileEyesTriangleSvg from "assets/calendar/emoticons/smile_eyes_triangle.svg" +import smileWaterDropSvg from "assets/calendar/emoticons/smile_water_drop.svg" +import smileSvg from "assets/calendar/emoticons/smile.svg" +import starEyesSvg from "assets/calendar/emoticons/star_eyes.svg" -export const dotColorGold = "rgba(242, 186, 82, 1)" export const purpleBerry = "rgba(98, 96, 166, 1)" +export enum CalendarBottomSheetStatus { + PERIODS, + MONTHLY_EVENTS, + DAILY_EVENTS, + ADD_EVENT, + EVENT_DETAILS, +} + export interface Period { start?: string end?: string @@ -37,9 +64,11 @@ export interface CalendarEvent { repeats?: boolean //this is weird - mood?: string + mood?: ValidEmoticonName status: CalendarEventStatus + + id: string } export enum CalendarEventStatus { @@ -53,7 +82,7 @@ const calendarPeriods: CalendarPeriod[] = [ dates: [{ start: "2023-08-01", end: "2023-08-24" }], title: "Vacanze", subtitle: "1/08 - 24/08", - color: dotColorGold, + color: palette.goldish, shown: true, }, { @@ -88,6 +117,8 @@ export declare interface CalendarSingletonWrapper { on(event: "calendarPeriodsChanged", listener: () => void): this on(event: "markedDatesSet", listener: () => void): this + + on(event: "calendarEventsChanged", listener: () => void): this } export class CalendarSingletonWrapper extends EventEmitter { @@ -104,11 +135,48 @@ export class CalendarSingletonWrapper extends EventEmitter { private _calendarEvents: CalendarEvent[] = [] + public get calendarEvents(): CalendarEvent[] { + return this._calendarEvents + } + public constructor() { super() void this._initializeCalendar() } private async _initializeCalendar() { + await this._writeEvents([]) + await this._writeEvents([ + { + id: "1", + title: "prova", + start: "2023-08-01T14:00:00.000Z", + end: "2023-08-01T15:00:00.000Z", + status: CalendarEventStatus.INITIAL, + mood: "boom", + reminder: "2021-08-01T13:00:00.000Z", + repeats: false, + }, + { + id: "2", + title: "prova2", + start: "2023-08-02T14:00:00.000Z", + end: "2021-08-02T15:00:00.000Z", + status: CalendarEventStatus.INITIAL, + mood: "cry_face", + reminder: "2021-08-02T13:00:00.000Z", + repeats: false, + }, + { + id: "3", + title: "prova3", + start: "2023-08-03T14:00:00.000Z", + end: "2021-08-03T15:00:00.000Z", + status: CalendarEventStatus.INITIAL, + mood: "look_aside", + reminder: "2021-08-03T13:00:00.000Z", + repeats: false, + }, + ]) await this._readEvents() await this._readCalendarPeriods() this._applyPeriods() @@ -121,6 +189,8 @@ export class CalendarSingletonWrapper extends EventEmitter { ) const calendarEvents = JSON.parse(calendarEventsJSON) as CalendarEvent[] this._calendarEvents = calendarEvents + + this.emit("calendarEventsChanged") } catch (err) { console.log(err) console.log("Error reading calendarEvents") @@ -136,6 +206,7 @@ export class CalendarSingletonWrapper extends EventEmitter { calendarEventsJSON ) + this.emit("calendarEventsChanged") return true } catch (err) { console.log(err) @@ -382,7 +453,15 @@ export const dayComponentCustom: ComponentType< return ( onPress(dateData) : undefined} + onPress={ + onPress + ? () => { + console.log("pressing!!") + console.log(dateData) + onPress(dateData) + } + : undefined + } onLongPress={onLongPress ? () => onLongPress(dateData) : undefined} > { + const date = new Date(event.start) + + const day = date.getDate() + + const month = date.getMonth() + 1 + + const dayNumber = date.getDay() + + let dayOfTheWeek + + if (lan === "it") { + dayOfTheWeek = daysOfWeekIt[dayNumber] + } else { + dayOfTheWeek = daysOfWeekEn[dayNumber] + } + + return `${day.toString().padStart(2, "0")}/${month + .toString() + .padStart(2, "0")} | ${dayOfTheWeek}` +} + +type ValidEmoticonName = + | "boom" + | "broken_heart" + | "cry_face" + | "desperate" + | "fall_in_love" + | "grinning" + | "heart" + | "laughing" + | "look_aside" + | "normal_smile" + | "one_hundred" + | "sick_face" + | "smile_eyes_closed" + | "smile_eyes_open" + | "smile_eyes_triangle" + | "smile_water_drop" + | "smile" + | "star_eyes" + +const emoticons: Record = { + boom: boomSvg, + broken_heart: brokenHeartSvg, + cry_face: cryFaceSvg, + desperate: desperateSvg, + fall_in_love: fallInLoveSvg, + grinning: grinningSvg, + heart: heartSvg, + laughing: laughingSvg, + look_aside: lookAsideSvg, + normal_smile: normalSmileSvg, + one_hundred: oneHundredSvg, + sick_face: sickFaceSvg, + smile_eyes_closed: smileEyesClosedSvg, + smile_eyes_open: smileEyesOpenSvg, + smile_eyes_triangle: smileEyesTriangleSvg, + smile_water_drop: smileWaterDropSvg, + smile: smileSvg, + star_eyes: starEyesSvg, +} + +export const getSourceEmoticon = (emoticon: ValidEmoticonName | undefined) => { + if (emoticon) { + return emoticons[emoticon] + } else { + return smileSvg + } +} diff --git a/src/utils/colors.ts b/src/utils/colors.ts index 7985d2e8..d82bc008 100644 --- a/src/utils/colors.ts +++ b/src/utils/colors.ts @@ -13,6 +13,7 @@ export const palette = { accent: "#FFB544", widgetBgLighter: "#F6F7FC", widgetBgDarker: "#343E5A", + goldish: "rgba(242, 186, 82, 1)", } as const export type Palette = typeof palette @@ -114,6 +115,11 @@ export interface ColorTheme { * purple/blueish in light mode, white in dark mode, used in TimeLeftTile */ iconHighContrast: string + + /** + * color used for dots inside calendar Page + */ + dotColor: string } /** @@ -202,6 +208,7 @@ export const usePalette: () => ColorTheme & sliderBorderColor: palette.variant3, labelsHighContrast: palette.variant1, // "#414867", iconHighContrast: palette.variant3, // "#454773", + dotColor: palette.goldish, } const darkTheme: ColorTheme = { @@ -221,6 +228,7 @@ export const usePalette: () => ColorTheme & sliderBorderColor: "#FFFFFF", labelsHighContrast: "#FFFFFF", iconHighContrast: "#FFFFFF", + dotColor: palette.goldish, } const colors = isLight ? lightTheme : darkTheme From c177fce7858165a2612bb9d6479bec89d57d10c3 Mon Sep 17 00:00:00 2001 From: DiegoZaff Date: Sat, 5 Aug 2023 13:35:47 +0200 Subject: [PATCH 06/31] Add and remove event --- assets/calendar/emoticons/smile.svg | 11 +- src/components/Calendar/CalendarAddEvent.tsx | 386 +++++++++++++++++- .../Calendar/CalendarMonthlyEvents.tsx | 23 +- .../FreeClass/DateTimePicker/DateTimeBox.tsx | 3 +- src/pages/Calendar.tsx | 41 +- src/utils/calendar.tsx | 251 +++++++++--- 6 files changed, 628 insertions(+), 87 deletions(-) diff --git a/assets/calendar/emoticons/smile.svg b/assets/calendar/emoticons/smile.svg index f3ac3c0a..705080a8 100644 --- a/assets/calendar/emoticons/smile.svg +++ b/assets/calendar/emoticons/smile.svg @@ -1,6 +1,7 @@ - - - - - + + + + + + diff --git a/src/components/Calendar/CalendarAddEvent.tsx b/src/components/Calendar/CalendarAddEvent.tsx index 4b87f1cd..5c0e78f1 100644 --- a/src/components/Calendar/CalendarAddEvent.tsx +++ b/src/components/Calendar/CalendarAddEvent.tsx @@ -1,20 +1,134 @@ -import { FC } from "react" -import { View, ScrollView, StyleSheet } from "react-native" -import { CalendarEvent } from "utils/calendar" -import { Text } from "components/Text" +import { FC, useEffect, useRef, useState } from "react" +import { + View, + ScrollView, + StyleSheet, + TextInput, + Keyboard, + Pressable, +} from "react-native" +import { + CalendarEvent, + CalendarEventStatus, + ValidEmoticonName, + emoticons, + fromatAddEventDate, + get1HourBeforeAfterSameDay, + getSourceEmoticon, + isValidEmoticonName, +} from "utils/calendar" +import { BodyText, Text } from "components/Text" import { usePalette } from "utils/colors" import { CalendarButton } from "./Button" +import { useCurrentLanguage } from "utils/articles" +import { DateTimeBox } from "components/FreeClass/DateTimePicker/DateTimeBox" +import DateTimePickerModal from "react-native-modal-datetime-picker" +import { Icon } from "components/Icon" +import { Modal } from "components/Modal" interface CalendarAddEventProps { addEvent: (event: CalendarEvent) => void date: string } +type DateModeCalendar = "start" | "end" | "reminder" + export const CalendarAddEvent: FC = props => { - const { homeBackground, dotColor } = usePalette() + const { homeBackground, isLight, primary } = usePalette() + + const lan = useCurrentLanguage() const dateObj = new Date(props.date) + const [title, setTitle] = useState("") + + const [isRepeating, setIsRepeating] = useState(false) + + const [mood, setMood] = useState(undefined) + + const [moodSource, setMoodSource] = useState(undefined) + + const [isMoodModalShowing, setIsMoodModalShowing] = useState(false) + + const inputText = useRef(null) + + const [dateModeCalendar, setDateModeCalendar] = + useState("start") + + const [startDate, setStartDate] = useState(new Date()) + + const [endDate, setEndDate] = useState( + get1HourBeforeAfterSameDay(startDate, true) + ) + + const [reminderDate, setReminderDate] = useState(undefined) + + const [isDatePickerVisible, setDatePickerVisibility] = useState(false) + + useEffect(() => { + const keyboardDidHideListener = Keyboard.addListener( + "keyboardDidHide", + () => { + inputText.current?.blur() + } + ) + + return () => { + keyboardDidHideListener.remove() + } + }, []) + + const showTimePicker = (mode: DateModeCalendar) => { + setDateModeCalendar(mode) + setDatePickerVisibility(true) + } + + const hideDateOrTimePicker = () => { + setDatePickerVisibility(false) + } + + const handleConfirm = (date: Date, mode: DateModeCalendar) => { + hideDateOrTimePicker() + if (mode === "start") { + setStartDate(date) + + if (date.getTime() > endDate.getTime()) { + setEndDate(get1HourBeforeAfterSameDay(date, true)) + } + } else if (mode === "end") { + setEndDate(date) + + if (date.getTime() < startDate.getTime()) { + setStartDate(get1HourBeforeAfterSameDay(date, false)) + } + } else { + setReminderDate(date) + } + } + + const resetNewEvent = () => { + setTitle("") + setMood(undefined) + setIsRepeating(false) + const now = new Date() + setStartDate(now) + setEndDate(get1HourBeforeAfterSameDay(now, true)) + setReminderDate(undefined) + } + + useEffect(() => { + if (mood === undefined) { + setMoodSource(undefined) + } else { + setMoodSource(getSourceEmoticon(mood)) + } + }, [mood]) + + useEffect(() => { + setStartDate(new Date(props.date)) + setEndDate(get1HourBeforeAfterSameDay(new Date(props.date), true)) + }, [props.date]) + // ! WIP return ( = props => { > Nuovo Evento - + { + if ( + title.length > 0 && + startDate.getTime() < endDate.getTime() && + startDate.getDate() === endDate.getDate() + ) { + props.addEvent({ + id: Date.now().toString(), + start: startDate.toISOString(), + end: endDate.toISOString(), + title: title, + mood: mood, + repeats: isRepeating, + reminder: reminderDate?.toISOString(), + status: CalendarEventStatus.INITIAL, + }) + } + }} + > Ok - + { + resetNewEvent() + }} + > Annulla + + {fromatAddEventDate(dateObj, lan)} + + { + setTitle(text) + }} + ref={inputText} + placeholderTextColor={homeBackground} + placeholder="Aggiungi Titolo" + /> + + + + Da + + { + showTimePicker("start") + }} + style={{ flexDirection: "row" }} + > + + + : + + + + + + + A + + { + showTimePicker("end") + }} + style={{ flexDirection: "row" }} + > + + + : + + + + + + + + + Imposta Promemoria + + + { + showTimePicker("reminder") + }} + style={{ flexDirection: "row", marginTop: 8 }} + > + + + : + + + + + + + setIsMoodModalShowing(true)} + > + + Mood + {moodSource && ( + + )} + + + { + setIsRepeating(!isRepeating) + }} + > + + {isRepeating ? "Si ripete" : "Non si ripete"} + + + + + { + handleConfirm(date, dateModeCalendar) + }} + onCancel={hideDateOrTimePicker} + date={dateModeCalendar === "start" ? startDate : endDate} + /> + setIsMoodModalShowing(false)} + > + + {Object.keys(emoticons).map((emoticon, index) => { + if (index <= 8 && isValidEmoticonName(emoticon)) { + return ( + { + setMood(emoticon) + setIsMoodModalShowing(false) + }} + > + + + ) + } + })} + + + {Object.keys(emoticons).map((emoticon, index) => { + if (index > 8 && isValidEmoticonName(emoticon)) { + return ( + { + setMood(emoticon) + setIsMoodModalShowing(false) + }} + > + + + ) + } + })} + + ) } @@ -54,4 +423,5 @@ const styles = StyleSheet.create({ fontSize: 20, fontWeight: "900", }, + colon: { alignSelf: "center", marginHorizontal: 4, fontSize: 14 }, }) diff --git a/src/components/Calendar/CalendarMonthlyEvents.tsx b/src/components/Calendar/CalendarMonthlyEvents.tsx index b4b04326..61066c3d 100644 --- a/src/components/Calendar/CalendarMonthlyEvents.tsx +++ b/src/components/Calendar/CalendarMonthlyEvents.tsx @@ -1,5 +1,5 @@ import { FC } from "react" -import { View, ScrollView, StyleSheet } from "react-native" +import { View, ScrollView, StyleSheet, Pressable } from "react-native" import { CalendarEvent, formatCalendarEventDay, @@ -9,12 +9,14 @@ import { Text } from "components/Text" import { usePalette } from "utils/colors" import { Icon } from "components/Icon" import { Divider } from "components/Divider" +import deleteSvg from "assets/modal/delete.svg" interface CalendarMonthlyEventsProps { events: CalendarEvent[] month: string year: number lan: string + onDeleteEvent: (id: string) => void } export const CalendarMonthlyEvents: FC = props => { @@ -86,9 +88,22 @@ export const CalendarMonthlyEvents: FC = props => { justifyContent: "center", }} > - - {event.title} - + + + {event.title} + + props.onDeleteEvent(event.id)}> + + + + = props => { return ( = () => { const { homeBackground, background, dotColor } = usePalette() - const { t } = useTranslation() + + // todo : implement translation :( + /* const { t } = useTranslation() */ const lan = useCurrentLanguage() - const [selectedDay, setSelectedDay] = useState( - new Date().toISOString().slice(0, 10) - ) + const [selectedDay, setSelectedDay] = useState(new Date().toISOString()) const [bottomSheetStatus, setBottomSheetStatus] = useState(CalendarBottomSheetStatus.PERIODS) @@ -68,6 +69,7 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { calendarObj.current = new CalendarManager() calendarObj.current.addListener("markedDatesSet", () => { if (calendarObj.current?.markedDatesPeriods) { + console.log("marked dates sets") setMarkedDates(calendarObj.current?.markedDatesPeriods) setCalendarPeriods(calendarObj.current?.calendarPeriods) } @@ -75,15 +77,15 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { calendarObj.current.addListener("calendarPeriodsChanged", () => { if (calendarObj.current?.calendarPeriods) { + console.log("calendarPeriodsChanged") setCalendarPeriods(calendarObj.current?.calendarPeriods) } }) calendarObj.current.addListener("calendarEventsChanged", () => { - console.log("calendarEventsChanged") if (calendarObj.current?.calendarEvents) { - /* console.log(calendarObj.current?.calendarEvents) */ - setCalendarEvents(calendarObj.current?.calendarEvents) + console.log("calendarEventsChanged") + setCalendarEvents([...(calendarObj.current?.calendarEvents ?? [])]) } }) } else { @@ -110,7 +112,7 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { new Date(event.start).getMonth() === month && new Date(event.start).getFullYear() === year ) - /* console.log(filteredEvents) */ + setCalendarEventsMonth(filteredEvents) } }, [calendarEvents, month, year]) @@ -180,7 +182,14 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { dotColor: dotColor, }} onDayPress={day => { - setSelectedDay(day.dateString) + const date = new Date(day.dateString) + const now = new Date() + + //set hours and minutes of date to now + date.setHours(now.getHours()) + date.setMinutes(now.getMinutes()) + + setSelectedDay(date.toISOString()) setBottomSheetStatus(CalendarBottomSheetStatus.ADD_EVENT) }} @@ -233,7 +242,7 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { {bottomSheetStatus === CalendarBottomSheetStatus.PERIODS && ( calendarObj.current?.updatePeriods(title, value) @@ -243,15 +252,19 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { {bottomSheetStatus === CalendarBottomSheetStatus.MONTHLY_EVENTS && ( { + calendarObj.current?.removeEvent(id) + }} /> )} {bottomSheetStatus === CalendarBottomSheetStatus.ADD_EVENT && ( { - return + calendarObj.current?.addEvent(event) + setBottomSheetStatus(CalendarBottomSheetStatus.MONTHLY_EVENTS) }} date={selectedDay} /> diff --git a/src/utils/calendar.tsx b/src/utils/calendar.tsx index e54027d6..41f26d8b 100644 --- a/src/utils/calendar.tsx +++ b/src/utils/calendar.tsx @@ -2,7 +2,7 @@ import { DateData, MarkedDates } from "react-native-calendars/src/types" import * as FileSystem from "expo-file-system" import { EventEmitter } from "events" -import { ComponentType, useMemo } from "react" +import { ComponentType, useEffect, useMemo, useState } from "react" import { TouchableOpacity, View, ViewStyle } from "react-native" import { DayProps } from "react-native-calendars/src/calendar/day" import { Text } from "components/Text" @@ -144,43 +144,9 @@ export class CalendarSingletonWrapper extends EventEmitter { void this._initializeCalendar() } private async _initializeCalendar() { - await this._writeEvents([]) - await this._writeEvents([ - { - id: "1", - title: "prova", - start: "2023-08-01T14:00:00.000Z", - end: "2023-08-01T15:00:00.000Z", - status: CalendarEventStatus.INITIAL, - mood: "boom", - reminder: "2021-08-01T13:00:00.000Z", - repeats: false, - }, - { - id: "2", - title: "prova2", - start: "2023-08-02T14:00:00.000Z", - end: "2021-08-02T15:00:00.000Z", - status: CalendarEventStatus.INITIAL, - mood: "cry_face", - reminder: "2021-08-02T13:00:00.000Z", - repeats: false, - }, - { - id: "3", - title: "prova3", - start: "2023-08-03T14:00:00.000Z", - end: "2021-08-03T15:00:00.000Z", - status: CalendarEventStatus.INITIAL, - mood: "look_aside", - reminder: "2021-08-03T13:00:00.000Z", - repeats: false, - }, - ]) await this._readEvents() await this._readCalendarPeriods() this._applyPeriods() - /* this._markedDatesMerging() */ } private _readEvents = async () => { try { @@ -205,8 +171,6 @@ export class CalendarSingletonWrapper extends EventEmitter { FileSystem.documentDirectory + "calendar_events.json", calendarEventsJSON ) - - this.emit("calendarEventsChanged") return true } catch (err) { console.log(err) @@ -304,11 +268,10 @@ export class CalendarSingletonWrapper extends EventEmitter { this._markedDatesPeriods = { ...this._markedDatesPeriods, ...periodTmp } }) }) - this.emit("markedDatesSet") + this._applyMarkers() } public updatePeriods = (title: string, val: boolean) => { - console.log(val) const periods = this._calendarPeriods ?? [] for (let i = 0; i < periods.length; i++) { if (periods[i].title === title) { @@ -324,26 +287,56 @@ export class CalendarSingletonWrapper extends EventEmitter { this._applyPeriods() } - // ! non testata public addEvent = (event: CalendarEvent) => { this._calendarEvents.push(event) + this.emit("calendarEventsChanged") + void this._writeEvents(this._calendarEvents) + + void this._applyMarkers() } - // ! non testata - public applyMarkers = () => { + private _applyMarkers = () => { for (let i = 0; i < this._calendarEvents.length; i++) { const dateString = this._calendarEvents[i].start.substring(0, 10) - this._markedDatesPeriods[dateString].marked = true + this._markedDatesPeriods[dateString] = { + ...this._markedDatesPeriods[dateString], + marked: true, + } } - this._calendarEvents + + this.emit("markedDatesSet") } - /* private _markedDatesMerging() { - throw new Error("Method not implemented.") - } */ + private _removeMarkers = (dateString: string) => { + const isAtLeastOneEvent = this.calendarEvents.find( + event => event.start.substring(0, 10) === dateString + ) + if (isAtLeastOneEvent) return + + this._markedDatesPeriods[dateString] = { + ...this._markedDatesPeriods[dateString], + marked: false, + } + + this.emit("markedDatesSet") + } + + public removeEvent = (id: string) => { + const index = this._calendarEvents.findIndex(event => event.id === id) + + if (index === -1) return + + const removedElement = this._calendarEvents.splice(index, 1)[0] + + this.emit("calendarEventsChanged") + + void this._writeEvents(this._calendarEvents) + + void this._removeMarkers(removedElement.start.substring(0, 10)) + } } const getNextDayFormattedDate = ( @@ -356,7 +349,7 @@ const getNextDayFormattedDate = ( return { dateString, dateObj } } -export const months = [ +export const monthsIt = [ "Gennaio", "Febbraio", "Marzo", @@ -371,6 +364,51 @@ export const months = [ "Dicembre", ] +export const monthsEn = [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "Augost", + "September", + "October", + "November", + "December", +] + +export const monthsAcronymsIt = [ + "Gen", + "Feb", + "Mar", + "Apr", + "Mag", + "Giu", + "Lug", + "Ago", + "Set", + "Ott", + "Nov", + "Dic", +] + +export const monthsAcronymsEn = [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Augost", + "Sep", + "Oct", + "Nov", + "Dec", +] + const FILLER_HEIGHT = 26 export const dayComponentCustom: ComponentType< @@ -384,14 +422,20 @@ export const dayComponentCustom: ComponentType< date, onPress, onLongPress, - state, + /* state, accessibilityLabel, - testID, + testID, */ children, } = props const dateData = dateToDateData(date) + const [isMarked, setIsMarked] = useState(marking?.marked ?? false) + + useEffect(() => { + setIsMarked(marking?.marked ?? false) + }, [marking]) + const fillerStyles = useMemo(() => { const leftFillerStyle: ViewStyle = { flex: 1 } const rightFillerStyle: ViewStyle = { flex: 1 } @@ -456,8 +500,6 @@ export const dayComponentCustom: ComponentType< onPress={ onPress ? () => { - console.log("pressing!!") - console.log(dateData) onPress(dateData) } : undefined @@ -521,7 +563,7 @@ export const dayComponentCustom: ComponentType< {String(children)} - {marking?.marked && ( + {isMarked && ( { .padStart(2, "0")} | ${dayOfTheWeek}` } -type ValidEmoticonName = +export type ValidEmoticonName = | "boom" | "broken_heart" | "cry_face" @@ -623,7 +685,31 @@ type ValidEmoticonName = | "smile" | "star_eyes" -const emoticons: Record = { +// Type guard function to check if the string is a ValidEmoticonName +export function isValidEmoticonName(name: string): name is ValidEmoticonName { + return [ + "boom", + "broken_heart", + "cry_face", + "desperate", + "fall_in_love", + "grinning", + "heart", + "laughing", + "look_aside", + "normal_smile", + "one_hundred", + "sick_face", + "smile_eyes_closed", + "smile_eyes_open", + "smile_eyes_triangle", + "smile_water_drop", + "smile", + "star_eyes", + ].includes(name) +} + +export const emoticons: Record = { boom: boomSvg, broken_heart: brokenHeartSvg, cry_face: cryFaceSvg, @@ -651,3 +737,58 @@ export const getSourceEmoticon = (emoticon: ValidEmoticonName | undefined) => { return smileSvg } } + +export const fromatAddEventDate = (date: Date, lan: string) => { + const day = date.getDay() + + let acronymDay + let monthAcronym + const dayNumber = date.getDate() + const year = date.getFullYear() + + if (lan === "it") { + acronymDay = daysOfWeekAcronymsIt[day] + monthAcronym = monthsAcronymsIt[date.getMonth()] + } else { + acronymDay = daysOfWeekAcronymsEn[day] + monthAcronym = monthsAcronymsEn[date.getMonth()] + } + + return `${acronymDay} ${dayNumber} ${monthAcronym} ${year}` +} + +export const get1HourBeforeAfterSameDay = ( + date: Date, + after: boolean +): Date => { + let newDate = date + if (after) { + newDate = new Date(date.getTime() + 60 * 60 * 1000) + + //if the new end date is not the same day as the start date set to midnight + if (newDate.getDate() !== date.getDate()) { + newDate = new Date( + date.getFullYear(), + date.getMonth(), + date.getDate(), + 23, + 59 + ) + } + } else { + newDate = new Date(date.getTime() - 60 * 60 * 1000) + + //if the new start date is not the same day as the end date set to midnight + if (newDate.getDate() !== date.getDate()) { + newDate = new Date( + date.getFullYear(), + date.getMonth(), + date.getDate(), + 0, + 0 + ) + } + } + + return newDate +} From 154d14c310a938ac29aac109fb55b55f2452c485 Mon Sep 17 00:00:00 2001 From: DiegoZaff Date: Sat, 26 Aug 2023 23:15:45 +0200 Subject: [PATCH 07/31] polimi events in calendar --- .../Calendar/CalendarMonthlyEvents.tsx | 15 +- src/pages/Calendar.tsx | 34 ++- src/utils/calendar.tsx | 223 +++++++++++++++++- 3 files changed, 259 insertions(+), 13 deletions(-) diff --git a/src/components/Calendar/CalendarMonthlyEvents.tsx b/src/components/Calendar/CalendarMonthlyEvents.tsx index 61066c3d..a4c4264e 100644 --- a/src/components/Calendar/CalendarMonthlyEvents.tsx +++ b/src/components/Calendar/CalendarMonthlyEvents.tsx @@ -95,13 +95,20 @@ export const CalendarMonthlyEvents: FC = props => { }} > {event.title} - props.onDeleteEvent(event.id)}> - - + {(event.isPolimiEvent == undefined || + event.isPolimiEvent == false) && ( + props.onDeleteEvent(event.id)}> + + + )} = () => { const { homeBackground, background, dotColor } = usePalette() @@ -34,6 +35,10 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { // todo : implement translation :( /* const { t } = useTranslation() */ + const { userInfo } = useContext(LoginContext) + + const { matricola } = userInfo?.careers?.[0] ?? {} + const lan = useCurrentLanguage() const [selectedDay, setSelectedDay] = useState(new Date().toISOString()) @@ -66,7 +71,10 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { useEffect(() => { const initCalendar = () => { if (!calendarObj.current) { - calendarObj.current = new CalendarManager() + calendarObj.current = new CalendarManager({ + hidePeriods: false, + matricola: matricola, + }) calendarObj.current.addListener("markedDatesSet", () => { if (calendarObj.current?.markedDatesPeriods) { console.log("marked dates sets") @@ -117,6 +125,28 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { } }, [calendarEvents, month, year]) + // hide or show peridos based on bottom sheet status + useEffect(() => { + if (bottomSheetStatus !== CalendarBottomSheetStatus.PERIODS) { + if (calendarObj.current?.hidePeriods == false) { + calendarObj.current?.hideAllPerdiods() + } + } else if (bottomSheetStatus === CalendarBottomSheetStatus.PERIODS) { + calendarObj.current?.showSwitchedOnPeriods() + } + }, [bottomSheetStatus]) + + // change matricola + useEffect(() => { + if ( + calendarObj.current && + matricola && + calendarObj.current.matricola !== matricola + ) { + calendarObj.current?.changeMatricola(matricola) + } + }, [matricola]) + return ( } export enum CalendarEventStatus { @@ -77,6 +85,11 @@ export enum CalendarEventStatus { COMPLETED, } +export interface CalendarPolimiSyncObj { + matricola?: string + lastSync?: string +} + const calendarPeriods: CalendarPeriod[] = [ { dates: [{ start: "2023-08-01", end: "2023-08-24" }], @@ -129,6 +142,13 @@ export class CalendarSingletonWrapper extends EventEmitter { } private _calendarPeriods?: CalendarPeriod[] + // if true all periods wont be shown even though they are switched on + private _hidePeriods = false + + public get hidePeriods(): boolean { + return this._hidePeriods + } + public get calendarPeriods(): CalendarPeriod[] | undefined { return this._calendarPeriods } @@ -139,15 +159,185 @@ export class CalendarSingletonWrapper extends EventEmitter { return this._calendarEvents } - public constructor() { + private _matricola?: string + + public get matricola(): string | undefined { + return this._matricola + } + + //matricola and last sync date with polimi events + private _calendarPolimiSync?: CalendarPolimiSyncObj + + public constructor({ + hidePeriods = false, + matricola, + }: { + hidePeriods?: boolean + matricola?: string + }) { super() + //weather or not I want to hide the periods as soon as the object is created + this._hidePeriods = hidePeriods + this._matricola = matricola void this._initializeCalendar() } private async _initializeCalendar() { await this._readEvents() + await this._readCaledarPolimiSync() await this._readCalendarPeriods() this._applyPeriods() + this._checkNeedSyncingPolimiEvents() + } + + public changeMatricola = (matricola?: string) => { + this._matricola = matricola + + this._checkNeedSyncingPolimiEvents() } + + private _checkNeedSyncingPolimiEvents = () => { + if (this._matricola == null) { + //oldMatricola set && newMatricola undefined + if (this._calendarPolimiSync?.matricola) { + this._cleanCalendarEventsFromPolimiEvents({ calledBeforeSync: false }) + + this._calendarPolimiSync = {} + void this._writeCalendarPolimiSync({}) + } else { + //oldMatricola undefined && newMatricola undefined + return + } + } else { + //oldMatricola undefined && newMatricola set + if (this._calendarPolimiSync?.matricola == null) { + //sync + void this._syncPolimiEvents() + + //sync events with new matricola + } else if (this._calendarPolimiSync?.matricola !== this._matricola) { + //oldMatricola set && newMatricola set but they are different => clean and sync + this._cleanCalendarEventsFromPolimiEvents({ calledBeforeSync: true }) + + void this._syncPolimiEvents() + } else { + //oldMatricola set && newMatricola set && they are equal => sync if last sync is older than 7 days + if (this._calendarPolimiSync.lastSync) { + const lastSyncDate = new Date(this._calendarPolimiSync.lastSync) + + const now = new Date() + + const diff = now.getTime() - lastSyncDate.getTime() + + const days = diff / (1000 * 3600 * 24) + + if (days > 7) { + void this._syncPolimiEvents() + } + } else { + void this._syncPolimiEvents() + } + } + } + } + + private _cleanCalendarEventsFromPolimiEvents = ({ + calledBeforeSync = false, + }) => { + const newArray = this._calendarEvents.filter(event => !event.isPolimiEvent) + + const hasChanged = newArray.length !== this._calendarEvents.length + + this._calendarEvents = newArray + + // dont write events and apply markers if called before sync + if (!calledBeforeSync && hasChanged) { + void this._writeEvents(this._calendarEvents) + + void this._applyMarkers() + + this.emit("calendarEventsChanged") + } + } + + private _syncPolimiEvents = async () => { + if (this._matricola == null) { + return + } + + const events: Event[] = await api.events.getEvents({ + matricola: this._matricola, + startDate: new Date().toISOString().substring(0, 10), + nEvents: 20, + }) + + events.forEach(event => { + if ( + !this._calendarEvents.find( + calendarEvent => calendarEvent.id === event.event_id.toString() + ) + ) { + this._calendarEvents.push({ + id: event.event_id.toString(), + end: event.date_end, + start: event.date_start, + title: event.title.it, + titleEn: event.title.en, + status: CalendarEventStatus.INITIAL, + isPolimiEvent: true, + polimiEventFields: event, + }) + } + }) + + void this._writeEvents(this._calendarEvents) + + this.emit("calendarEventsChanged") + + void this._applyMarkers() + + //write latest sync date + this._calendarPolimiSync = { + matricola: this._matricola, + lastSync: new Date().toISOString(), + } + void this._writeCalendarPolimiSync(this._calendarPolimiSync) + } + + private _readCaledarPolimiSync = async () => { + try { + const calendarPolimiSyncJSON = await FileSystem.readAsStringAsync( + FileSystem.documentDirectory + "calendar_polimi_sync.json" + ) + const calendarPolimiSync = JSON.parse( + calendarPolimiSyncJSON + ) as CalendarPolimiSyncObj + this._calendarPolimiSync = calendarPolimiSync + } catch (err) { + console.log(err) + console.log("Error reading calendarPolimiSync") + this._calendarPolimiSync = undefined + } + } + + private _writeCalendarPolimiSync = async ( + calendarPolimiSync: CalendarPolimiSyncObj + ): Promise => { + const calendarPolimiSyncJSON = JSON.stringify(calendarPolimiSync) + try { + this._calendarPolimiSync = calendarPolimiSync + await FileSystem.writeAsStringAsync( + FileSystem.documentDirectory + "calendar_polimi_sync.json", + calendarPolimiSyncJSON + ) + + return true + } catch (err) { + console.log(err) + console.log("Error storing calendarPolimiSync ") + return false + } + } + private _readEvents = async () => { try { const calendarEventsJSON = await FileSystem.readAsStringAsync( @@ -217,7 +407,10 @@ export class CalendarSingletonWrapper extends EventEmitter { private _applyPeriods() { this._markedDatesPeriods = {} - this._calendarPeriods?.forEach(period => { + + const periods = this._hidePeriods ? [] : this._calendarPeriods + + periods?.forEach(period => { if (!period.shown) return period.dates.forEach(date => { const periodTmp: MarkedDates = {} @@ -280,6 +473,7 @@ export class CalendarSingletonWrapper extends EventEmitter { } } + // create a new array to trigger the change this._calendarPeriods = periods.slice() this.emit("calendarPeriodsChanged") @@ -287,6 +481,16 @@ export class CalendarSingletonWrapper extends EventEmitter { this._applyPeriods() } + public hideAllPerdiods = () => { + this._hidePeriods = true + this._applyPeriods() + } + + public showSwitchedOnPeriods = () => { + this._hidePeriods = false + this._applyPeriods() + } + public addEvent = (event: CalendarEvent) => { this._calendarEvents.push(event) @@ -422,7 +626,8 @@ export const dayComponentCustom: ComponentType< date, onPress, onLongPress, - /* state, + state, + /* accessibilityLabel, testID, */ children, @@ -469,7 +674,7 @@ export const dayComponentCustom: ComponentType< let startAngle let sweepAngle - if (marking?.startingDay && marking.endingDay) { + if ((marking?.startingDay && marking.endingDay) || state == "today") { startAngle = 90 sweepAngle = 360 } else if (marking?.startingDay) { @@ -492,7 +697,7 @@ export const dayComponentCustom: ComponentType< ) return path - }, [marking]) + }, [marking, state]) return ( {String(children)} From adfb3a1b9bfd2c18e59f7ea5046a4115a296dc49 Mon Sep 17 00:00:00 2001 From: DiegoZaff Date: Sun, 27 Aug 2023 00:48:35 +0200 Subject: [PATCH 08/31] calendar event details and notes --- .../Calendar/CalendarEventDetails.tsx | 188 ++++++++++++++++++ .../Calendar/CalendarMonthlyEvents.tsx | 104 +++++----- src/locales/i18n.ts | 14 +- src/locales/jsons/en/calendar.json | 4 + src/locales/jsons/it/calendar.json | 4 + src/pages/Calendar.tsx | 39 +++- src/utils/calendar.tsx | 40 ++++ 7 files changed, 341 insertions(+), 52 deletions(-) create mode 100644 src/components/Calendar/CalendarEventDetails.tsx create mode 100644 src/locales/jsons/en/calendar.json create mode 100644 src/locales/jsons/it/calendar.json diff --git a/src/components/Calendar/CalendarEventDetails.tsx b/src/components/Calendar/CalendarEventDetails.tsx new file mode 100644 index 00000000..bf7d7d4f --- /dev/null +++ b/src/components/Calendar/CalendarEventDetails.tsx @@ -0,0 +1,188 @@ +import { FC, useEffect, useRef } from "react" +import { View, ScrollView, StyleSheet, TextInput, Keyboard } from "react-native" +import { + CalendarEvent, + emoticons, + formatDateCalendarDetails, + formatHoursFromDate, +} from "utils/calendar" +import { Text } from "components/Text" +import { usePalette } from "utils/colors" +import { Icon } from "components/Icon" +import { useTranslation } from "react-i18next" + +interface CalendarEventDetailsProps { + event?: CalendarEvent + updateNotes: (id: string, notes: string) => void +} + +export const CalendarEventDetails: FC = props => { + const { event } = props + + const { homeBackground } = usePalette() + + //i18n + const { t } = useTranslation("calendar") + + const inputText = useRef(null) + + const timer = useRef(null) + + useEffect(() => { + const keyboardDidHideListener = Keyboard.addListener( + "keyboardDidHide", + () => { + inputText.current?.blur() + } + ) + + return () => { + keyboardDidHideListener.remove() + } + }, []) + + return ( + + + {event?.mood && ( + + )} + + {event?.title} + + + + + {formatDateCalendarDetails(event)} + + + + {formatHoursFromDate(event?.start)} + + {event?.isPolimiEvent && event.polimiEventFields?.room?.acronym_dn ? ( + <> + + + {event.polimiEventFields.room.acronym_dn} + + + ) : ( + + )} + + {event?.reminder ?? + (true && ( + + + {t("reminder")} + + + {formatHoursFromDate(new Date().toISOString())} + + + ))} + + + {t("notes")} + + + { + if (timer.current) { + clearTimeout(timer.current) + } + timer.current = setTimeout(() => { + props.updateNotes(event?.id ?? "", text) + }, 1000) + }} + ref={inputText} + defaultValue={event?.notes} + multiline={true} + maxLength={200} + numberOfLines={4} + placeholderTextColor={homeBackground} + placeholder="aggiungi delle note" + /> + {/* */} + + ) +} + +//stylesheet +const styles = StyleSheet.create({ + text162700: { + fontSize: 16, + fontWeight: "700", + }, + text12w400: { fontSize: 12, fontWeight: "400" }, + text20w700: { fontSize: 20, fontWeight: "700" }, + text20w900: { + fontSize: 20, + fontWeight: "900", + }, + text16w700: { + fontSize: 16, + fontWeight: "700", + }, + colon: { alignSelf: "center", marginHorizontal: 4, fontSize: 14 }, +}) diff --git a/src/components/Calendar/CalendarMonthlyEvents.tsx b/src/components/Calendar/CalendarMonthlyEvents.tsx index a4c4264e..d225bdaf 100644 --- a/src/components/Calendar/CalendarMonthlyEvents.tsx +++ b/src/components/Calendar/CalendarMonthlyEvents.tsx @@ -17,6 +17,7 @@ interface CalendarMonthlyEventsProps { year: number lan: string onDeleteEvent: (id: string) => void + onSelectedEvent: (event: CalendarEvent) => void } export const CalendarMonthlyEvents: FC = props => { @@ -63,73 +64,78 @@ export const CalendarMonthlyEvents: FC = props => { {events.map(event => { return ( - props.onSelectedEvent(event)} > - - - - + + + + + + + {event.title} + + {(event.isPolimiEvent == undefined || + event.isPolimiEvent == false) && ( + props.onDeleteEvent(event.id)}> + + + )} + + + {formatCalendarEventDay(event, lan)} + + + - {event.title} + {event.notes ?? "aggiungi una nota"} - {(event.isPolimiEvent == undefined || - event.isPolimiEvent == false) && ( - props.onDeleteEvent(event.id)}> - - - )} - - - {formatCalendarEventDay(event, lan)} - - - - Note - - + ) })} diff --git a/src/locales/i18n.ts b/src/locales/i18n.ts index a9a8eeb3..8a6f8cbd 100644 --- a/src/locales/i18n.ts +++ b/src/locales/i18n.ts @@ -12,6 +12,9 @@ import settingsIT from "./jsons/it/settings.json" import settingsEN from "./jsons/en/settings.json" import notificationsIT from "./jsons/it/notifications.json" import notificationsEN from "./jsons/en/notifications.json" +import calendarIT from "./jsons/it/calendar.json" +import calendarEN from "./jsons/en/calendar.json" + import { getLocales } from "expo-localization" async function initializeI18n() { @@ -23,6 +26,7 @@ async function initializeI18n() { freeClass: FreeClassIT, settings: settingsIT, notifications: notificationsIT, + calendar: calendarIT, }, en: { common: commonEN, @@ -30,13 +34,21 @@ async function initializeI18n() { freeClass: FreeClassEN, settings: settingsEN, notifications: notificationsEN, + calendar: calendarEN, }, }, lng: getLocales()[0].languageCode, compatibilityJSON: "v3", fallbackLng: "en", defaultNS: "common", - ns: ["common", "home", "freeClass", "settings", "notifications"], + ns: [ + "common", + "home", + "freeClass", + "settings", + "notifications", + "calendar", + ], interpolation: { escapeValue: false, }, diff --git a/src/locales/jsons/en/calendar.json b/src/locales/jsons/en/calendar.json new file mode 100644 index 00000000..e4c796df --- /dev/null +++ b/src/locales/jsons/en/calendar.json @@ -0,0 +1,4 @@ +{ + "reminder": "Reminder", + "notes": "Notes" +} diff --git a/src/locales/jsons/it/calendar.json b/src/locales/jsons/it/calendar.json new file mode 100644 index 00000000..c7b189ef --- /dev/null +++ b/src/locales/jsons/it/calendar.json @@ -0,0 +1,4 @@ +{ + "reminder": "Promemoria", + "notes": "Note" +} diff --git a/src/pages/Calendar.tsx b/src/pages/Calendar.tsx index 3db0c567..fbc8b6d4 100644 --- a/src/pages/Calendar.tsx +++ b/src/pages/Calendar.tsx @@ -1,4 +1,4 @@ -import { MainStackScreen } from "navigation/NavigationTypes" +import { MainStackScreen, useNavigation } from "navigation/NavigationTypes" /* import { useTranslation } from "react-i18next" */ import { BoxShadowView } from "components/BoxShadow" import { NavBar } from "components/NavBar" @@ -28,6 +28,7 @@ import { CalendarMonthlyEvents } from "components/Calendar/CalendarMonthlyEvents import { useCurrentLanguage } from "utils/articles" import { CalendarAddEvent } from "components/Calendar/CalendarAddEvent" import { LoginContext } from "contexts/login" +import { CalendarEventDetails } from "components/Calendar/CalendarEventDetails" export const CalendarPage: MainStackScreen<"Calendar"> = () => { const { homeBackground, background, dotColor } = usePalette() @@ -62,6 +63,12 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { CalendarEvent[] >([]) + const [selectedEvent, setSelectedEvent] = useState( + undefined + ) + + const navigation = useNavigation() + useEffect(() => { console.log(selectedDay) }, [selectedDay]) @@ -288,6 +295,10 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { onDeleteEvent={(id: string) => { calendarObj.current?.removeEvent(id) }} + onSelectedEvent={(event: CalendarEvent) => { + setSelectedEvent(event) + setBottomSheetStatus(CalendarBottomSheetStatus.EVENT_DETAILS) + }} /> )} {bottomSheetStatus === CalendarBottomSheetStatus.ADD_EVENT && ( @@ -299,8 +310,32 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { date={selectedDay} /> )} + {bottomSheetStatus == CalendarBottomSheetStatus.EVENT_DETAILS && ( + { + calendarObj.current?.updateNotes(id, notes) + }} + /> + )} - + { + if (bottomSheetStatus === CalendarBottomSheetStatus.EVENT_DETAILS) { + setBottomSheetStatus(CalendarBottomSheetStatus.MONTHLY_EVENTS) + } else if ( + bottomSheetStatus === CalendarBottomSheetStatus.MONTHLY_EVENTS + ) { + setBottomSheetStatus(CalendarBottomSheetStatus.PERIODS) + } else if ( + bottomSheetStatus === CalendarBottomSheetStatus.ADD_EVENT + ) { + setBottomSheetStatus(CalendarBottomSheetStatus.MONTHLY_EVENTS) + } else { + navigation.goBack() + } + }} + /> ) } diff --git a/src/utils/calendar.tsx b/src/utils/calendar.tsx index ff3cb9ce..0bd6b570 100644 --- a/src/utils/calendar.tsx +++ b/src/utils/calendar.tsx @@ -77,6 +77,8 @@ export interface CalendarEvent { titleEn?: string polimiEventFields?: Partial + + notes?: string } export enum CalendarEventStatus { @@ -189,6 +191,18 @@ export class CalendarSingletonWrapper extends EventEmitter { this._checkNeedSyncingPolimiEvents() } + public updateNotes = (id: string, notes: string) => { + const index = this._calendarEvents.findIndex(event => event.id === id) + + if (index === -1) return + + this._calendarEvents[index].notes = notes + + void this._writeEvents(this._calendarEvents) + + this.emit("calendarEventsChanged") + } + public changeMatricola = (matricola?: string) => { this._matricola = matricola @@ -874,6 +888,32 @@ export const formatCalendarEventDay = (event: CalendarEvent, lan: string) => { .padStart(2, "0")} | ${dayOfTheWeek}` } +export const formatDateCalendarDetails = (event?: CalendarEvent) => { + if (!event) return "" + const date = new Date(event.start) + + const day = date.getDate() + + const month = date.getMonth() + 1 + + const year = date.getFullYear() + + return `${day}/${month}/${year}` +} + +export const formatHoursFromDate = (dateString?: string) => { + if (!dateString) return "" + const date = new Date(dateString) + + const hour = date.getHours() + + const minutes = date.getMinutes() + + return `${hour.toString().padStart(2, "0")}:${minutes + .toString() + .padStart(2, "0")}` +} + export type ValidEmoticonName = | "boom" | "broken_heart" From de16c25e3870f7bc38d83d5b885db48c56eb0bbf Mon Sep 17 00:00:00 2001 From: DiegoZaff Date: Sat, 16 Sep 2023 12:58:40 +0200 Subject: [PATCH 09/31] Daily Events Progress Flow --- .../Calendar/CalendarDailyEvents.tsx | 209 ++++++++++++++++++ .../Calendar/CalendarEventDetails.tsx | 5 +- src/components/Calendar/DottedLine.tsx | 41 ++++ src/pages/Calendar.tsx | 44 +++- src/utils/calendar.tsx | 52 +++++ 5 files changed, 347 insertions(+), 4 deletions(-) create mode 100644 src/components/Calendar/CalendarDailyEvents.tsx create mode 100644 src/components/Calendar/DottedLine.tsx diff --git a/src/components/Calendar/CalendarDailyEvents.tsx b/src/components/Calendar/CalendarDailyEvents.tsx new file mode 100644 index 00000000..60a7dfed --- /dev/null +++ b/src/components/Calendar/CalendarDailyEvents.tsx @@ -0,0 +1,209 @@ +import { FC } from "react" +import { View, ScrollView, StyleSheet, Pressable } from "react-native" +import { + CalendarEvent, + CalendarEventStatus, + formatHoursFromDate, + getBackColorFromEventStatus, + getSourceEmoticon, + getTextFromEventStatus, + shiftedEventStatus, +} from "utils/calendar" +import { Text } from "components/Text" +import { usePalette } from "utils/colors" +import { Icon } from "components/Icon" + +import tickSvg from "assets/freeClassrooms/tick.svg" +import { DottedLine } from "./DottedLine" +import { CalendarButton } from "./Button" + +interface CalendarDailyEventsProps { + events: CalendarEvent[] + month: string + year: number + day: number + lan: string + onChangeStatusEvent: (id: string, status: CalendarEventStatus) => void + goToAddEvent: () => void +} + +export const CalendarDailyEvents: FC = props => { + const { events, month, year, lan, day } = props + + const { homeBackground, palette } = usePalette() + + return ( + + + + {day + " " + month + " " + year} + + props?.goToAddEvent()} + style={{ width: 100, height: 32 }} + > + Aggiungi + + + + {events.map((event, index) => { + return ( + + props.onChangeStatusEvent( + event.id, + shiftedEventStatus(event.status) + ) + } + > + + + + + + + + + + {event.title} + + + {formatHoursFromDate(event.start)} + {event.polimiEventFields?.room?.acronym_dn + ? ` | ${event.polimiEventFields?.room?.acronym_dn}` + : ""} + + + + + + {getTextFromEventStatus(event.status, lan)} + + + + {event.status == CalendarEventStatus.INITIAL ? ( + + ) : event.status === CalendarEventStatus.PROGRESS ? ( + + ) : ( + + + + )} + + + + {index != events.length - 1 ? ( + + ) : ( + + )} + + + + ) + })} + + ) +} + +//stylesheet +const styles = StyleSheet.create({ + mediumSizeText: { + fontSize: 16, + fontWeight: "700", + }, + smallSizeText: { fontSize: 12, fontWeight: "400" }, + monthTitle: { + fontSize: 20, + fontWeight: "900", + }, +}) diff --git a/src/components/Calendar/CalendarEventDetails.tsx b/src/components/Calendar/CalendarEventDetails.tsx index bf7d7d4f..e5f36b3b 100644 --- a/src/components/Calendar/CalendarEventDetails.tsx +++ b/src/components/Calendar/CalendarEventDetails.tsx @@ -57,7 +57,10 @@ export const CalendarEventDetails: FC = props => { /> )} {event?.title} diff --git a/src/components/Calendar/DottedLine.tsx b/src/components/Calendar/DottedLine.tsx new file mode 100644 index 00000000..06d9a460 --- /dev/null +++ b/src/components/Calendar/DottedLine.tsx @@ -0,0 +1,41 @@ +import { FC } from "react" +import { View } from "react-native" + +export const DottedLine: FC = () => { + return ( + <> + + + + + + ) +} diff --git a/src/pages/Calendar.tsx b/src/pages/Calendar.tsx index fbc8b6d4..85030382 100644 --- a/src/pages/Calendar.tsx +++ b/src/pages/Calendar.tsx @@ -16,6 +16,7 @@ import { CalendarEvent, monthsIt, monthsEn, + CalendarEventStatus, } from "utils/calendar" import { MarkedDates } from "react-native-calendars/src/types" import { Text } from "components/Text" @@ -29,6 +30,7 @@ import { useCurrentLanguage } from "utils/articles" import { CalendarAddEvent } from "components/Calendar/CalendarAddEvent" import { LoginContext } from "contexts/login" import { CalendarEventDetails } from "components/Calendar/CalendarEventDetails" +import { CalendarDailyEvents } from "components/Calendar/CalendarDailyEvents" export const CalendarPage: MainStackScreen<"Calendar"> = () => { const { homeBackground, background, dotColor } = usePalette() @@ -63,15 +65,19 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { CalendarEvent[] >([]) + const [calendarEventsDaily, setCalendarEventsDaily] = useState< + CalendarEvent[] + >([]) + const [selectedEvent, setSelectedEvent] = useState( undefined ) const navigation = useNavigation() - useEffect(() => { + /* useEffect(() => { console.log(selectedDay) - }, [selectedDay]) + }, [selectedDay]) */ const calendarObj = useRef() @@ -132,6 +138,19 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { } }, [calendarEvents, month, year]) + useEffect(() => { + if (calendarEvents.length > 0) { + const filteredEvents = calendarEvents.filter( + event => + new Date(event.start).getDate() === new Date(selectedDay).getDate() && + new Date(event.start).getMonth() === month && + new Date(event.start).getFullYear() === year + ) + + setCalendarEventsDaily(filteredEvents) + } + }, [calendarEvents, selectedDay]) + // hide or show peridos based on bottom sheet status useEffect(() => { if (bottomSheetStatus !== CalendarBottomSheetStatus.PERIODS) { @@ -228,7 +247,7 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { setSelectedDay(date.toISOString()) - setBottomSheetStatus(CalendarBottomSheetStatus.ADD_EVENT) + setBottomSheetStatus(CalendarBottomSheetStatus.DAILY_EVENTS) }} style={{ marginTop: 150, @@ -310,6 +329,21 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { date={selectedDay} /> )} + {bottomSheetStatus == CalendarBottomSheetStatus.DAILY_EVENTS && ( + { + calendarObj.current?.changeEventStatus(id, status) + }} + goToAddEvent={() => { + setBottomSheetStatus(CalendarBottomSheetStatus.ADD_EVENT) + }} + /> + )} {bottomSheetStatus == CalendarBottomSheetStatus.EVENT_DETAILS && ( = () => { setBottomSheetStatus(CalendarBottomSheetStatus.PERIODS) } else if ( bottomSheetStatus === CalendarBottomSheetStatus.ADD_EVENT + ) { + setBottomSheetStatus(CalendarBottomSheetStatus.DAILY_EVENTS) + } else if ( + bottomSheetStatus === CalendarBottomSheetStatus.DAILY_EVENTS ) { setBottomSheetStatus(CalendarBottomSheetStatus.MONTHLY_EVENTS) } else { diff --git a/src/utils/calendar.tsx b/src/utils/calendar.tsx index 0bd6b570..e4238d84 100644 --- a/src/utils/calendar.tsx +++ b/src/utils/calendar.tsx @@ -215,6 +215,7 @@ export class CalendarSingletonWrapper extends EventEmitter { if (this._calendarPolimiSync?.matricola) { this._cleanCalendarEventsFromPolimiEvents({ calledBeforeSync: false }) + //update sync obj this._calendarPolimiSync = {} void this._writeCalendarPolimiSync({}) } else { @@ -555,6 +556,17 @@ export class CalendarSingletonWrapper extends EventEmitter { void this._removeMarkers(removedElement.start.substring(0, 10)) } + + public changeEventStatus = (id: string, status: CalendarEventStatus) => { + const index = this._calendarEvents.findIndex(event => event.id === id) + + if (index === -1) return + + this._calendarEvents[index].status = status + + this.emit("calendarEventsChanged") + void this._writeEvents(this._calendarEvents) + } } const getNextDayFormattedDate = ( @@ -1041,3 +1053,43 @@ export const get1HourBeforeAfterSameDay = ( return newDate } + +export const getBackColorFromEventStatus = ( + status: CalendarEventStatus +): string => { + switch (status) { + case CalendarEventStatus.INITIAL: + return "#F2F2F2" + case CalendarEventStatus.PROGRESS: + return "#F29999" + case CalendarEventStatus.COMPLETED: + return palette.primary + } +} + +export const getTextFromEventStatus = ( + status: CalendarEventStatus, + lan: string +): string => { + switch (status) { + case CalendarEventStatus.INITIAL: + return lan === "it" ? "Prossimo" : "Next" + case CalendarEventStatus.PROGRESS: + return lan === "it" ? "In corso" : "In progress" + case CalendarEventStatus.COMPLETED: + return lan === "it" ? "Completato" : "Completed" + } +} + +export const shiftedEventStatus = ( + status: CalendarEventStatus +): CalendarEventStatus => { + switch (status) { + case CalendarEventStatus.INITIAL: + return CalendarEventStatus.PROGRESS + case CalendarEventStatus.PROGRESS: + return CalendarEventStatus.COMPLETED + case CalendarEventStatus.COMPLETED: + return CalendarEventStatus.INITIAL + } +} From 9969c01cb5e5151ead6f28297aaa3c25993388bb Mon Sep 17 00:00:00 2001 From: DiegoZaff Date: Sat, 16 Sep 2023 16:02:14 +0200 Subject: [PATCH 10/31] notification reminder in calendar events --- .../Calendar/CalendarEventDetails.tsx | 47 +++++++++--------- src/notifications/NotificationCenter.ts | 48 +++++++++++++++++-- src/notifications/NotificationTypes.ts | 6 +++ src/utils/calendar.tsx | 9 ++++ 4 files changed, 82 insertions(+), 28 deletions(-) diff --git a/src/components/Calendar/CalendarEventDetails.tsx b/src/components/Calendar/CalendarEventDetails.tsx index e5f36b3b..294c3c0b 100644 --- a/src/components/Calendar/CalendarEventDetails.tsx +++ b/src/components/Calendar/CalendarEventDetails.tsx @@ -105,31 +105,30 @@ export const CalendarEventDetails: FC = props => { )} - {event?.reminder ?? - (true && ( - + + {t("reminder")} + + - - {t("reminder")} - - - {formatHoursFromDate(new Date().toISOString())} - - - ))} + {formatHoursFromDate(new Date().toISOString())} + + + )} { + if (event.reminder === undefined) return + + const notificationContent: NotificationCustomContentInput = { + title: event.title, + data: { + eventId: event.id, + content: "Notifica dal calendario", + object: event.title, + sender: "Centro Notifiche", + storeOnSchedule: false, + dontStore: true, + }, + } + + const notificationTrigger = { + date: new Date(event.reminder), + channelId: "default", + } + + await this.sendScheduledNotification( + notificationContent, + notificationTrigger + ) + } } diff --git a/src/notifications/NotificationTypes.ts b/src/notifications/NotificationTypes.ts index f323e92b..832dc93c 100644 --- a/src/notifications/NotificationTypes.ts +++ b/src/notifications/NotificationTypes.ts @@ -61,6 +61,12 @@ export interface NotificationCustomContentInput * if it is false, it is stored when it is received. */ storeOnSchedule?: boolean + + /* + for calendar Events, we don't want to store the notification in the storage + */ + dontStore?: boolean + /** * enable deeplinking to NotificationDetails */ diff --git a/src/utils/calendar.tsx b/src/utils/calendar.tsx index e4238d84..c0f6686b 100644 --- a/src/utils/calendar.tsx +++ b/src/utils/calendar.tsx @@ -28,6 +28,7 @@ import smileSvg from "assets/calendar/emoticons/smile.svg" import starEyesSvg from "assets/calendar/emoticons/star_eyes.svg" import { api } from "api" import { Event } from "api/collections/event" +import { NotificationCenter } from "notifications/NotificationCenter" export const purpleBerry = "rgba(98, 96, 166, 1)" @@ -170,6 +171,8 @@ export class CalendarSingletonWrapper extends EventEmitter { //matricola and last sync date with polimi events private _calendarPolimiSync?: CalendarPolimiSyncObj + private _notificationCentre = NotificationCenter.getInstance() + public constructor({ hidePeriods = false, matricola, @@ -514,6 +517,12 @@ export class CalendarSingletonWrapper extends EventEmitter { void this._writeEvents(this._calendarEvents) void this._applyMarkers() + + if (event.reminder) { + void this._notificationCentre.scheduledNotificationFromCalendarEvent( + event + ) + } } private _applyMarkers = () => { From 446eef1a40ed805ba076fc6f30721c282cdf1405 Mon Sep 17 00:00:00 2001 From: DiegoZaff Date: Thu, 21 Sep 2023 10:38:25 +0200 Subject: [PATCH 11/31] bug fix --- .../Calendar/CalendarDailyEvents.tsx | 19 +++++++++++++++---- src/pages/Calendar.tsx | 4 +--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/components/Calendar/CalendarDailyEvents.tsx b/src/components/Calendar/CalendarDailyEvents.tsx index 60a7dfed..bd0fdc7e 100644 --- a/src/components/Calendar/CalendarDailyEvents.tsx +++ b/src/components/Calendar/CalendarDailyEvents.tsx @@ -7,6 +7,8 @@ import { getBackColorFromEventStatus, getSourceEmoticon, getTextFromEventStatus, + monthsEn, + monthsIt, shiftedEventStatus, } from "utils/calendar" import { Text } from "components/Text" @@ -19,16 +21,25 @@ import { CalendarButton } from "./Button" interface CalendarDailyEventsProps { events: CalendarEvent[] - month: string - year: number - day: number + + dayString: string lan: string onChangeStatusEvent: (id: string, status: CalendarEventStatus) => void goToAddEvent: () => void } export const CalendarDailyEvents: FC = props => { - const { events, month, year, lan, day } = props + const { events, lan, dayString } = props + + const date = new Date(dayString) + + const day = date.getDate() + + const monthNumber = date.getMonth() + + const month = lan === "it" ? monthsIt[monthNumber] : monthsEn[monthNumber] + + const year = date.getFullYear() const { homeBackground, palette } = usePalette() diff --git a/src/pages/Calendar.tsx b/src/pages/Calendar.tsx index 85030382..0315f875 100644 --- a/src/pages/Calendar.tsx +++ b/src/pages/Calendar.tsx @@ -332,10 +332,8 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { {bottomSheetStatus == CalendarBottomSheetStatus.DAILY_EVENTS && ( { calendarObj.current?.changeEventStatus(id, status) }} From 30252a1070d2c34d58b2d800b9e64075ca43f31c Mon Sep 17 00:00:00 2001 From: DiegoZaff Date: Sat, 30 Sep 2023 20:58:12 +0200 Subject: [PATCH 12/31] dark mode and a months page --- src/components/Calendar/Button.tsx | 4 +- src/components/Calendar/CalendarAddEvent.tsx | 39 +- .../Calendar/CalendarDailyEvents.tsx | 32 +- .../Calendar/CalendarEventDetails.tsx | 46 +- .../Calendar/CalendarMonthlyEvents.tsx | 35 +- .../Calendar/CalendarPeriodsSwitches.tsx | 18 +- src/components/Calendar/SingleMonth.tsx | 101 +++++ .../FreeClass/DateTimePicker/DateTimeBox.tsx | 3 +- src/pages/Calendar.tsx | 398 +++++++++++------- src/utils/calendar.tsx | 177 +++++++- 10 files changed, 649 insertions(+), 204 deletions(-) create mode 100644 src/components/Calendar/SingleMonth.tsx diff --git a/src/components/Calendar/Button.tsx b/src/components/Calendar/Button.tsx index f2906c0a..b48b7272 100644 --- a/src/components/Calendar/Button.tsx +++ b/src/components/Calendar/Button.tsx @@ -5,7 +5,7 @@ import { usePalette } from "utils/colors" interface CalendarButton { children: React.ReactNode onPress?: () => void - + backgroundColor?: string style?: ViewStyle } @@ -16,7 +16,7 @@ export const CalendarButton: FC = props => { = props => { setEndDate(get1HourBeforeAfterSameDay(new Date(props.date), true)) }, [props.date]) - // ! WIP return ( = props => { > Nuovo Evento { if ( title.length > 0 && @@ -168,6 +171,7 @@ export const CalendarAddEvent: FC = props => { Ok { resetNewEvent() @@ -177,24 +181,30 @@ export const CalendarAddEvent: FC = props => { - + {fromatAddEventDate(dateObj, lan)} { setTitle(text) }} ref={inputText} - placeholderTextColor={homeBackground} + placeholderTextColor={isLight ? homeBackground : "#fff"} placeholder="Aggiungi Titolo" /> = props => { = props => { @@ -255,6 +267,7 @@ export const CalendarAddEvent: FC = props => { = props => { - + Imposta Promemoria = props => { : "00" } width={54} + fullOpacity={true} /> = props => { : "00" } width={54} + fullOpacity={true} /> setIsMoodModalShowing(true)} > @@ -328,6 +350,7 @@ export const CalendarAddEvent: FC = props => { { setIsRepeating(!isRepeating) diff --git a/src/components/Calendar/CalendarDailyEvents.tsx b/src/components/Calendar/CalendarDailyEvents.tsx index bd0fdc7e..aed8064a 100644 --- a/src/components/Calendar/CalendarDailyEvents.tsx +++ b/src/components/Calendar/CalendarDailyEvents.tsx @@ -41,7 +41,7 @@ export const CalendarDailyEvents: FC = props => { const year = date.getFullYear() - const { homeBackground, palette } = usePalette() + const { isLight, homeBackground, palette } = usePalette() return ( = props => { {day + " " + month + " " + year} @@ -120,12 +124,18 @@ export const CalendarDailyEvents: FC = props => { > {event.title} {formatHoursFromDate(event.start)} {event.polimiEventFields?.room?.acronym_dn @@ -144,11 +154,17 @@ export const CalendarDailyEvents: FC = props => { alignItems: "center", flexDirection: "row", backgroundColor: getBackColorFromEventStatus( - event.status + event.status, + isLight ), }} > - + {getTextFromEventStatus(event.status, lan)} @@ -159,7 +175,7 @@ export const CalendarDailyEvents: FC = props => { width: 40, height: 40, borderRadius: 20, - backgroundColor: "#F2F2F2", + backgroundColor: isLight ? "#F2F2F2" : "#D7D9E2", }} /> ) : event.status === CalendarEventStatus.PROGRESS ? ( @@ -176,7 +192,7 @@ export const CalendarDailyEvents: FC = props => { diff --git a/src/components/Calendar/CalendarEventDetails.tsx b/src/components/Calendar/CalendarEventDetails.tsx index 294c3c0b..595d17cc 100644 --- a/src/components/Calendar/CalendarEventDetails.tsx +++ b/src/components/Calendar/CalendarEventDetails.tsx @@ -19,7 +19,7 @@ interface CalendarEventDetailsProps { export const CalendarEventDetails: FC = props => { const { event } = props - const { homeBackground } = usePalette() + const { homeBackground, isLight } = usePalette() //i18n const { t } = useTranslation("calendar") @@ -59,7 +59,10 @@ export const CalendarEventDetails: FC = props => { {event?.title} @@ -73,18 +76,28 @@ export const CalendarEventDetails: FC = props => { justifyContent: "space-between", }} > - + {formatDateCalendarDetails(event)} - + {formatHoursFromDate(event?.start)} {event?.isPolimiEvent && event.polimiEventFields?.room?.acronym_dn ? ( @@ -92,12 +105,17 @@ export const CalendarEventDetails: FC = props => { - + {event.polimiEventFields.room.acronym_dn} @@ -114,14 +132,19 @@ export const CalendarEventDetails: FC = props => { justifyContent: "space-between", }} > - + {t("reminder")} @@ -131,7 +154,10 @@ export const CalendarEventDetails: FC = props => { )} {t("notes")} diff --git a/src/components/Calendar/CalendarMonthlyEvents.tsx b/src/components/Calendar/CalendarMonthlyEvents.tsx index d225bdaf..97698d5a 100644 --- a/src/components/Calendar/CalendarMonthlyEvents.tsx +++ b/src/components/Calendar/CalendarMonthlyEvents.tsx @@ -23,7 +23,7 @@ interface CalendarMonthlyEventsProps { export const CalendarMonthlyEvents: FC = props => { const { events, month, year, lan } = props - const { homeBackground, dotColor } = usePalette() + const { homeBackground, dotColor, isLight } = usePalette() return ( = props => { {month + " " + year} @@ -56,7 +56,12 @@ export const CalendarMonthlyEvents: FC = props => { }} /> )} - + {events.length > 0 ? events.length + " eventi in programma" : "Nessun evento in programma"} @@ -72,7 +77,9 @@ export const CalendarMonthlyEvents: FC = props => { style={{ height: 80, width: "100%", - backgroundColor: "rgba(242, 242, 242, 0.4", + backgroundColor: isLight + ? "rgba(242, 242, 242, 0.4" + : "#343A55", borderColor: "rgba(69, 71, 115, 1)", borderWidth: 0.5, borderRadius: 5, @@ -101,7 +108,10 @@ export const CalendarMonthlyEvents: FC = props => { @@ -110,7 +120,11 @@ export const CalendarMonthlyEvents: FC = props => { {(event.isPolimiEvent == undefined || event.isPolimiEvent == false) && ( props.onDeleteEvent(event.id)}> - + )} @@ -118,16 +132,19 @@ export const CalendarMonthlyEvents: FC = props => { {formatCalendarEventDay(event, lan)} - + diff --git a/src/components/Calendar/CalendarPeriodsSwitches.tsx b/src/components/Calendar/CalendarPeriodsSwitches.tsx index c7e13845..b9cbb433 100644 --- a/src/components/Calendar/CalendarPeriodsSwitches.tsx +++ b/src/components/Calendar/CalendarPeriodsSwitches.tsx @@ -17,7 +17,7 @@ export const CalendarPeriodsSwitches: FC< > = props => { const { calendarPeriods, month, year } = props - const { homeBackground } = usePalette() + const { homeBackground, isLight } = usePalette() if (!calendarPeriods) return null @@ -32,7 +32,7 @@ export const CalendarPeriodsSwitches: FC< {month + " " + year} @@ -48,10 +48,20 @@ export const CalendarPeriodsSwitches: FC< }} > - + {period.title} - + {period.subtitle} diff --git a/src/components/Calendar/SingleMonth.tsx b/src/components/Calendar/SingleMonth.tsx new file mode 100644 index 00000000..8eb71408 --- /dev/null +++ b/src/components/Calendar/SingleMonth.tsx @@ -0,0 +1,101 @@ +import { FC } from "react" +import { View, ViewStyle } from "react-native" +import { Calendar } from "react-native-calendars" +import { useCurrentLanguage } from "utils/articles" +import { + monthsIt, + monthsEn, + daysOfWeekLetters, + dayComponentAllMonthPage, +} from "utils/calendar" +import { usePalette } from "utils/colors" +import { Text } from "components/Text" +import { MarkedDates } from "react-native-calendars/src/types" + +interface SingleMonthProps { + month: number + year: number + markedDates: MarkedDates + style?: ViewStyle +} + +export const SingleMonth: FC = props => { + const { palette } = usePalette() + + const lan = useCurrentLanguage() + + return ( + + + + {lan === "it" ? monthsIt[props.month] : monthsEn[props.month]}{" "} + {props.year} + + + {daysOfWeekLetters.map((day, index) => ( + + {day} + + ))} + + + + null} + renderArrow={() => null} + enableSwipeMonths={false} + showSixWeeks={true} + hideDayNames={true} + headerStyle={{ display: "none" }} + markingType="period" + markedDates={props.markedDates} + dayComponent={dayComponentAllMonthPage} + /> + + ) +} diff --git a/src/components/FreeClass/DateTimePicker/DateTimeBox.tsx b/src/components/FreeClass/DateTimePicker/DateTimeBox.tsx index 8870dab7..d7da8008 100644 --- a/src/components/FreeClass/DateTimePicker/DateTimeBox.tsx +++ b/src/components/FreeClass/DateTimePicker/DateTimeBox.tsx @@ -6,6 +6,7 @@ import { usePalette } from "utils/colors" export interface DateTimeBoxProps { value?: string width?: number + fullOpacity?: boolean } /** * custom box which contains a 2 digit number, used @@ -30,7 +31,7 @@ export const DateTimeBox: FC = props => { fontSize: 20, fontWeight: "400", color: isLight ? palette.variant3 : "#fff", - opacity: 0.4, + opacity: props.fullOpacity ? undefined : 0.4, }} > {props.value} diff --git a/src/pages/Calendar.tsx b/src/pages/Calendar.tsx index 0315f875..6a25bc90 100644 --- a/src/pages/Calendar.tsx +++ b/src/pages/Calendar.tsx @@ -6,7 +6,7 @@ import { Pressable, View } from "react-native" import { usePalette } from "utils/colors" import { StyleSheet } from "react-native" import { Calendar } from "react-native-calendars" -import { useContext, useEffect, useRef, useState } from "react" +import { useContext, useEffect, useMemo, useRef, useState } from "react" import { CalendarPeriod, CalendarSingletonWrapper as CalendarManager, @@ -31,9 +31,19 @@ import { CalendarAddEvent } from "components/Calendar/CalendarAddEvent" import { LoginContext } from "contexts/login" import { CalendarEventDetails } from "components/Calendar/CalendarEventDetails" import { CalendarDailyEvents } from "components/Calendar/CalendarDailyEvents" +import { SingleMonth } from "components/Calendar/SingleMonth" +import { ScrollView } from "react-native-gesture-handler" export const CalendarPage: MainStackScreen<"Calendar"> = () => { - const { homeBackground, background, dotColor } = usePalette() + const { homeBackground, background, dotColor, isLight, palette } = + usePalette() + + const [counter, setCounter] = useState(0) + + useEffect(() => { + console.log(counter) + setCounter(counter + 1) + }, [isLight]) // todo : implement translation :( /* const { t } = useTranslation() */ @@ -75,12 +85,62 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { const navigation = useNavigation() - /* useEffect(() => { - console.log(selectedDay) - }, [selectedDay]) */ - const calendarObj = useRef() + // I thought memoizing would improve performance, but it appears to be still very slow!! + const scrollMonths = useMemo(() => { + return ( + + + {[0, 2, 4, 6, 8, 10].map(monthX => { + return ( + + { + setMonth(monthX) + setBottomSheetStatus( + CalendarBottomSheetStatus.MONTHLY_EVENTS + ) + }} + > + + + + { + setMonth(monthX + 1) + setBottomSheetStatus( + CalendarBottomSheetStatus.MONTHLY_EVENTS + ) + }} + > + + + + ) + })} + + + ) + }, [markedDates]) + useEffect(() => { const initCalendar = () => { if (!calendarObj.current) { @@ -89,9 +149,9 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { matricola: matricola, }) calendarObj.current.addListener("markedDatesSet", () => { - if (calendarObj.current?.markedDatesPeriods) { + if (calendarObj.current?.datesMarkedAndPeriods) { console.log("marked dates sets") - setMarkedDates(calendarObj.current?.markedDatesPeriods) + setMarkedDates(calendarObj.current?.datesMarkedAndPeriods) setCalendarPeriods(calendarObj.current?.calendarPeriods) } }) @@ -110,8 +170,8 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { } }) } else { - if (calendarObj.current?.markedDatesPeriods) { - setMarkedDates(calendarObj.current?.markedDatesPeriods) + if (calendarObj.current?.datesMarkedAndPeriods) { + setMarkedDates(calendarObj.current?.datesMarkedAndPeriods) setCalendarPeriods(calendarObj.current?.calendarPeriods) } } @@ -153,7 +213,10 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { // hide or show peridos based on bottom sheet status useEffect(() => { - if (bottomSheetStatus !== CalendarBottomSheetStatus.PERIODS) { + if ( + bottomSheetStatus !== CalendarBottomSheetStatus.PERIODS && + bottomSheetStatus !== CalendarBottomSheetStatus.ALL_MONTHS + ) { if (calendarObj.current?.hidePeriods == false) { calendarObj.current?.hideAllPerdiods() } @@ -193,164 +256,195 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { }} > { - if (bottomSheetStatus === CalendarBottomSheetStatus.PERIODS) { - setBottomSheetStatus(CalendarBottomSheetStatus.MONTHLY_EVENTS) - } else { - setBottomSheetStatus(CalendarBottomSheetStatus.PERIODS) - } - }} + onPress={() => + bottomSheetStatus === CalendarBottomSheetStatus.ALL_MONTHS + ? setBottomSheetStatus(CalendarBottomSheetStatus.PERIODS) + : setBottomSheetStatus(CalendarBottomSheetStatus.ALL_MONTHS) + } > - + { + if (bottomSheetStatus === CalendarBottomSheetStatus.PERIODS) { + setBottomSheetStatus(CalendarBottomSheetStatus.MONTHLY_EVENTS) + } else { + setBottomSheetStatus(CalendarBottomSheetStatus.PERIODS) + } + }} + > + + - - {daysOfWeekLetters.map((day, index) => ( - + - {day} - - ))} - - + {daysOfWeekLetters.map((day, index) => ( + + {day} + + ))} + + + + )} - { - const date = new Date(day.dateString) - const now = new Date() + {bottomSheetStatus != CalendarBottomSheetStatus.ALL_MONTHS && ( + <> + { + const date = new Date(day.dateString) + const now = new Date() - //set hours and minutes of date to now - date.setHours(now.getHours()) - date.setMinutes(now.getMinutes()) + //set hours and minutes of date to now + date.setHours(now.getHours()) + date.setMinutes(now.getMinutes()) - setSelectedDay(date.toISOString()) + setSelectedDay(date.toISOString()) - setBottomSheetStatus(CalendarBottomSheetStatus.DAILY_EVENTS) - }} - style={{ - marginTop: 150, - height: 290, - backgroundColor: homeBackground, - }} - markedDates={{ - ...markedDates, - // eslint-disable-next-line @typescript-eslint/naming-convention - "2023-07-15": { - marked: true, - startingDay: true, - endingDay: true, - color: "orange", - }, - }} - customHeaderTitle={undefined} - hideExtraDays={true} - renderHeader={() => null} - renderArrow={() => null} - enableSwipeMonths={true} - showSixWeeks={true} - hideDayNames={true} - markingType="period" - current={selectedDay} - onMonthChange={month => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - setMonth(month.month - 1) - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access - setYear(month.year) - }} - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - dayComponent={dayComponentCustom} - /> - - {bottomSheetStatus === CalendarBottomSheetStatus.PERIODS && ( - - calendarObj.current?.updatePeriods(title, value) - } - /> - )} - {bottomSheetStatus === CalendarBottomSheetStatus.MONTHLY_EVENTS && ( - { - calendarObj.current?.removeEvent(id) + setBottomSheetStatus(CalendarBottomSheetStatus.DAILY_EVENTS) }} - onSelectedEvent={(event: CalendarEvent) => { - setSelectedEvent(event) - setBottomSheetStatus(CalendarBottomSheetStatus.EVENT_DETAILS) - }} - /> - )} - {bottomSheetStatus === CalendarBottomSheetStatus.ADD_EVENT && ( - { - calendarObj.current?.addEvent(event) - setBottomSheetStatus(CalendarBottomSheetStatus.MONTHLY_EVENTS) + style={{ + marginTop: 150, + height: 290, + backgroundColor: homeBackground, }} - date={selectedDay} - /> - )} - {bottomSheetStatus == CalendarBottomSheetStatus.DAILY_EVENTS && ( - { - calendarObj.current?.changeEventStatus(id, status) + markedDates={{ + ...markedDates, + // eslint-disable-next-line @typescript-eslint/naming-convention + "2023-07-15": { + marked: true, + startingDay: true, + endingDay: true, + color: "orange", + }, }} - goToAddEvent={() => { - setBottomSheetStatus(CalendarBottomSheetStatus.ADD_EVENT) + customHeaderTitle={undefined} + hideExtraDays={true} + renderHeader={() => null} + renderArrow={() => null} + enableSwipeMonths={true} + showSixWeeks={true} + hideDayNames={true} + markingType="period" + current={selectedDay} + onMonthChange={month => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + setMonth(month.month - 1) + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access + setYear(month.year) }} + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + dayComponent={dayComponentCustom} /> - )} - {bottomSheetStatus == CalendarBottomSheetStatus.EVENT_DETAILS && ( - { - calendarObj.current?.updateNotes(id, notes) + - )} - + style={styles.boxShadow} + contentContainerStyle={[ + { backgroundColor: background }, + styles.boxShadowContainer, + ]} + > + {bottomSheetStatus === CalendarBottomSheetStatus.PERIODS && ( + + calendarObj.current?.updatePeriods(title, value) + } + /> + )} + {bottomSheetStatus === CalendarBottomSheetStatus.MONTHLY_EVENTS && ( + { + calendarObj.current?.removeEvent(id) + }} + onSelectedEvent={(event: CalendarEvent) => { + setSelectedEvent(event) + setBottomSheetStatus(CalendarBottomSheetStatus.EVENT_DETAILS) + }} + /> + )} + {bottomSheetStatus === CalendarBottomSheetStatus.ADD_EVENT && ( + { + calendarObj.current?.addEvent(event) + setBottomSheetStatus(CalendarBottomSheetStatus.MONTHLY_EVENTS) + }} + date={selectedDay} + /> + )} + {bottomSheetStatus == CalendarBottomSheetStatus.DAILY_EVENTS && ( + { + calendarObj.current?.changeEventStatus(id, status) + }} + goToAddEvent={() => { + setBottomSheetStatus(CalendarBottomSheetStatus.ADD_EVENT) + }} + /> + )} + {bottomSheetStatus == CalendarBottomSheetStatus.EVENT_DETAILS && ( + { + calendarObj.current?.updateNotes(id, notes) + }} + /> + )} + + + )} + + {bottomSheetStatus == CalendarBottomSheetStatus.ALL_MONTHS && ( + {scrollMonths} + )} + { if (bottomSheetStatus === CalendarBottomSheetStatus.EVENT_DETAILS) { @@ -367,6 +461,10 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { bottomSheetStatus === CalendarBottomSheetStatus.DAILY_EVENTS ) { setBottomSheetStatus(CalendarBottomSheetStatus.MONTHLY_EVENTS) + } else if ( + bottomSheetStatus === CalendarBottomSheetStatus.ALL_MONTHS + ) { + setBottomSheetStatus(CalendarBottomSheetStatus.PERIODS) } else { navigation.goBack() } diff --git a/src/utils/calendar.tsx b/src/utils/calendar.tsx index c0f6686b..e2ecb7ca 100644 --- a/src/utils/calendar.tsx +++ b/src/utils/calendar.tsx @@ -38,6 +38,7 @@ export enum CalendarBottomSheetStatus { DAILY_EVENTS, ADD_EVENT, EVENT_DETAILS, + ALL_MONTHS, } export interface Period { @@ -138,10 +139,12 @@ export declare interface CalendarSingletonWrapper { } export class CalendarSingletonWrapper extends EventEmitter { - private _markedDatesPeriods: MarkedDates = {} + private _datesOnlyPeriods: MarkedDates = {} - public get markedDatesPeriods(): MarkedDates | undefined { - return this._markedDatesPeriods + private _datesMarkedAndPeriods: MarkedDates = {} + + public get datesMarkedAndPeriods(): MarkedDates | undefined { + return this._datesMarkedAndPeriods } private _calendarPeriods?: CalendarPeriod[] @@ -424,7 +427,15 @@ export class CalendarSingletonWrapper extends EventEmitter { } private _applyPeriods() { - this._markedDatesPeriods = {} + //if datesOnlyPeriods has been already calculated + if (Object.keys(this._datesOnlyPeriods).length > 0) { + this._datesMarkedAndPeriods = this._hidePeriods + ? {} + : { ...this._datesOnlyPeriods } + this._applyMarkers() + return + } + this._datesMarkedAndPeriods = {} const periods = this._hidePeriods ? [] : this._calendarPeriods @@ -476,7 +487,16 @@ export class CalendarSingletonWrapper extends EventEmitter { } } - this._markedDatesPeriods = { ...this._markedDatesPeriods, ...periodTmp } + this._datesMarkedAndPeriods = { + ...this._datesMarkedAndPeriods, + ...periodTmp, + } + + //save dates with periods for later use + this._datesOnlyPeriods = { + ...this._datesMarkedAndPeriods, + ...periodTmp, + } }) }) this._applyMarkers() @@ -529,8 +549,8 @@ export class CalendarSingletonWrapper extends EventEmitter { for (let i = 0; i < this._calendarEvents.length; i++) { const dateString = this._calendarEvents[i].start.substring(0, 10) - this._markedDatesPeriods[dateString] = { - ...this._markedDatesPeriods[dateString], + this._datesMarkedAndPeriods[dateString] = { + ...this._datesMarkedAndPeriods[dateString], marked: true, } } @@ -544,8 +564,8 @@ export class CalendarSingletonWrapper extends EventEmitter { ) if (isAtLeastOneEvent) return - this._markedDatesPeriods[dateString] = { - ...this._markedDatesPeriods[dateString], + this._datesMarkedAndPeriods[dateString] = { + ...this._datesMarkedAndPeriods[dateString], marked: false, } @@ -649,6 +669,7 @@ export const monthsAcronymsEn = [ ] const FILLER_HEIGHT = 26 +const FILLER_HEIGHT_ALL_MONTHS = 22 export const dayComponentCustom: ComponentType< DayProps & { @@ -824,6 +845,137 @@ export const dayComponentCustom: ComponentType< ) } +export const dayComponentAllMonthPage: ComponentType< + DayProps & { + date?: DateData | undefined + } +> = props => { + const { marking, state, children } = props + + const fillerStyles = useMemo(() => { + const leftFillerStyle: ViewStyle = { flex: 1 } + const rightFillerStyle: ViewStyle = { flex: 1 } + let globalfiller: ViewStyle = {} + + const start = marking?.startingDay + const end = marking?.endingDay + + if (start && !end) { + rightFillerStyle.borderBottomColor = marking?.color + rightFillerStyle.borderBottomWidth = 2 + rightFillerStyle.borderTopColor = marking?.color + rightFillerStyle.borderTopWidth = 2 + } else if (end && !start) { + leftFillerStyle.borderBottomColor = marking?.color + leftFillerStyle.borderBottomWidth = 2 + leftFillerStyle.borderTopColor = marking?.color + leftFillerStyle.borderTopWidth = 2 + } else if (marking?.color && !start && !end) { + globalfiller = { + borderBottomColor: marking?.color, + borderBottomWidth: 2, + borderTopColor: marking?.color, + borderTopWidth: 2, + } + } + return { leftFillerStyle, rightFillerStyle, globalfiller } + }, [marking]) + + const path = useMemo(() => { + let startAngle + let sweepAngle + + if (marking?.startingDay && marking.endingDay) { + startAngle = 90 + sweepAngle = 360 + } else if (marking?.startingDay) { + startAngle = 90 + sweepAngle = 180 + } else if (marking?.endingDay) { + startAngle = 270 + sweepAngle = 180 + } else { + return undefined + } + + const path = Skia.Path.Make() + path.moveTo(19, 1) + //this looks kinda random + path.addArc( + { height: FILLER_HEIGHT_ALL_MONTHS - 2, width: 19, y: 1, x: 4 }, + startAngle, + sweepAngle + ) + + return path + }, [marking, state]) + + return ( + + + + + + + {path && ( + + + + )} + + + {String(children)} + + + + ) +} + const dateToDateData = ( date: (string & DateData) | undefined ): DateData | undefined => { @@ -1064,15 +1216,16 @@ export const get1HourBeforeAfterSameDay = ( } export const getBackColorFromEventStatus = ( - status: CalendarEventStatus + status: CalendarEventStatus, + isLight: boolean ): string => { switch (status) { case CalendarEventStatus.INITIAL: - return "#F2F2F2" + return isLight ? "#F2F2F2" : "#D7D9E2" case CalendarEventStatus.PROGRESS: return "#F29999" case CalendarEventStatus.COMPLETED: - return palette.primary + return isLight ? palette.primary : "#9BC0D8" } } From 34205534f0d8c826d7aef47086c6b3c651de4528 Mon Sep 17 00:00:00 2001 From: DiegoZaff Date: Thu, 26 Oct 2023 23:11:35 +0200 Subject: [PATCH 13/31] improve ux and optimizations --- src/components/Calendar/SingleMonth.tsx | 1 + src/pages/Calendar.tsx | 191 +++++++++++++++--------- src/utils/calendar.tsx | 8 + 3 files changed, 129 insertions(+), 71 deletions(-) diff --git a/src/components/Calendar/SingleMonth.tsx b/src/components/Calendar/SingleMonth.tsx index 8eb71408..53923077 100644 --- a/src/components/Calendar/SingleMonth.tsx +++ b/src/components/Calendar/SingleMonth.tsx @@ -84,6 +84,7 @@ export const SingleMonth: FC = props => { initialDate={new Date(props.year, props.month, 1) .toISOString() .slice(0, 10)} + disableMonthChange={true} customHeaderTitle={undefined} hideExtraDays={true} renderHeader={() => null} diff --git a/src/pages/Calendar.tsx b/src/pages/Calendar.tsx index 6a25bc90..29e9618c 100644 --- a/src/pages/Calendar.tsx +++ b/src/pages/Calendar.tsx @@ -5,7 +5,7 @@ import { NavBar } from "components/NavBar" import { Pressable, View } from "react-native" import { usePalette } from "utils/colors" import { StyleSheet } from "react-native" -import { Calendar } from "react-native-calendars" +import { CalendarList } from "react-native-calendars" import { useContext, useEffect, useMemo, useRef, useState } from "react" import { CalendarPeriod, @@ -54,8 +54,12 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { const lan = useCurrentLanguage() + const today = new Date() + const [selectedDay, setSelectedDay] = useState(new Date().toISOString()) + const [visibleDay, setVisibleDay] = useState(new Date().toISOString()) + const [bottomSheetStatus, setBottomSheetStatus] = useState(CalendarBottomSheetStatus.PERIODS) @@ -65,6 +69,8 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { const [markedDates, setMarkedDates] = useState({}) + const [datesOnlyPeriods, setDatesOnlyPeriods] = useState({}) + const [calendarPeriods, setCalendarPeriods] = useState< CalendarPeriod[] | undefined >() @@ -87,15 +93,104 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { const calendarObj = useRef() + const calendarMemoized = useMemo(() => { + return ( + { + const date = new Date(day.dateString) + const now = new Date() + + //set hours and minutes of date to now + date.setHours(now.getHours()) + date.setMinutes(now.getMinutes()) + + setSelectedDay(date.toISOString()) + + setBottomSheetStatus(CalendarBottomSheetStatus.DAILY_EVENTS) + }} + style={{ + marginTop: 176, + height: 270, + backgroundColor: homeBackground, + }} + markedDates={{ + ...markedDates, + // eslint-disable-next-line @typescript-eslint/naming-convention + "2023-07-15": { + marked: true, + startingDay: true, + endingDay: true, + color: "orange", + }, + }} + customHeaderTitle={undefined} + hideExtraDays={true} + renderHeader={() => null} + renderArrow={() => null} + showSixWeeks={true} + hideDayNames={true} + markingType="period" + current={visibleDay} + onMonthChange={month => { + console.log("month changed") + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + setMonth(month.month - 1) + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access + setYear(month.year) + }} + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + dayComponent={dayComponentCustom} + /> + ) + }, [markedDates, visibleDay]) + // I thought memoizing would improve performance, but it appears to be still very slow!! const scrollMonths = useMemo(() => { + console.log("rerendering") return ( - {[0, 2, 4, 6, 8, 10].map(monthX => { + {[ + [-1, 0], + [1, 2], + [3, 4], + ].map(monthOffsets => { + const monthOffset1 = monthOffsets[0] + + const monthOffset2 = monthOffsets[1] + + const nMonthsAgoOrFutureDate1 = new Date( + today.getTime() + monthOffset1 * 30 * 24 * 60 * 60 * 1000 + ) + + const nMonthsAgoOrFutureDate2 = new Date( + today.getTime() + monthOffset2 * 30 * 24 * 60 * 60 * 1000 + ) + return ( = () => { { - setMonth(monthX) + setMonth(nMonthsAgoOrFutureDate1.getMonth()) + setVisibleDay( + nMonthsAgoOrFutureDate1.toISOString().slice(0, 10) + ) setBottomSheetStatus( CalendarBottomSheetStatus.MONTHLY_EVENTS ) }} > { - setMonth(monthX + 1) + setMonth(nMonthsAgoOrFutureDate2.getMonth()) + setVisibleDay( + nMonthsAgoOrFutureDate2.toISOString().slice(0, 10) + ) setBottomSheetStatus( CalendarBottomSheetStatus.MONTHLY_EVENTS ) }} > @@ -139,7 +240,7 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { ) - }, [markedDates]) + }, [datesOnlyPeriods]) useEffect(() => { const initCalendar = () => { @@ -169,6 +270,12 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { setCalendarEvents([...(calendarObj.current?.calendarEvents ?? [])]) } }) + calendarObj.current.addListener("datesOnlyPeriodsSet", () => { + if (calendarObj.current?.datesOnlyPeriods) { + console.log("datesOnlyPeriodsSet") + setDatesOnlyPeriods(calendarObj.current?.datesOnlyPeriods) + } + }) } else { if (calendarObj.current?.datesMarkedAndPeriods) { setMarkedDates(calendarObj.current?.datesMarkedAndPeriods) @@ -307,65 +414,7 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { {bottomSheetStatus != CalendarBottomSheetStatus.ALL_MONTHS && ( <> - { - const date = new Date(day.dateString) - const now = new Date() - - //set hours and minutes of date to now - date.setHours(now.getHours()) - date.setMinutes(now.getMinutes()) - - setSelectedDay(date.toISOString()) - - setBottomSheetStatus(CalendarBottomSheetStatus.DAILY_EVENTS) - }} - style={{ - marginTop: 150, - height: 290, - backgroundColor: homeBackground, - }} - markedDates={{ - ...markedDates, - // eslint-disable-next-line @typescript-eslint/naming-convention - "2023-07-15": { - marked: true, - startingDay: true, - endingDay: true, - color: "orange", - }, - }} - customHeaderTitle={undefined} - hideExtraDays={true} - renderHeader={() => null} - renderArrow={() => null} - enableSwipeMonths={true} - showSixWeeks={true} - hideDayNames={true} - markingType="period" - current={selectedDay} - onMonthChange={month => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - setMonth(month.month - 1) - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access - setYear(month.year) - }} - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - dayComponent={dayComponentCustom} - /> + {calendarMemoized} void): this on(event: "calendarEventsChanged", listener: () => void): this + + on(event: "datesOnlyPeriodsSet", listener: () => void): this } export class CalendarSingletonWrapper extends EventEmitter { private _datesOnlyPeriods: MarkedDates = {} + public get datesOnlyPeriods(): MarkedDates { + return this._datesOnlyPeriods + } + private _datesMarkedAndPeriods: MarkedDates = {} public get datesMarkedAndPeriods(): MarkedDates | undefined { @@ -497,6 +503,8 @@ export class CalendarSingletonWrapper extends EventEmitter { ...this._datesMarkedAndPeriods, ...periodTmp, } + + this.emit("datesOnlyPeriodsSet") }) }) this._applyMarkers() From e32e29c3f12d17b632680f265a852f41a57372e7 Mon Sep 17 00:00:00 2001 From: DiegoZaff Date: Fri, 27 Oct 2023 21:02:34 +0200 Subject: [PATCH 14/31] datesOnlyPeriods removed --- src/pages/Calendar.tsx | 19 +++++-------------- src/utils/calendar.tsx | 24 ------------------------ 2 files changed, 5 insertions(+), 38 deletions(-) diff --git a/src/pages/Calendar.tsx b/src/pages/Calendar.tsx index 29e9618c..11d68579 100644 --- a/src/pages/Calendar.tsx +++ b/src/pages/Calendar.tsx @@ -69,8 +69,6 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { const [markedDates, setMarkedDates] = useState({}) - const [datesOnlyPeriods, setDatesOnlyPeriods] = useState({}) - const [calendarPeriods, setCalendarPeriods] = useState< CalendarPeriod[] | undefined >() @@ -101,8 +99,8 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { scrollEnabled={true} scrollsToTop={false} initialNumToRender={10} - pastScrollRange={6} - futureScrollRange={6} + pastScrollRange={12} + futureScrollRange={12} horizontal={true} theme={{ calendarBackground: isLight ? palette.primary : palette.darker, @@ -167,7 +165,6 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { // I thought memoizing would improve performance, but it appears to be still very slow!! const scrollMonths = useMemo(() => { - console.log("rerendering") return ( @@ -210,7 +207,7 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { }} > @@ -229,7 +226,7 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { }} > @@ -240,7 +237,7 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { ) - }, [datesOnlyPeriods]) + }, [markedDates]) useEffect(() => { const initCalendar = () => { @@ -270,12 +267,6 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { setCalendarEvents([...(calendarObj.current?.calendarEvents ?? [])]) } }) - calendarObj.current.addListener("datesOnlyPeriodsSet", () => { - if (calendarObj.current?.datesOnlyPeriods) { - console.log("datesOnlyPeriodsSet") - setDatesOnlyPeriods(calendarObj.current?.datesOnlyPeriods) - } - }) } else { if (calendarObj.current?.datesMarkedAndPeriods) { setMarkedDates(calendarObj.current?.datesMarkedAndPeriods) diff --git a/src/utils/calendar.tsx b/src/utils/calendar.tsx index 71e3739f..7311b06e 100644 --- a/src/utils/calendar.tsx +++ b/src/utils/calendar.tsx @@ -136,17 +136,9 @@ export declare interface CalendarSingletonWrapper { on(event: "markedDatesSet", listener: () => void): this on(event: "calendarEventsChanged", listener: () => void): this - - on(event: "datesOnlyPeriodsSet", listener: () => void): this } export class CalendarSingletonWrapper extends EventEmitter { - private _datesOnlyPeriods: MarkedDates = {} - - public get datesOnlyPeriods(): MarkedDates { - return this._datesOnlyPeriods - } - private _datesMarkedAndPeriods: MarkedDates = {} public get datesMarkedAndPeriods(): MarkedDates | undefined { @@ -433,14 +425,6 @@ export class CalendarSingletonWrapper extends EventEmitter { } private _applyPeriods() { - //if datesOnlyPeriods has been already calculated - if (Object.keys(this._datesOnlyPeriods).length > 0) { - this._datesMarkedAndPeriods = this._hidePeriods - ? {} - : { ...this._datesOnlyPeriods } - this._applyMarkers() - return - } this._datesMarkedAndPeriods = {} const periods = this._hidePeriods ? [] : this._calendarPeriods @@ -497,14 +481,6 @@ export class CalendarSingletonWrapper extends EventEmitter { ...this._datesMarkedAndPeriods, ...periodTmp, } - - //save dates with periods for later use - this._datesOnlyPeriods = { - ...this._datesMarkedAndPeriods, - ...periodTmp, - } - - this.emit("datesOnlyPeriodsSet") }) }) this._applyMarkers() From 37625f9b4a73089eb7737e891bf3b01b82f09dc2 Mon Sep 17 00:00:00 2001 From: DiegoZaff Date: Fri, 27 Oct 2023 21:18:56 +0200 Subject: [PATCH 15/31] all months bug fix --- src/pages/Calendar.tsx | 51 +++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/src/pages/Calendar.tsx b/src/pages/Calendar.tsx index 11d68579..a3acb329 100644 --- a/src/pages/Calendar.tsx +++ b/src/pages/Calendar.tsx @@ -173,17 +173,42 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { [1, 2], [3, 4], ].map(monthOffsets => { + const todayYear = today.getFullYear() + const todayMonth = today.getMonth() + const monthOffset1 = monthOffsets[0] const monthOffset2 = monthOffsets[1] - const nMonthsAgoOrFutureDate1 = new Date( - today.getTime() + monthOffset1 * 30 * 24 * 60 * 60 * 1000 - ) + let newYear1 + let newMonth1 = todayMonth + monthOffset1 + + if (newMonth1 === -1) { + newMonth1 = 11 + newYear1 = todayYear - 1 + } else if (newMonth1 === 12) { + newMonth1 = 0 + newYear1 = todayYear + 1 + } else { + newYear1 = todayYear + } - const nMonthsAgoOrFutureDate2 = new Date( - today.getTime() + monthOffset2 * 30 * 24 * 60 * 60 * 1000 - ) + const nMonthsAgoOrFutureDate1 = new Date(newYear1, newMonth1, 1) + + let newYear2 + let newMonth2 = todayMonth + monthOffset2 + + if (newMonth2 === -1) { + newMonth2 = 11 + newYear2 = todayYear - 1 + } else if (newMonth2 === 12) { + newMonth2 = 0 + newYear2 = todayYear + 1 + } else { + newYear2 = todayYear + } + + const nMonthsAgoOrFutureDate2 = new Date(newYear2, newMonth2, 1) return ( = () => { { - if (bottomSheetStatus === CalendarBottomSheetStatus.PERIODS) { + if ( + bottomSheetStatus !== CalendarBottomSheetStatus.MONTHLY_EVENTS + ) { setBottomSheetStatus(CalendarBottomSheetStatus.MONTHLY_EVENTS) } else { setBottomSheetStatus(CalendarBottomSheetStatus.PERIODS) @@ -375,7 +402,15 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { > - + { + if (bottomSheetStatus !== CalendarBottomSheetStatus.PERIODS) { + setBottomSheetStatus(CalendarBottomSheetStatus.PERIODS) + } + }} + > + + {bottomSheetStatus != CalendarBottomSheetStatus.ALL_MONTHS && ( From 0bb0a869a757ffe1e27719c93661b5a98046be3c Mon Sep 17 00:00:00 2001 From: DiegoZaff Date: Fri, 27 Oct 2023 21:43:05 +0200 Subject: [PATCH 16/31] bug fixes --- src/pages/Calendar.tsx | 19 ++++--------------- src/utils/calendar.tsx | 4 ++++ 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/pages/Calendar.tsx b/src/pages/Calendar.tsx index a3acb329..ac041efc 100644 --- a/src/pages/Calendar.tsx +++ b/src/pages/Calendar.tsx @@ -38,13 +38,6 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { const { homeBackground, background, dotColor, isLight, palette } = usePalette() - const [counter, setCounter] = useState(0) - - useEffect(() => { - console.log(counter) - setCounter(counter + 1) - }, [isLight]) - // todo : implement translation :( /* const { t } = useTranslation() */ @@ -150,18 +143,14 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { hideDayNames={true} markingType="period" current={visibleDay} - onMonthChange={month => { - console.log("month changed") - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - setMonth(month.month - 1) - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access - setYear(month.year) + onMonthChange={date => { + setMonth(date.month - 1) + setYear(date.year) }} - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment dayComponent={dayComponentCustom} /> ) - }, [markedDates, visibleDay]) + }, [markedDates, visibleDay, isLight]) // I thought memoizing would improve performance, but it appears to be still very slow!! const scrollMonths = useMemo(() => { diff --git a/src/utils/calendar.tsx b/src/utils/calendar.tsx index 7311b06e..996b7148 100644 --- a/src/utils/calendar.tsx +++ b/src/utils/calendar.tsx @@ -539,6 +539,8 @@ export class CalendarSingletonWrapper extends EventEmitter { } } + this._datesMarkedAndPeriods = { ...this._datesMarkedAndPeriods } + this.emit("markedDatesSet") } @@ -553,6 +555,8 @@ export class CalendarSingletonWrapper extends EventEmitter { marked: false, } + this._datesMarkedAndPeriods = { ...this._datesMarkedAndPeriods } + this.emit("markedDatesSet") } From 197ab542ad8e6e04fe089847557dd2b8b51af747 Mon Sep 17 00:00:00 2001 From: DiegoZaff Date: Fri, 27 Oct 2023 22:17:14 +0200 Subject: [PATCH 17/31] i18n --- src/components/Calendar/CalendarAddEvent.tsx | 22 ++++++++++++------- .../Calendar/CalendarDailyEvents.tsx | 9 ++++++-- .../Calendar/CalendarEventDetails.tsx | 9 ++++---- .../Calendar/CalendarMonthlyEvents.tsx | 11 ++++++---- .../Calendar/CalendarPeriodsSwitches.tsx | 5 ++++- src/locales/jsons/en/calendar.json | 15 ++++++++++++- src/locales/jsons/it/calendar.json | 15 ++++++++++++- src/utils/calendar.tsx | 5 +++++ 8 files changed, 70 insertions(+), 21 deletions(-) diff --git a/src/components/Calendar/CalendarAddEvent.tsx b/src/components/Calendar/CalendarAddEvent.tsx index 1191e147..0e50e276 100644 --- a/src/components/Calendar/CalendarAddEvent.tsx +++ b/src/components/Calendar/CalendarAddEvent.tsx @@ -25,6 +25,7 @@ import { DateTimeBox } from "components/FreeClass/DateTimePicker/DateTimeBox" import DateTimePickerModal from "react-native-modal-datetime-picker" import { Icon } from "components/Icon" import { Modal } from "components/Modal" +import { useTranslation } from "react-i18next" interface CalendarAddEventProps { addEvent: (event: CalendarEvent) => void @@ -65,6 +66,8 @@ export const CalendarAddEvent: FC = props => { const [isDatePickerVisible, setDatePickerVisibility] = useState(false) + const { t } = useTranslation("calendar") + useEffect(() => { const keyboardDidHideListener = Keyboard.addListener( "keyboardDidHide", @@ -108,6 +111,7 @@ export const CalendarAddEvent: FC = props => { const resetNewEvent = () => { setTitle("") + inputText.current?.clear() setMood(undefined) setIsRepeating(false) const now = new Date() @@ -144,7 +148,7 @@ export const CalendarAddEvent: FC = props => { { color: isLight ? homeBackground : "#fff", paddingBottom: 0 }, ]} > - Nuovo Evento + {t("newEvent")} = props => { resetNewEvent() }} > - Annulla + + {t("cancel")} + @@ -205,7 +211,7 @@ export const CalendarAddEvent: FC = props => { }} ref={inputText} placeholderTextColor={isLight ? homeBackground : "#fff"} - placeholder="Aggiungi Titolo" + placeholder={t("addTitle") || "Aggiungi Titolo"} /> = props => { marginRight: 12, }} > - Da + {t("from")} { @@ -256,7 +262,7 @@ export const CalendarAddEvent: FC = props => { marginRight: 12, }} > - A + {t("to")} { @@ -290,7 +296,7 @@ export const CalendarAddEvent: FC = props => { { color: isLight ? homeBackground : "#fff" }, ]} > - Imposta Promemoria + {t("setReminder")} = props => { }} > - {isRepeating ? "Si ripete" : "Non si ripete"} + {isRepeating ? t("repeat") : t("dontRepeat")} @@ -372,7 +378,7 @@ export const CalendarAddEvent: FC = props => { date={dateModeCalendar === "start" ? startDate : endDate} /> setIsMoodModalShowing(false)} diff --git a/src/components/Calendar/CalendarDailyEvents.tsx b/src/components/Calendar/CalendarDailyEvents.tsx index aed8064a..5c3ddbaf 100644 --- a/src/components/Calendar/CalendarDailyEvents.tsx +++ b/src/components/Calendar/CalendarDailyEvents.tsx @@ -18,6 +18,7 @@ import { Icon } from "components/Icon" import tickSvg from "assets/freeClassrooms/tick.svg" import { DottedLine } from "./DottedLine" import { CalendarButton } from "./Button" +import { useTranslation } from "react-i18next" interface CalendarDailyEventsProps { events: CalendarEvent[] @@ -43,6 +44,8 @@ export const CalendarDailyEvents: FC = props => { const { isLight, homeBackground, palette } = usePalette() + const { t } = useTranslation("calendar") + return ( = props => { onPress={() => props?.goToAddEvent()} style={{ width: 100, height: 32 }} > - Aggiungi + {t("add")} @@ -129,7 +132,9 @@ export const CalendarDailyEvents: FC = props => { { color: isLight ? homeBackground : "#fff" }, ]} > - {event.title} + {lan === "it" + ? event.title + : event.titleEn ?? event.title} = props => { const { homeBackground, isLight } = usePalette() - //i18n const { t } = useTranslation("calendar") + const lan = useCurrentLanguage() + const inputText = useRef(null) const timer = useRef(null) @@ -65,7 +67,7 @@ export const CalendarEventDetails: FC = props => { }, ]} > - {event?.title} + {lan === "it" ? event?.title : event?.titleEn ?? event?.title} = props => { maxLength={200} numberOfLines={4} placeholderTextColor={homeBackground} - placeholder="aggiungi delle note" + placeholder={t("addNotes") || "aggiungi delle note"} /> - {/* */} ) } diff --git a/src/components/Calendar/CalendarMonthlyEvents.tsx b/src/components/Calendar/CalendarMonthlyEvents.tsx index 97698d5a..576f47d0 100644 --- a/src/components/Calendar/CalendarMonthlyEvents.tsx +++ b/src/components/Calendar/CalendarMonthlyEvents.tsx @@ -10,6 +10,7 @@ import { usePalette } from "utils/colors" import { Icon } from "components/Icon" import { Divider } from "components/Divider" import deleteSvg from "assets/modal/delete.svg" +import { useTranslation } from "react-i18next" interface CalendarMonthlyEventsProps { events: CalendarEvent[] @@ -25,6 +26,8 @@ export const CalendarMonthlyEvents: FC = props => { const { homeBackground, dotColor, isLight } = usePalette() + const { t } = useTranslation("calendar") + return ( = props => { ]} > {events.length > 0 - ? events.length + " eventi in programma" - : "Nessun evento in programma"} + ? events.length + t("scheduledEvents") + : t("noScheduledEvents")} {events.map(event => { @@ -115,7 +118,7 @@ export const CalendarMonthlyEvents: FC = props => { ]} numberOfLines={1} > - {event.title} + {lan === "it" ? event.title : event.titleEn ?? event.title} {(event.isPolimiEvent == undefined || event.isPolimiEvent == false) && ( @@ -148,7 +151,7 @@ export const CalendarMonthlyEvents: FC = props => { ]} numberOfLines={1} > - {event.notes ?? "aggiungi una nota"} + {event.notes ?? t("addNotes")} diff --git a/src/components/Calendar/CalendarPeriodsSwitches.tsx b/src/components/Calendar/CalendarPeriodsSwitches.tsx index b9cbb433..cfa55da1 100644 --- a/src/components/Calendar/CalendarPeriodsSwitches.tsx +++ b/src/components/Calendar/CalendarPeriodsSwitches.tsx @@ -4,6 +4,7 @@ import { CalendarPeriod } from "utils/calendar" import { ToggleSwitch } from "components/ToggleSwitch" import { Text } from "components/Text" import { usePalette } from "utils/colors" +import { useCurrentLanguage } from "utils/articles" interface CalendarPeriodsSwitchesProps { calendarPeriods?: CalendarPeriod[] @@ -19,6 +20,8 @@ export const CalendarPeriodsSwitches: FC< const { homeBackground, isLight } = usePalette() + const lan = useCurrentLanguage() + if (!calendarPeriods) return null return ( @@ -54,7 +57,7 @@ export const CalendarPeriodsSwitches: FC< { color: isLight ? homeBackground : "#fff" }, ]} > - {period.title} + {lan === "it" ? period.title : period.titleEn ?? period.title} Date: Fri, 27 Oct 2023 23:19:00 +0200 Subject: [PATCH 18/31] added some calendar periods t.t --- src/components/Calendar/SingleMonth.tsx | 3 +- src/pages/Calendar.tsx | 1 + src/utils/calendar.tsx | 125 +++++++++++++++--------- 3 files changed, 82 insertions(+), 47 deletions(-) diff --git a/src/components/Calendar/SingleMonth.tsx b/src/components/Calendar/SingleMonth.tsx index 53923077..3042b4c1 100644 --- a/src/components/Calendar/SingleMonth.tsx +++ b/src/components/Calendar/SingleMonth.tsx @@ -74,6 +74,7 @@ export const SingleMonth: FC = props => { /> = props => { dayTextColor: "#fff", weekVerticalMargin: 2, }} - initialDate={new Date(props.year, props.month, 1) + initialDate={new Date(props.year, props.month, 2) .toISOString() .slice(0, 10)} disableMonthChange={true} diff --git a/src/pages/Calendar.tsx b/src/pages/Calendar.tsx index ac041efc..972e039c 100644 --- a/src/pages/Calendar.tsx +++ b/src/pages/Calendar.tsx @@ -87,6 +87,7 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { const calendarMemoized = useMemo(() => { return ( { - try { - const calendarPeriodsJSON = await FileSystem.readAsStringAsync( - FileSystem.documentDirectory + "calendar_periods.json" - ) - const calendarPeriods = JSON.parse( - calendarPeriodsJSON - ) as CalendarPeriod[] - this._calendarPeriods = calendarPeriods - } catch (err) { - console.log(err) - console.log("Error reading calendarPeriods") - this._calendarPeriods = calendarPeriods - void this._writeCalendarPeriods(calendarPeriods) - } - } - - private _writeCalendarPeriods = async ( - periods: CalendarPeriod[] - ): Promise => { - const calendarPeriodsJSON = JSON.stringify(periods) - try { - this._calendarPeriods = periods - await FileSystem.writeAsStringAsync( - FileSystem.documentDirectory + "calendar_periods.json", - calendarPeriodsJSON - ) - - return true - } catch (err) { - console.log(err) - console.log("Error storing periods ") - return false - } - } - private _applyPeriods() { this._datesMarkedAndPeriods = {} @@ -504,7 +537,7 @@ export class CalendarSingletonWrapper extends EventEmitter { this._calendarPeriods = periods.slice() this.emit("calendarPeriodsChanged") - void this._writeCalendarPeriods(periods) + this._applyPeriods() } @@ -624,7 +657,7 @@ export const monthsEn = [ "May", "June", "July", - "Augost", + "August", "September", "October", "November", From a712a382be2d1adb3c439e52cc50ccf9c34e6f9e Mon Sep 17 00:00:00 2001 From: DiegoZaff Date: Sun, 29 Oct 2023 11:55:28 +0100 Subject: [PATCH 19/31] import eslint rule and interface-class merging fix --- .eslintrc.cjs | 4 ++++ src/utils/calendar.tsx | 7 +++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index c903a10a..0a591ace 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -82,6 +82,10 @@ module.exports = { selector: "enumMember", format: ["UPPER_CASE"], }, + { + selector: "import", + format: null, + }, ], "@typescript-eslint/restrict-plus-operands": "off", diff --git a/src/utils/calendar.tsx b/src/utils/calendar.tsx index 0cb08d20..f5037dd3 100644 --- a/src/utils/calendar.tsx +++ b/src/utils/calendar.tsx @@ -204,7 +204,7 @@ const calendarPeriods: CalendarPeriod[] = [ }, ] -export declare interface CalendarSingletonWrapper { +export declare interface CalendarSingletonWrapperInterface { on(event: "calendarPeriodsChanged", listener: () => void): this on(event: "markedDatesSet", listener: () => void): this @@ -212,7 +212,10 @@ export declare interface CalendarSingletonWrapper { on(event: "calendarEventsChanged", listener: () => void): this } -export class CalendarSingletonWrapper extends EventEmitter { +export class CalendarSingletonWrapper + extends EventEmitter + implements CalendarSingletonWrapperInterface +{ private _datesMarkedAndPeriods: MarkedDates = {} public get datesMarkedAndPeriods(): MarkedDates | undefined { From 68a7a7ffe59e8fd3487fd952f2863378d4329d0c Mon Sep 17 00:00:00 2001 From: Tommaso Morganti Date: Sat, 9 Dec 2023 13:39:52 +0100 Subject: [PATCH 20/31] =?UTF-8?q?probabilmente=20=C3=A8=20questo=20che=20f?= =?UTF-8?q?a=20fallire=20i=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yarn.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn.lock b/yarn.lock index f9575f42..ea9a2114 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6823,9 +6823,9 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -"license-checker@git+https://github.com/mwittig/license-checker.git#d546e3f738e14c62e732346fa355162d46700893": +"license-checker@git+https://github.com/mwittig/license-checker#d546e3f738e14c62e732346fa355162d46700893": version "1.0.0" - resolved "git+https://github.com/mwittig/license-checker.git#d546e3f738e14c62e732346fa355162d46700893" + resolved "git+https://github.com/mwittig/license-checker#d546e3f738e14c62e732346fa355162d46700893" dependencies: chalk "~0.5.1" mkdirp "^0.3.5" From 1b3d379d800f016bcf4cd1d3841a4eee09392db0 Mon Sep 17 00:00:00 2001 From: Tommaso Morganti Date: Tue, 30 Jan 2024 14:55:39 +0100 Subject: [PATCH 21/31] kind of improved rendering? --- package.json | 4 +- .../Calendar/DayComponentCustom.tsx | 171 +++++++ src/components/Calendar/SingleMonth.tsx | 23 +- src/pages/Calendar.tsx | 148 +++--- src/utils/calendar.tsx | 472 +++--------------- yarn.lock | 8 +- 6 files changed, 325 insertions(+), 501 deletions(-) create mode 100644 src/components/Calendar/DayComponentCustom.tsx diff --git a/package.json b/package.json index 3d6e8de4..02be9ec2 100644 --- a/package.json +++ b/package.json @@ -63,9 +63,9 @@ "react": "18.2.0", "react-dom": "18.2.0", "react-i18next": "^12.2.0", - "react-native-app-intro-slider": "^4.0.4", - "react-native-calendars": "^1.1299.0", "react-native": "0.72.5", + "react-native-app-intro-slider": "^4.0.4", + "react-native-calendars": "^1.1303.0", "react-native-dropdown-select-list": "^2.0.4", "react-native-fit-image": "^1.5.5", "react-native-gesture-handler": "~2.12.0", diff --git a/src/components/Calendar/DayComponentCustom.tsx b/src/components/Calendar/DayComponentCustom.tsx new file mode 100644 index 00000000..67d75e43 --- /dev/null +++ b/src/components/Calendar/DayComponentCustom.tsx @@ -0,0 +1,171 @@ +import { FC, useEffect, useMemo, useState } from "react" +import { TouchableOpacity, View, ViewStyle } from "react-native" +import { DayProps } from "react-native-calendars/src/calendar/day" +import { Text } from "components/Text" +import { Canvas, Path, Skia } from "@shopify/react-native-skia" +import { DateData } from "react-native-calendars" +import { palette } from "utils/colors" + +let count = 0 + +export const DayComponentCustom: FC< + DayProps & { date?: DateData; height: number; dark?: boolean } +> = ({ + theme, + marking, + date, + onPress, + onLongPress, + state, + children, + height, + dark, +}) => { + useEffect(() => { + console.log("rendered", count++) + }, []) + const [isMarked, setIsMarked] = useState(marking?.marked ?? false) + + const start = marking?.startingDay ?? false + const end = marking?.endingDay ?? false + const color = marking?.color ?? "transparent" + + useEffect(() => { + // console.log("marked changed") + setIsMarked(marking?.marked ?? false) + }, [marking?.marked]) + + const fillerStyles = useMemo(() => { + const leftFillerStyle: ViewStyle = { flex: 1 } + const rightFillerStyle: ViewStyle = { flex: 1 } + let globalfiller: ViewStyle = {} + + if (start && !end) { + rightFillerStyle.borderBottomColor = color + rightFillerStyle.borderBottomWidth = 2 + rightFillerStyle.borderTopColor = color + rightFillerStyle.borderTopWidth = 2 + } else if (end && !start) { + leftFillerStyle.borderBottomColor = color + leftFillerStyle.borderBottomWidth = 2 + leftFillerStyle.borderTopColor = color + leftFillerStyle.borderTopWidth = 2 + } else if (color && !start && !end) { + globalfiller = { + borderBottomColor: color, + borderBottomWidth: 2, + borderTopColor: color, + borderTopWidth: 2, + } + } + return { leftFillerStyle, rightFillerStyle, globalfiller } + }, [start, end, color]) + + const path = useMemo(() => { + let startAngle: number | undefined + let sweepAngle: number | undefined + + if ((start && end) || state == "today") { + startAngle = 90 + sweepAngle = 360 + } else if (start) { + startAngle = 90 + sweepAngle = 180 + } else if (end) { + startAngle = 270 + sweepAngle = 180 + } else { + return undefined + } + + const path = Skia.Path.Make() + // path.moveTo(18, 1) + //this looks kinda random + path.addArc( + { height: height - 2, width: height - 2, y: 1, x: 1 }, + startAngle, + sweepAngle + ) + + return path + }, [start, end, state]) + + return ( + onPress?.(date)} + onLongPress={() => onLongPress?.(date)} + > + + + + + + {path && ( + + + + )} + + + {String(children)} + + {isMarked && ( + + )} + + + + ) +} diff --git a/src/components/Calendar/SingleMonth.tsx b/src/components/Calendar/SingleMonth.tsx index 6383977a..299a3680 100644 --- a/src/components/Calendar/SingleMonth.tsx +++ b/src/components/Calendar/SingleMonth.tsx @@ -1,16 +1,15 @@ -import { FC } from "react" +import { FC, useCallback } from "react" import { View, ViewStyle } from "react-native" import { Calendar } from "react-native-calendars" import { useCurrentLanguage } from "utils/language" -import { - monthsIt, - monthsEn, - daysOfWeekLetters, - dayComponentAllMonthPage, -} from "utils/calendar" +import { monthsIt, monthsEn, daysOfWeekLetters } from "utils/calendar" import { usePalette } from "utils/colors" import { Text } from "components/Text" -import { MarkedDates } from "react-native-calendars/src/types" +import { DateData, MarkedDates } from "react-native-calendars/src/types" +import { DayComponentCustom } from "./DayComponentCustom" +import { DayProps } from "react-native-calendars/src/calendar/day" + +const DAY_HEIGHT = 22 interface SingleMonthProps { month: number @@ -24,12 +23,15 @@ export const SingleMonth: FC = props => { const lan = useCurrentLanguage() + const DCC = useCallback< + (props: DayProps & { date?: DateData }) => JSX.Element + >(props => , []) + return ( @@ -74,6 +76,7 @@ export const SingleMonth: FC = props => { /> = props => { headerStyle={{ display: "none" }} markingType="period" markedDates={props.markedDates} - dayComponent={dayComponentAllMonthPage} + dayComponent={DCC} /> ) diff --git a/src/pages/Calendar.tsx b/src/pages/Calendar.tsx index a790746f..d062adbe 100644 --- a/src/pages/Calendar.tsx +++ b/src/pages/Calendar.tsx @@ -6,11 +6,17 @@ import { Pressable, View } from "react-native" import { usePalette } from "utils/colors" import { StyleSheet } from "react-native" import { CalendarList } from "react-native-calendars" -import { useContext, useEffect, useMemo, useRef, useState } from "react" +import { + useCallback, + useContext, + useEffect, + useMemo, + useRef, + useState, +} from "react" import { CalendarPeriod, CalendarSingletonWrapper as CalendarManager, - dayComponentCustom, daysOfWeekLetters, CalendarBottomSheetStatus, CalendarEvent, @@ -18,7 +24,8 @@ import { monthsEn, CalendarEventStatus, } from "utils/calendar" -import { MarkedDates } from "react-native-calendars/src/types" +import { DayComponentCustom } from "components/Calendar/DayComponentCustom" +import { DateData, MarkedDates } from "react-native-calendars/src/types" import { Text } from "components/Text" import { Icon } from "components/Icon" import calendarIcon from "assets/calendar/calendar.svg" @@ -33,6 +40,7 @@ import { CalendarDailyEvents } from "components/Calendar/CalendarDailyEvents" import { SingleMonth } from "components/Calendar/SingleMonth" import { ScrollView } from "react-native-gesture-handler" import { useCurrentLanguage } from "utils/language" +import { DayProps } from "react-native-calendars/src/calendar/day" export const CalendarPage: MainStackScreen<"Calendar"> = () => { const { homeBackground, background, dotColor, isLight } = usePalette() @@ -80,75 +88,6 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { const calendarObj = useRef() - const calendarMemoized = useMemo(() => { - return ( - { - const date = new Date(day.dateString) - const now = new Date() - - //set hours and minutes of date to now - date.setHours(now.getHours()) - date.setMinutes(now.getMinutes()) - - setSelectedDay(date.toISOString()) - - setBottomSheetStatus(CalendarBottomSheetStatus.DAILY_EVENTS) - }} - style={{ - marginTop: 176, - height: 270, - backgroundColor: "transparent", - }} - markedDates={{ - ...markedDates, - // eslint-disable-next-line @typescript-eslint/naming-convention - "2023-07-15": { - marked: true, - startingDay: true, - endingDay: true, - color: "orange", - }, - }} - customHeaderTitle={undefined} - hideExtraDays={true} - renderHeader={() => null} - renderArrow={() => null} - showSixWeeks={true} - hideDayNames={true} - markingType="period" - current={visibleDay} - onMonthChange={date => { - setMonth(date.month - 1) - setYear(date.year) - }} - dayComponent={dayComponentCustom} - /> - ) - }, [markedDates, visibleDay, isLight]) - // I thought memoizing would improve performance, but it appears to be still very slow!! const scrollMonths = useMemo(() => { return ( @@ -345,6 +284,10 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { } }, [matricola]) + const DCC = useCallback< + (props: DayProps & { date?: DateData }) => JSX.Element + >(props => , []) + return ( = () => { {bottomSheetStatus != CalendarBottomSheetStatus.ALL_MONTHS && ( <> - {calendarMemoized} + { + const date = new Date(day.dateString) + const now = new Date() + + //set hours and minutes of date to now + date.setHours(now.getHours()) + date.setMinutes(now.getMinutes()) + setSelectedDay(date.toISOString()) + setBottomSheetStatus(CalendarBottomSheetStatus.DAILY_EVENTS) + }} + style={{ + marginTop: 176, + height: 270, + backgroundColor: "transparent", + }} + markedDates={{ + ...markedDates, + // eslint-disable-next-line @typescript-eslint/naming-convention + "2023-07-15": { + marked: true, + startingDay: true, + endingDay: true, + color: "orange", + }, + }} + renderHeader={() => null} + hideExtraDays={true} + showSixWeeks={true} + hideDayNames={true} + markingType="period" + current={visibleDay} + onMonthChange={date => { + setMonth(date.month - 1) + setYear(date.year) + }} + dayComponent={DCC} + /> { - try { - const calendarPolimiSyncJSON = await FileSystem.readAsStringAsync( - FileSystem.documentDirectory + "calendar_polimi_sync.json" - ) - const calendarPolimiSync = JSON.parse( - calendarPolimiSyncJSON - ) as CalendarPolimiSyncObj - this._calendarPolimiSync = calendarPolimiSync - } catch (err) { - console.log(err) - console.log("Error reading calendarPolimiSync") - this._calendarPolimiSync = undefined - } + // try { + // const calendarPolimiSyncJSON = await FileSystem.readAsStringAsync( + // FileSystem.documentDirectory + "calendar_polimi_sync.json" + // ) + // const calendarPolimiSync = JSON.parse( + // calendarPolimiSyncJSON + // ) as CalendarPolimiSyncObj + // this._calendarPolimiSync = calendarPolimiSync + // } catch (err) { + // console.log(err) + // console.log("Error reading calendarPolimiSync") + // this._calendarPolimiSync = undefined + // } } private _writeCalendarPolimiSync = async ( calendarPolimiSync: CalendarPolimiSyncObj - ): Promise => { - const calendarPolimiSyncJSON = JSON.stringify(calendarPolimiSync) - try { - this._calendarPolimiSync = calendarPolimiSync - await FileSystem.writeAsStringAsync( - FileSystem.documentDirectory + "calendar_polimi_sync.json", - calendarPolimiSyncJSON - ) - - return true - } catch (err) { - console.log(err) - console.log("Error storing calendarPolimiSync ") - return false - } + ): Promise => { + // const calendarPolimiSyncJSON = JSON.stringify(calendarPolimiSync) + // try { + // this._calendarPolimiSync = calendarPolimiSync + // await FileSystem.writeAsStringAsync( + // FileSystem.documentDirectory + "calendar_polimi_sync.json", + // calendarPolimiSyncJSON + // ) + // return true + // } catch (err) { + // console.log(err) + // console.log("Error storing calendarPolimiSync ") + // return false + // } } private _readEvents = async () => { - try { - const calendarEventsJSON = await FileSystem.readAsStringAsync( - FileSystem.documentDirectory + "calendar_events.json" - ) - const calendarEvents = JSON.parse(calendarEventsJSON) as CalendarEvent[] - this._calendarEvents = calendarEvents - - this.emit("calendarEventsChanged") - } catch (err) { - console.log(err) - console.log("Error reading calendarEvents") - } - } - - private _writeEvents = async (events: CalendarEvent[]): Promise => { - const calendarEventsJSON = JSON.stringify(events) - try { - this._calendarEvents = events - await FileSystem.writeAsStringAsync( - FileSystem.documentDirectory + "calendar_events.json", - calendarEventsJSON - ) - return true - } catch (err) { - console.log(err) - console.log("Error storing calendar events") - return false - } + // try { + // const calendarEventsJSON = await FileSystem.readAsStringAsync( + // FileSystem.documentDirectory + "calendar_events.json" + // ) + // const calendarEvents = JSON.parse(calendarEventsJSON) as CalendarEvent[] + // this._calendarEvents = calendarEvents + // this.emit("calendarEventsChanged") + // } catch (err) { + // console.log(err) + // console.log("Error reading calendarEvents") + // } + } + + private _writeEvents = async (events: CalendarEvent[]): Promise => { + // const calendarEventsJSON = JSON.stringify(events) + // try { + // this._calendarEvents = events + // await FileSystem.writeAsStringAsync( + // FileSystem.documentDirectory + "calendar_events.json", + // calendarEventsJSON + // ) + // return true + // } catch (err) { + // console.log(err) + // console.log("Error storing calendar events") + // return false + // } } private _applyPeriods() { @@ -697,335 +674,6 @@ export const monthsAcronymsEn = [ "Dec", ] -const FILLER_HEIGHT = 26 -const FILLER_HEIGHT_ALL_MONTHS = 22 - -export const dayComponentCustom: ComponentType< - DayProps & { - date?: DateData | undefined - } -> = props => { - const { - theme, - marking, - date, - onPress, - onLongPress, - state, - /* - accessibilityLabel, - testID, */ - children, - } = props - - const dateData = dateToDateData(date) - - const [isMarked, setIsMarked] = useState(marking?.marked ?? false) - - useEffect(() => { - setIsMarked(marking?.marked ?? false) - }, [marking]) - - const fillerStyles = useMemo(() => { - const leftFillerStyle: ViewStyle = { flex: 1 } - const rightFillerStyle: ViewStyle = { flex: 1 } - let globalfiller: ViewStyle = {} - - const start = marking?.startingDay - const end = marking?.endingDay - - if (start && !end) { - rightFillerStyle.borderBottomColor = marking?.color - rightFillerStyle.borderBottomWidth = 2 - rightFillerStyle.borderTopColor = marking?.color - rightFillerStyle.borderTopWidth = 2 - } else if (end && !start) { - leftFillerStyle.borderBottomColor = marking?.color - leftFillerStyle.borderBottomWidth = 2 - leftFillerStyle.borderTopColor = marking?.color - leftFillerStyle.borderTopWidth = 2 - } else if (marking?.color && !start && !end) { - globalfiller = { - borderBottomColor: marking?.color, - borderBottomWidth: 2, - borderTopColor: marking?.color, - borderTopWidth: 2, - } - } - return { leftFillerStyle, rightFillerStyle, globalfiller } - }, [marking]) - - const path = useMemo(() => { - let startAngle - let sweepAngle - - if ((marking?.startingDay && marking.endingDay) || state == "today") { - startAngle = 90 - sweepAngle = 360 - } else if (marking?.startingDay) { - startAngle = 90 - sweepAngle = 180 - } else if (marking?.endingDay) { - startAngle = 270 - sweepAngle = 180 - } else { - return undefined - } - - const path = Skia.Path.Make() - path.moveTo(19, 1) - //this looks kinda random - path.addArc( - { height: FILLER_HEIGHT - 2, width: 30, y: 1, x: 4 }, - startAngle, - sweepAngle - ) - - return path - }, [marking, state]) - - return ( - { - onPress(dateData) - } - : undefined - } - onLongPress={onLongPress ? () => onLongPress(dateData) : undefined} - > - - - - - - - {path && ( - - - - )} - - - {String(children)} - - - {isMarked && ( - - )} - - - - - ) -} - -export const dayComponentAllMonthPage: ComponentType< - DayProps & { - date?: DateData | undefined - } -> = props => { - const { marking, state, children } = props - - const fillerStyles = useMemo(() => { - const leftFillerStyle: ViewStyle = { flex: 1 } - const rightFillerStyle: ViewStyle = { flex: 1 } - let globalfiller: ViewStyle = {} - - const start = marking?.startingDay - const end = marking?.endingDay - - if (start && !end) { - rightFillerStyle.borderBottomColor = marking?.color - rightFillerStyle.borderBottomWidth = 2 - rightFillerStyle.borderTopColor = marking?.color - rightFillerStyle.borderTopWidth = 2 - } else if (end && !start) { - leftFillerStyle.borderBottomColor = marking?.color - leftFillerStyle.borderBottomWidth = 2 - leftFillerStyle.borderTopColor = marking?.color - leftFillerStyle.borderTopWidth = 2 - } else if (marking?.color && !start && !end) { - globalfiller = { - borderBottomColor: marking?.color, - borderBottomWidth: 2, - borderTopColor: marking?.color, - borderTopWidth: 2, - } - } - return { leftFillerStyle, rightFillerStyle, globalfiller } - }, [marking]) - - const path = useMemo(() => { - let startAngle - let sweepAngle - - if (marking?.startingDay && marking.endingDay) { - startAngle = 90 - sweepAngle = 360 - } else if (marking?.startingDay) { - startAngle = 90 - sweepAngle = 180 - } else if (marking?.endingDay) { - startAngle = 270 - sweepAngle = 180 - } else { - return undefined - } - - const path = Skia.Path.Make() - path.moveTo(19, 1) - //this looks kinda random - path.addArc( - { height: FILLER_HEIGHT_ALL_MONTHS - 2, width: 19, y: 1, x: 4 }, - startAngle, - sweepAngle - ) - - return path - }, [marking, state]) - - return ( - - - - - - - {path && ( - - - - )} - - - {String(children)} - - - - ) -} - -const dateToDateData = ( - date: (string & DateData) | undefined -): DateData | undefined => { - if (date) { - if (typeof date === "string") { - const d = new Date(date) - - return { - day: d.getDate(), - month: d.getMonth() + 1, - year: d.getFullYear(), - dateString: d.toISOString().substring(0, 10), - timestamp: d.getTime(), - } - } else { - return date - } - } - return undefined -} - export const daysOfWeekLetters = ["L", "M", "M", "G", "V", "S", "D"] export const daysOfWeekAcronymsIt = [ diff --git a/yarn.lock b/yarn.lock index ea9a2114..5e211857 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8740,10 +8740,10 @@ react-native-app-intro-slider@^4.0.4: resolved "https://registry.yarnpkg.com/react-native-app-intro-slider/-/react-native-app-intro-slider-4.0.4.tgz#fa5cda7057db62c448ac975ffd2ba0cff94cc8d8" integrity sha512-Zkjaol6X3BbZkHUpVDj2LjdidpS6rCgKi0fx80xgGKa0pHxBRd4swWTv2bHnnvu5k1/HXwYk0mY2TbK+2jHl5w== -react-native-calendars@^1.1299.0: - version "1.1301.0" - resolved "https://registry.yarnpkg.com/react-native-calendars/-/react-native-calendars-1.1301.0.tgz#250760b5762944e0e28bd0431c398332ece28226" - integrity sha512-KfDntslK2qKoVl99Hm9bKZuFrdQTru1Ss2t12bCwKuhrKRh5Ho1wgXBAY5SE9sxxWy8mbydmOcLnmxl7BeYWXw== +react-native-calendars@^1.1303.0: + version "1.1303.0" + resolved "https://registry.yarnpkg.com/react-native-calendars/-/react-native-calendars-1.1303.0.tgz#72f82135947c75c194ab893549e53de69ed27667" + integrity sha512-afR9D+EbJQe/YnlXRly/4pqkM7iXSziaKUZz1EoKWk3R0D+sela5LknziXIiM1XFDCpYk5ZJ3cjnTed0MjxVKg== dependencies: hoist-non-react-statics "^3.3.1" lodash "^4.17.15" From 280a5decaffb7b6027b634724bc7c2e120b22799 Mon Sep 17 00:00:00 2001 From: Tommaso Morganti Date: Sat, 2 Mar 2024 03:38:52 +0100 Subject: [PATCH 22/31] update a bunch of stuff --- .eslintrc.cjs | 3 +- package.json | 18 +- .../settings/contributors/Contributors.tsx | 3 +- yarn.lock | 327 +++++++++++------- 4 files changed, 206 insertions(+), 145 deletions(-) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 0a591ace..b97f91a6 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -84,7 +84,8 @@ module.exports = { }, { selector: "import", - format: null, + format: ["camelCase", "PascalCase", "UPPER_CASE", "snake_case"], + leadingUnderscore: "allow", }, ], diff --git a/package.json b/package.json index 844a66ba..5b5a426c 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "@fortawesome/free-solid-svg-icons": "^6.1.1", "@fortawesome/react-native-fontawesome": "^0.3.0", "@freakycoder/react-native-header-view": "^1.2.0", - "@gorhom/bottom-sheet": "^4.4.3", + "@gorhom/bottom-sheet": "4.4.3", "@react-native-async-storage/async-storage": "1.18.2", "@react-native-community/datetimepicker": "7.2.0", "@react-native-firebase/app": "^17.3.2", @@ -47,10 +47,10 @@ "expo-checkbox": "~2.4.0", "expo-clipboard": "~4.3.1", "expo-constants": "~14.4.2", - "expo-dev-client": "~2.4.11", + "expo-dev-client": "~2.4.12", "expo-device": "~5.4.0", - "expo-file-system": "~15.4.4", - "expo-image": "~1.3.4", + "expo-file-system": "~15.4.5", + "expo-image": "~1.3.5", "expo-linear-gradient": "~12.3.0", "expo-localization": "~14.3.0", "expo-location": "~16.1.0", @@ -58,14 +58,14 @@ "expo-sharing": "~11.5.0", "expo-splash-screen": "~0.20.5", "expo-status-bar": "~1.6.0", - "expo-updates": "~0.18.14", + "expo-updates": "~0.18.19", "geolib": "^3.3.3", "i18next": "^22.4.11", "moment": "^2.29.4", "react": "18.2.0", "react-dom": "18.2.0", "react-i18next": "^12.2.0", - "react-native": "0.72.5", + "react-native": "0.72.6", "react-native-app-intro-slider": "^4.0.4", "react-native-calendars": "^1.1303.0", "react-native-dropdown-select-list": "^2.0.4", @@ -97,11 +97,11 @@ "@babel/core": "^7.20.0", "@types/color-string": "^1.5.2", "@types/npm-license-crawler": "^0.2.1", - "@types/react": "~18.2.14", + "@types/react": "^18.2.48", "@types/react-dom": "~18.0.10", "@types/react-native-vector-icons": "^6.4.10", - "@typescript-eslint/eslint-plugin": "^5.18.0", - "@typescript-eslint/parser": "^5.18.0", + "@typescript-eslint/eslint-plugin": "^7.1.0", + "@typescript-eslint/parser": "^7.1.0", "all-contributors-cli": "^6.24.0", "eslint": "^8.13.0", "eslint-config-prettier": "^8.5.0", diff --git a/src/pages/settings/contributors/Contributors.tsx b/src/pages/settings/contributors/Contributors.tsx index eb041c32..9124ff3b 100644 --- a/src/pages/settings/contributors/Contributors.tsx +++ b/src/pages/settings/contributors/Contributors.tsx @@ -15,6 +15,7 @@ enum ContributionType { export const Contributors: SettingsStackScreen<"Contributors"> = () => { const { isLight } = usePalette() + /* eslint-disable @typescript-eslint/no-unsafe-enum-comparison */ const managementContributors = contributors.filter( c => c.contributions[0] === ContributionType.MANAGEMENT ) @@ -81,7 +82,7 @@ export const Contributors: SettingsStackScreen<"Contributors"> = () => { avatar_url={item.avatar_url} profile={item.profile} contributions={item.contributions} - key={"contributor-" + section + " -" + index} + key={"contributor-" + section.title + " -" + index} /> )} /> diff --git a/yarn.lock b/yarn.lock index 28e5392e..4c2e8559 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1245,19 +1245,14 @@ resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== -"@eslint-community/eslint-utils@^4.2.0": +"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== dependencies: eslint-visitor-keys "^3.3.0" -"@eslint-community/regexpp@^4.4.0": - version "4.9.1" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.9.1.tgz#449dfa81a57a1d755b09aa58d826c1262e4283b4" - integrity sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA== - -"@eslint-community/regexpp@^4.6.1": +"@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": version "4.10.0" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== @@ -1716,18 +1711,20 @@ resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== -"@gorhom/bottom-sheet@^4.4.3": - version "4.5.1" - resolved "https://registry.yarnpkg.com/@gorhom/bottom-sheet/-/bottom-sheet-4.5.1.tgz#1ac4b234a80e7dff263f0b7ac207f92e41562849" - integrity sha512-4Qy6hzvN32fXu2hDxDXOIS0IBGBT6huST7J7+K1V5bXemZ08KIx5ZffyLgwhCUl+CnyeG2KG6tqk6iYLkIwi7Q== +"@gorhom/bottom-sheet@4.4.3": + version "4.4.3" + resolved "https://registry.yarnpkg.com/@gorhom/bottom-sheet/-/bottom-sheet-4.4.3.tgz#4c31f214342faa0ba9cd453a98f8c1e0e780c428" + integrity sha512-ZEbCLbvLaEVNa9c+om/o9Le0q7o9GkEM7smhuoFkqj9CIjv3XbpZof7uEKV86yyta+ONAInNYrCdVSpYQ1Rjkg== dependencies: - "@gorhom/portal" "1.0.14" + "@gorhom/portal" "1.0.13" invariant "^2.2.4" + nanoid "^3.3.3" + react-native-redash "^16.1.1" -"@gorhom/portal@1.0.14": - version "1.0.14" - resolved "https://registry.yarnpkg.com/@gorhom/portal/-/portal-1.0.14.tgz#1953edb76aaba80fb24021dc774550194a18e111" - integrity sha512-MXyL4xvCjmgaORr/rtryDNFy3kU4qUbKlwtQqqsygd0xX3mhKjOLn6mQK8wfu0RkoE0pBE0nAasRoHua+/QZ7A== +"@gorhom/portal@1.0.13": + version "1.0.13" + resolved "https://registry.yarnpkg.com/@gorhom/portal/-/portal-1.0.13.tgz#da3af4d427e1fa68d264107de4b3072a4adf35ce" + integrity sha512-ViClKPkyGnj8HVMW45OGQSnGbWBVh8i3tgMOkGqpm6Cv0WVcDfUL7SER6zyGQy8Wdoj3GUDpAJFMqVOxpmRpzw== dependencies: nanoid "^3.3.1" @@ -2414,6 +2411,11 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== +"@types/json-schema@^7.0.12": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + "@types/mime@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.3.tgz#886674659ce55fe7c6c06ec5ca7c0eb276a08f91" @@ -2494,10 +2496,10 @@ "@types/scheduler" "*" csstype "^3.0.2" -"@types/react@~18.2.14": - version "18.2.33" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.33.tgz#055356243dc4350a9ee6c6a2c07c5cae12e38877" - integrity sha512-v+I7S+hu3PIBoVkKGpSYYpiBT1ijqEzWpzQD62/jm4K74hPpSP7FF9BnKG6+fg2+62weJYkkBWDJlZt5JO/9hg== +"@types/react@^18.2.48": + version "18.2.48" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.48.tgz#11df5664642d0bd879c1f58bc1d37205b064e8f1" + integrity sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -2513,10 +2515,10 @@ resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.5.tgz#4751153abbf8d6199babb345a52e1eb4167d64af" integrity sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw== -"@types/semver@^7.3.12": - version "7.5.3" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.3.tgz#9a726e116beb26c24f1ccd6850201e1246122e04" - integrity sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw== +"@types/semver@^7.5.0": + version "7.5.8" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" + integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== "@types/send@*": version "0.17.3" @@ -2587,89 +2589,91 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^5.18.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz#aeef0328d172b9e37d9bab6dbc13b87ed88977db" - integrity sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag== +"@typescript-eslint/eslint-plugin@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.0.tgz#22bb999a8d59893c0ea07923e8a21f9d985ad740" + integrity sha512-j6vT/kCulhG5wBmGtstKeiVr1rdXE4nk+DT1k6trYkwlrvW9eOF5ZbgKnd/YR6PcM4uTEXa0h6Fcvf6X7Dxl0w== dependencies: - "@eslint-community/regexpp" "^4.4.0" - "@typescript-eslint/scope-manager" "5.62.0" - "@typescript-eslint/type-utils" "5.62.0" - "@typescript-eslint/utils" "5.62.0" + "@eslint-community/regexpp" "^4.5.1" + "@typescript-eslint/scope-manager" "7.1.0" + "@typescript-eslint/type-utils" "7.1.0" + "@typescript-eslint/utils" "7.1.0" + "@typescript-eslint/visitor-keys" "7.1.0" debug "^4.3.4" graphemer "^1.4.0" - ignore "^5.2.0" - natural-compare-lite "^1.4.0" - semver "^7.3.7" - tsutils "^3.21.0" - -"@typescript-eslint/parser@^5.18.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.62.0.tgz#1b63d082d849a2fcae8a569248fbe2ee1b8a56c7" - integrity sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA== - dependencies: - "@typescript-eslint/scope-manager" "5.62.0" - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/typescript-estree" "5.62.0" + ignore "^5.2.4" + natural-compare "^1.4.0" + semver "^7.5.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/parser@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.1.0.tgz#b89dab90840f7d2a926bf4c23b519576e8c31970" + integrity sha512-V1EknKUubZ1gWFjiOZhDSNToOjs63/9O0puCgGS8aDOgpZY326fzFu15QAUjwaXzRZjf/qdsdBrckYdv9YxB8w== + dependencies: + "@typescript-eslint/scope-manager" "7.1.0" + "@typescript-eslint/types" "7.1.0" + "@typescript-eslint/typescript-estree" "7.1.0" + "@typescript-eslint/visitor-keys" "7.1.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c" - integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w== +"@typescript-eslint/scope-manager@7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.1.0.tgz#e4babaa39a3d612eff0e3559f3e99c720a2b4a54" + integrity sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A== dependencies: - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/visitor-keys" "5.62.0" + "@typescript-eslint/types" "7.1.0" + "@typescript-eslint/visitor-keys" "7.1.0" -"@typescript-eslint/type-utils@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz#286f0389c41681376cdad96b309cedd17d70346a" - integrity sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew== +"@typescript-eslint/type-utils@7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.1.0.tgz#372dfa470df181bcee0072db464dc778b75ed722" + integrity sha512-UZIhv8G+5b5skkcuhgvxYWHjk7FW7/JP5lPASMEUoliAPwIH/rxoUSQPia2cuOj9AmDZmwUl1usKm85t5VUMew== dependencies: - "@typescript-eslint/typescript-estree" "5.62.0" - "@typescript-eslint/utils" "5.62.0" + "@typescript-eslint/typescript-estree" "7.1.0" + "@typescript-eslint/utils" "7.1.0" debug "^4.3.4" - tsutils "^3.21.0" + ts-api-utils "^1.0.1" -"@typescript-eslint/types@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" - integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== +"@typescript-eslint/types@7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.1.0.tgz#52a86d6236fda646e7e5fe61154991dc0dc433ef" + integrity sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA== -"@typescript-eslint/typescript-estree@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" - integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA== +"@typescript-eslint/typescript-estree@7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.0.tgz#419b1310f061feee6df676c5bed460537310c593" + integrity sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ== dependencies: - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/visitor-keys" "5.62.0" + "@typescript-eslint/types" "7.1.0" + "@typescript-eslint/visitor-keys" "7.1.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" - semver "^7.3.7" - tsutils "^3.21.0" - -"@typescript-eslint/utils@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86" - integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@types/json-schema" "^7.0.9" - "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.62.0" - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/typescript-estree" "5.62.0" - eslint-scope "^5.1.1" - semver "^7.3.7" - -"@typescript-eslint/visitor-keys@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e" - integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw== - dependencies: - "@typescript-eslint/types" "5.62.0" - eslint-visitor-keys "^3.3.0" + minimatch "9.0.3" + semver "^7.5.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/utils@7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.1.0.tgz#710ecda62aff4a3c8140edabf3c5292d31111ddd" + integrity sha512-WUFba6PZC5OCGEmbweGpnNJytJiLG7ZvDBJJoUcX4qZYf1mGZ97mO2Mps6O2efxJcJdRNpqweCistDbZMwIVHw== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@types/json-schema" "^7.0.12" + "@types/semver" "^7.5.0" + "@typescript-eslint/scope-manager" "7.1.0" + "@typescript-eslint/types" "7.1.0" + "@typescript-eslint/typescript-estree" "7.1.0" + semver "^7.5.4" + +"@typescript-eslint/visitor-keys@7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.0.tgz#576c4ad462ca1378135a55e2857d7aced96ce0a0" + integrity sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA== + dependencies: + "@typescript-eslint/types" "7.1.0" + eslint-visitor-keys "^3.4.1" "@ungap/structured-clone@^1.2.0": version "1.2.0" @@ -2858,6 +2862,11 @@ abort-controller@^3.0.0: dependencies: event-target-shim "^5.0.0" +abs-svg-path@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/abs-svg-path/-/abs-svg-path-0.1.1.tgz#df601c8e8d2ba10d4a76d625e236a9a39c2723bf" + integrity sha512-d8XPSGjfyzlXC3Xx891DJRyZfqk5JU0BJrDQcsWomFIV1/BIzPW5HDH5iDdWpqWaav0YVIEzT1RHTwWr0FFshA== + accepts@^1.3.7, accepts@^1.3.8, accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -4802,7 +4811,7 @@ eslint-rule-composer@^0.3.0: resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9" integrity sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg== -eslint-scope@5.1.1, eslint-scope@^5.1.1: +eslint-scope@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== @@ -5012,23 +5021,23 @@ expo-constants@~14.4.2: "@expo/config" "~8.1.0" uuid "^3.3.2" -expo-dev-client@~2.4.11: - version "2.4.11" - resolved "https://registry.yarnpkg.com/expo-dev-client/-/expo-dev-client-2.4.11.tgz#23b2e9b6c5c5ad62d11d196f82cc4d4c1c09e340" - integrity sha512-A7aKQZeEYG0YJ51GnjOFkMNe118jD1cbU+v5iM3E+H1Co5aVtnlGZWcv8Dtw3uGuWxRgbWGds5TGNbcDmJ1hDg== +expo-dev-client@~2.4.12: + version "2.4.12" + resolved "https://registry.yarnpkg.com/expo-dev-client/-/expo-dev-client-2.4.12.tgz#3ab2d03dfe22527c5f78324e4f658843a19e4d5d" + integrity sha512-3+xg0yb/0g6+JQaWq5+xn2uHoOXP4oSX33aWkaZPSNJLoyzfRaHNDF5MLcrMBbEHCw5T5qZRU291K+uQeMMC0g== dependencies: - expo-dev-launcher "2.4.13" - expo-dev-menu "3.2.1" + expo-dev-launcher "2.4.14" + expo-dev-menu "3.2.2" expo-dev-menu-interface "1.3.0" expo-manifests "~0.7.0" expo-updates-interface "~0.10.0" -expo-dev-launcher@2.4.13: - version "2.4.13" - resolved "https://registry.yarnpkg.com/expo-dev-launcher/-/expo-dev-launcher-2.4.13.tgz#bcae48e16521c05c6d831094adffea13fe64ea99" - integrity sha512-afszaREyGnhWJMmcOuDGs83r0UWeRvZrOHlKQxxst/UhAeFQqlDmkEjwtDWfTUy7BoXuuw2CuQtUFH+vTyjEGA== +expo-dev-launcher@2.4.14: + version "2.4.14" + resolved "https://registry.yarnpkg.com/expo-dev-launcher/-/expo-dev-launcher-2.4.14.tgz#ca0cabbefd6c1989709613ead9e86d2f159fe011" + integrity sha512-SlUf+fEX9sKzDzY1Ui8j5775eLKpO0xPVoI89G7CRsrpUv6ZRvRF836cMFesxkU5d+3bXHpKzDQiEPDSI1G/WQ== dependencies: - expo-dev-menu "3.2.1" + expo-dev-menu "3.2.2" resolve-from "^5.0.0" semver "^7.5.3" @@ -5037,10 +5046,10 @@ expo-dev-menu-interface@1.3.0: resolved "https://registry.yarnpkg.com/expo-dev-menu-interface/-/expo-dev-menu-interface-1.3.0.tgz#51b6be8c6e0ce73e414ac7a545998dfad0dfdb80" integrity sha512-WtRP7trQ2lizJJTTFXUSGGn1deIeHaYej0sUynvu/uC69VrSP4EeSnYOxbmEO29kuT/MsQBMGu0P/AkMQOqCOg== -expo-dev-menu@3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/expo-dev-menu/-/expo-dev-menu-3.2.1.tgz#ada145afca3f0c9638ca42f05a2f79a1f45d9ad5" - integrity sha512-SxH/ZUIYZliMBjJTpiECVSDkP7e81mbGNLH8ZD69iCAfLeH7P1OPXFycEdcvN33I7tVqzFgARGLK/W/8JV+U9w== +expo-dev-menu@3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/expo-dev-menu/-/expo-dev-menu-3.2.2.tgz#e5285846158286e7da20fa44be1b0e2079fa8cc4" + integrity sha512-q0IDlCGkZMsDIFV+Mgnz0Q3u/bcnrF8IFMglJ0onF09e5csLk5Ts7hKoQyervOJeThyI402r9OQsFNaru2tgtg== dependencies: expo-dev-menu-interface "1.3.0" semver "^7.5.3" @@ -5064,6 +5073,13 @@ expo-file-system@~15.4.0, expo-file-system@~15.4.4: dependencies: uuid "^3.4.0" +expo-file-system@~15.4.5: + version "15.4.5" + resolved "https://registry.yarnpkg.com/expo-file-system/-/expo-file-system-15.4.5.tgz#3ef68583027ff0e2fb9eca7a22b3caff6cfc550d" + integrity sha512-xy61KaTaDgXhT/dllwYDHm3ch026EyO8j4eC6wSVr/yE12MMMxAC09yGwy4f7kkOs6ztGVQF5j7ldRzNLN4l0Q== + dependencies: + uuid "^3.4.0" + expo-font@~11.4.0: version "11.4.0" resolved "https://registry.yarnpkg.com/expo-font/-/expo-font-11.4.0.tgz#e2d31c0bb76ba3c37c2d84703a49aeafc3afef28" @@ -5071,10 +5087,10 @@ expo-font@~11.4.0: dependencies: fontfaceobserver "^2.1.0" -expo-image@~1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/expo-image/-/expo-image-1.3.4.tgz#50f8468b118972698a4382853773db2f39e46190" - integrity sha512-2N6etMJA5OWbbvL9IdPVchNoJd18kVo5gcN4uC9Xtv1VM/ik6PRB3Tz+qP/0Uglkzh/yyJjw7aDTqWozj5nLZw== +expo-image@~1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/expo-image/-/expo-image-1.3.5.tgz#426deca8cc9a8a3e72a649e9d98c5019efde0d37" + integrity sha512-yrIR2mnfIKbKcguoqWK3U5m3zvLPnonvSCabB2ErVGhws8zQs7ILYf+7T08j8U6eFcohjw0CoAFJ6RWNsX2EhA== expo-json-utils@~0.7.0: version "0.7.1" @@ -5182,10 +5198,10 @@ expo-updates-interface@~0.10.0: resolved "https://registry.yarnpkg.com/expo-updates-interface/-/expo-updates-interface-0.10.1.tgz#cab075641cd381718ccd9264bf133dc393430a44" integrity sha512-I6JMR7EgjXwckrydDmrkBEX/iw750dcqpzQVsjznYWfi0HTEOxajLHB90fBFqQkUV5i5s4Fd3hYQ1Cn0oMzUbA== -expo-updates@~0.18.14: - version "0.18.17" - resolved "https://registry.yarnpkg.com/expo-updates/-/expo-updates-0.18.17.tgz#11ce03ee95ee19e1a1e253b2a98dd9b3dc019c71" - integrity sha512-oyBDR94nYEtVw+iBod3N9LFqTfpLHofmUjh0lP12YZINUI89hvoAyqRe56eSnlpWkzziG6g1y4NGva0D0ViK6w== +expo-updates@~0.18.19: + version "0.18.19" + resolved "https://registry.yarnpkg.com/expo-updates/-/expo-updates-0.18.19.tgz#40a69ac25f6fcdde7d9ee76b5a5e4e73eb6cd25d" + integrity sha512-dakYQ7XhZtBKMLcim08wum108ZUQcNigurijb/6PKdg3QHn21IzOr/27n6x54DctcoW8w1B8w8y1Xw2svVsx4w== dependencies: "@expo/code-signing-certificates" "0.0.5" "@expo/config" "~8.1.0" @@ -6138,6 +6154,11 @@ ignore@^5.1.9, ignore@^5.2.0: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== +ignore@^5.2.4: + version "5.3.1" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" + integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== + image-size@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/image-size/-/image-size-1.0.2.tgz#d778b6d0ab75b2737c1556dd631652eb963bc486" @@ -7596,6 +7617,13 @@ minimalistic-assert@^1.0.0: dependencies: brace-expansion "^1.1.7" +minimatch@9.0.3: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + minimatch@^5.0.1: version "5.1.6" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" @@ -7737,16 +7765,16 @@ nanoid@^3.1.23, nanoid@^3.3.1, nanoid@^3.3.6: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== +nanoid@^3.3.3: + version "3.3.7" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" + integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== + natives@^1.1.3: version "1.1.6" resolved "https://registry.yarnpkg.com/natives/-/natives-1.1.6.tgz#a603b4a498ab77173612b9ea1acdec4d980f00bb" integrity sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA== -natural-compare-lite@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" - integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== - natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -7875,6 +7903,13 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== +normalize-svg-path@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/normalize-svg-path/-/normalize-svg-path-1.1.0.tgz#0e614eca23c39f0cffe821d6be6cd17e569a766c" + integrity sha512-r9KHKG2UUeB5LoTouwDzBy2VxXlHsiM6fyLQvnJa0S5hrhzqElH/CH7TUGhT1fVvIYBIKf3OpY4YJ4CK+iaqHg== + dependencies: + svg-arc-to-cubic-bezier "^3.0.0" + normalize-url@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" @@ -8222,6 +8257,11 @@ parse-png@^2.1.0: dependencies: pngjs "^3.3.0" +parse-svg-path@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/parse-svg-path/-/parse-svg-path-0.1.2.tgz#7a7ec0d1eb06fa5325c7d3e009b859a09b5d49eb" + integrity sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ== + parseurl@~1.3.2, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -8970,6 +9010,15 @@ react-native-reanimated@~3.3.0: convert-source-map "^2.0.0" invariant "^2.2.4" +react-native-redash@^16.1.1: + version "16.3.0" + resolved "https://registry.yarnpkg.com/react-native-redash/-/react-native-redash-16.3.0.tgz#a9112ff1b0e0b506a2e2ae50967597e73b69d343" + integrity sha512-dhmeYbQ/usGzxZSGZmzmRuIFF2LrtJUKqgseKgf9Jdj0JQ7VM20m/LqTg60+wjxeiyAh2D/vKsQ2U7rMkuoplQ== + dependencies: + abs-svg-path "^0.1.1" + normalize-svg-path "^1.0.1" + parse-svg-path "^0.1.2" + react-native-safe-area-context@4.6.3: version "4.6.3" resolved "https://registry.yarnpkg.com/react-native-safe-area-context/-/react-native-safe-area-context-4.6.3.tgz#f06cfea05b1c4b018aa9758667a109f619c62b55" @@ -9047,10 +9096,10 @@ react-native-webview@13.2.2: escape-string-regexp "2.0.0" invariant "2.2.4" -react-native@0.72.5: - version "0.72.5" - resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.72.5.tgz#2c343fa6f3ead362cf07376634a33a4078864357" - integrity sha512-oIewslu5DBwOmo7x5rdzZlZXCqDIna0R4dUwVpfmVteORYLr4yaZo5wQnMeR+H7x54GaMhmgeqp0ZpULtulJFg== +react-native@0.72.6: + version "0.72.6" + resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.72.6.tgz#9f8d090694907e2f83af22e115cc0e4a3d5fa626" + integrity sha512-RafPY2gM7mcrFySS8TL8x+TIO3q7oAlHpzEmC7Im6pmXni6n1AuufGaVh0Narbr1daxstw7yW7T9BKW5dpVc2A== dependencies: "@jest/create-cache-key-function" "^29.2.1" "@react-native-community/cli" "11.3.7" @@ -9614,13 +9663,20 @@ semver@^7.3.5, semver@^7.3.8, semver@~7.3.2: dependencies: lru-cache "^6.0.0" -semver@^7.3.7, semver@^7.5.2, semver@^7.5.3: +semver@^7.5.2, semver@^7.5.3: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== dependencies: lru-cache "^6.0.0" +semver@^7.5.4: + version "7.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" + integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== + dependencies: + lru-cache "^6.0.0" + send@0.18.0, send@^0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" @@ -10202,6 +10258,11 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +svg-arc-to-cubic-bezier@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.0.tgz#390c450035ae1c4a0104d90650304c3bc814abe6" + integrity sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g== + svgo@^2.7.0: version "2.8.0" resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24" @@ -10384,6 +10445,11 @@ treeify@^1.0.1, treeify@^1.1.0: resolved "https://registry.yarnpkg.com/treeify/-/treeify-1.1.0.tgz#4e31c6a463accd0943879f30667c4fdaff411bb8" integrity sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A== +ts-api-utils@^1.0.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.2.1.tgz#f716c7e027494629485b21c0df6180f4d08f5e8b" + integrity sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA== + ts-interface-checker@^0.1.9: version "0.1.13" resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" @@ -10394,7 +10460,7 @@ ts-object-utils@0.0.5: resolved "https://registry.yarnpkg.com/ts-object-utils/-/ts-object-utils-0.0.5.tgz#95361cdecd7e52167cfc5e634c76345e90a26077" integrity sha512-iV0GvHqOmilbIKJsfyfJY9/dNHCs969z3so90dQWsO1eMMozvTpnB1MEaUbb3FYtZTGjv5sIy/xmslEz0Rg2TA== -tslib@^1.8.1, tslib@^1.9.0: +tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== @@ -10404,13 +10470,6 @@ tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== -tsutils@^3.21.0: - version "3.21.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" - integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== - dependencies: - tslib "^1.8.1" - type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" From 2732e925b201ce3c6eaa5746dc46a4c8dbb16d01 Mon Sep 17 00:00:00 2001 From: Tommaso Morganti Date: Sat, 2 Mar 2024 06:04:21 +0100 Subject: [PATCH 23/31] linciato tanta di quella roba mamma mia --- .gitignore | 1 + .vscode/launch.json | 9 +- app.json | 5 +- .../Calendar/DayComponentCustom.tsx | 5 - src/pages/Calendar.tsx | 766 ++++++++---------- src/utils/calendar.tsx | 81 +- 6 files changed, 396 insertions(+), 471 deletions(-) diff --git a/.gitignore b/.gitignore index be37b410..94b54358 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ npm-debug.* *.orig.* web-build/ .env +%ProgramData% # macOS .DS_Store diff --git a/.vscode/launch.json b/.vscode/launch.json index f3ce4579..faa3c71d 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,11 +5,10 @@ "version": "0.2.0", "configurations": [ { - "name": "Debug in Exponent", - "cwd": "${workspaceFolder}", - "type": "reactnative", - "request": "launch", - "platform": "exponent" + "name": "Attach to Hermes application - Experimental", + "request": "attach", + "type": "reactnativedirect", + "cwd": "${workspaceFolder}" } ] } diff --git a/app.json b/app.json index b448b6fe..3256120c 100644 --- a/app.json +++ b/app.json @@ -53,7 +53,8 @@ } ], "expo-localization" - ] + ], + "sdkVersion": "49.0.0" }, "name": "polifemo" -} +} \ No newline at end of file diff --git a/src/components/Calendar/DayComponentCustom.tsx b/src/components/Calendar/DayComponentCustom.tsx index 67d75e43..3b87ab36 100644 --- a/src/components/Calendar/DayComponentCustom.tsx +++ b/src/components/Calendar/DayComponentCustom.tsx @@ -6,8 +6,6 @@ import { Canvas, Path, Skia } from "@shopify/react-native-skia" import { DateData } from "react-native-calendars" import { palette } from "utils/colors" -let count = 0 - export const DayComponentCustom: FC< DayProps & { date?: DateData; height: number; dark?: boolean } > = ({ @@ -21,9 +19,6 @@ export const DayComponentCustom: FC< height, dark, }) => { - useEffect(() => { - console.log("rendered", count++) - }, []) const [isMarked, setIsMarked] = useState(marking?.marked ?? false) const start = marking?.startingDay ?? false diff --git a/src/pages/Calendar.tsx b/src/pages/Calendar.tsx index d062adbe..2a538989 100644 --- a/src/pages/Calendar.tsx +++ b/src/pages/Calendar.tsx @@ -1,28 +1,15 @@ -import { MainStackScreen, useNavigation } from "navigation/NavigationTypes" +import { MainStackScreen } from "navigation/NavigationTypes" /* import { useTranslation } from "react-i18next" */ -import { BoxShadowView } from "components/BoxShadow" import { NavBar } from "components/NavBar" import { Pressable, View } from "react-native" import { usePalette } from "utils/colors" import { StyleSheet } from "react-native" import { CalendarList } from "react-native-calendars" +import { useCallback, useContext, useMemo, useState } from "react" import { - useCallback, - useContext, - useEffect, - useMemo, - useRef, - useState, -} from "react" -import { - CalendarPeriod, - CalendarSingletonWrapper as CalendarManager, daysOfWeekLetters, - CalendarBottomSheetStatus, - CalendarEvent, - monthsIt, - monthsEn, - CalendarEventStatus, + addMarkForEvents, + generateMarkedDatesFromPeriods, } from "utils/calendar" import { DayComponentCustom } from "components/Calendar/DayComponentCustom" import { DateData, MarkedDates } from "react-native-calendars/src/types" @@ -31,258 +18,231 @@ import { Icon } from "components/Icon" import calendarIcon from "assets/calendar/calendar.svg" import capeIcon from "assets/calendar/cape_calendar.svg" import userIcon from "assets/calendar/user_calendar.svg" -import { CalendarPeriodsSwitches } from "components/Calendar/CalendarPeriodsSwitches" -import { CalendarMonthlyEvents } from "components/Calendar/CalendarMonthlyEvents" -import { CalendarAddEvent } from "components/Calendar/CalendarAddEvent" import { LoginContext } from "contexts/login" -import { CalendarEventDetails } from "components/Calendar/CalendarEventDetails" -import { CalendarDailyEvents } from "components/Calendar/CalendarDailyEvents" -import { SingleMonth } from "components/Calendar/SingleMonth" -import { ScrollView } from "react-native-gesture-handler" -import { useCurrentLanguage } from "utils/language" import { DayProps } from "react-native-calendars/src/calendar/day" +import { useApiCall } from "api/useApiCall" +import { api } from "api" export const CalendarPage: MainStackScreen<"Calendar"> = () => { const { homeBackground, background, dotColor, isLight } = usePalette() const { userInfo } = useContext(LoginContext) - const { matricola } = userInfo?.careers?.[0] ?? {} - const lan = useCurrentLanguage() - - const today = new Date() - - const [selectedDay, setSelectedDay] = useState(new Date().toISOString()) - - const [visibleDay, setVisibleDay] = useState(new Date().toISOString()) - - const [bottomSheetStatus, setBottomSheetStatus] = - useState(CalendarBottomSheetStatus.PERIODS) - const [month, setMonth] = useState(new Date().getMonth()) - const [year, setYear] = useState(new Date().getFullYear()) - const [markedDates, setMarkedDates] = useState({}) - - const [calendarPeriods, setCalendarPeriods] = useState< - CalendarPeriod[] | undefined - >() - - const [calendarEvents, setCalendarEvents] = useState([]) - - const [calendarEventsMonth, setCalendarEventsMonth] = useState< - CalendarEvent[] - >([]) - - const [calendarEventsDaily, setCalendarEventsDaily] = useState< - CalendarEvent[] - >([]) - - const [selectedEvent, setSelectedEvent] = useState( - undefined + const [events] = useApiCall( + api.events.getEvents, + { + matricola: matricola ?? "", + startDate: new Date(2024, 2, 1).toISOString().substring(0, 10), + nEvents: 1000, + }, + [matricola], + {}, + matricola === undefined ) - const navigation = useNavigation() - - const calendarObj = useRef() + const markedDates = useMemo(() => { + return addMarkForEvents(events, generateMarkedDatesFromPeriods([])) + }, [events]) // I thought memoizing would improve performance, but it appears to be still very slow!! - const scrollMonths = useMemo(() => { - return ( - - - {[ - [-1, 0], - [1, 2], - [3, 4], - ].map(monthOffsets => { - const todayYear = today.getFullYear() - const todayMonth = today.getMonth() - - const monthOffset1 = monthOffsets[0] - - const monthOffset2 = monthOffsets[1] - - let newYear1 - let newMonth1 = todayMonth + monthOffset1 - - if (newMonth1 === -1) { - newMonth1 = 11 - newYear1 = todayYear - 1 - } else if (newMonth1 === 12) { - newMonth1 = 0 - newYear1 = todayYear + 1 - } else { - newYear1 = todayYear - } - - const nMonthsAgoOrFutureDate1 = new Date(newYear1, newMonth1, 1) - - let newYear2 - let newMonth2 = todayMonth + monthOffset2 - - if (newMonth2 === -1) { - newMonth2 = 11 - newYear2 = todayYear - 1 - } else if (newMonth2 === 12) { - newMonth2 = 0 - newYear2 = todayYear + 1 - } else { - newYear2 = todayYear - } - - const nMonthsAgoOrFutureDate2 = new Date(newYear2, newMonth2, 1) - - return ( - - { - setMonth(nMonthsAgoOrFutureDate1.getMonth()) - setVisibleDay( - nMonthsAgoOrFutureDate1.toISOString().slice(0, 10) - ) - setBottomSheetStatus( - CalendarBottomSheetStatus.MONTHLY_EVENTS - ) - }} - > - - - - { - setMonth(nMonthsAgoOrFutureDate2.getMonth()) - setVisibleDay( - nMonthsAgoOrFutureDate2.toISOString().slice(0, 10) - ) - setBottomSheetStatus( - CalendarBottomSheetStatus.MONTHLY_EVENTS - ) - }} - > - - - - ) - })} - - - ) - }, [markedDates]) - - useEffect(() => { - const initCalendar = () => { - if (!calendarObj.current) { - calendarObj.current = new CalendarManager({ - hidePeriods: false, - matricola: matricola, - }) - calendarObj.current.addListener("markedDatesSet", () => { - if (calendarObj.current?.datesMarkedAndPeriods) { - console.log("marked dates sets") - setMarkedDates(calendarObj.current?.datesMarkedAndPeriods) - setCalendarPeriods(calendarObj.current?.calendarPeriods) - } - }) - - calendarObj.current.addListener("calendarPeriodsChanged", () => { - if (calendarObj.current?.calendarPeriods) { - console.log("calendarPeriodsChanged") - setCalendarPeriods(calendarObj.current?.calendarPeriods) - } - }) - - calendarObj.current.addListener("calendarEventsChanged", () => { - if (calendarObj.current?.calendarEvents) { - console.log("calendarEventsChanged") - setCalendarEvents([...(calendarObj.current?.calendarEvents ?? [])]) - } - }) - } else { - if (calendarObj.current?.datesMarkedAndPeriods) { - setMarkedDates(calendarObj.current?.datesMarkedAndPeriods) - setCalendarPeriods(calendarObj.current?.calendarPeriods) - } - } - } - - initCalendar() - - return () => { - calendarObj?.current?.removeAllListeners("markedDatesSet") - calendarObj?.current?.removeAllListeners("calendarPeriodsChanged") - calendarObj?.current?.removeAllListeners("calendarEventsChanged") - } - }, []) - - useEffect(() => { - if (calendarEvents.length > 0) { - const filteredEvents = calendarEvents.filter( - event => - new Date(event.start).getMonth() === month && - new Date(event.start).getFullYear() === year - ) - - setCalendarEventsMonth(filteredEvents) - } - }, [calendarEvents, month, year]) - - useEffect(() => { - if (calendarEvents.length > 0) { - const filteredEvents = calendarEvents.filter( - event => - new Date(event.start).getDate() === new Date(selectedDay).getDate() && - new Date(event.start).getMonth() === month && - new Date(event.start).getFullYear() === year - ) - - setCalendarEventsDaily(filteredEvents) - } - }, [calendarEvents, selectedDay]) + // const scrollMonths = useMemo(() => { + // return ( + // + // + // {[ + // [-1, 0], + // [1, 2], + // [3, 4], + // ].map(monthOffsets => { + // const todayYear = today.getFullYear() + // const todayMonth = today.getMonth() + + // const monthOffset1 = monthOffsets[0] + + // const monthOffset2 = monthOffsets[1] + + // let newYear1 + // let newMonth1 = todayMonth + monthOffset1 + + // if (newMonth1 === -1) { + // newMonth1 = 11 + // newYear1 = todayYear - 1 + // } else if (newMonth1 === 12) { + // newMonth1 = 0 + // newYear1 = todayYear + 1 + // } else { + // newYear1 = todayYear + // } + + // const nMonthsAgoOrFutureDate1 = new Date(newYear1, newMonth1, 1) + + // let newYear2 + // let newMonth2 = todayMonth + monthOffset2 + + // if (newMonth2 === -1) { + // newMonth2 = 11 + // newYear2 = todayYear - 1 + // } else if (newMonth2 === 12) { + // newMonth2 = 0 + // newYear2 = todayYear + 1 + // } else { + // newYear2 = todayYear + // } + + // const nMonthsAgoOrFutureDate2 = new Date(newYear2, newMonth2, 1) + + // return ( + // + // { + // setMonth(nMonthsAgoOrFutureDate1.getMonth()) + // setVisibleDay( + // nMonthsAgoOrFutureDate1.toISOString().slice(0, 10) + // ) + // setBottomSheetStatus( + // CalendarBottomSheetStatus.MONTHLY_EVENTS + // ) + // }} + // > + // + // + // + // { + // setMonth(nMonthsAgoOrFutureDate2.getMonth()) + // setVisibleDay( + // nMonthsAgoOrFutureDate2.toISOString().slice(0, 10) + // ) + // setBottomSheetStatus( + // CalendarBottomSheetStatus.MONTHLY_EVENTS + // ) + // }} + // > + // + // + // + // ) + // })} + // + // + // ) + // }, [_markedDates]) + + // useEffect(() => { + // const initCalendar = () => { + // if (!calendarObj.current) { + // calendarObj.current = new CalendarManager({ + // hidePeriods: false, + // matricola: matricola, + // }) + // calendarObj.current.addListener("markedDatesSet", () => { + // if (calendarObj.current?.datesMarkedAndPeriods) { + // console.log("marked dates sets") + // setMarkedDates(calendarObj.current?.datesMarkedAndPeriods) + // setCalendarPeriods(calendarObj.current?.calendarPeriods) + // } + // }) + + // calendarObj.current.addListener("calendarPeriodsChanged", () => { + // if (calendarObj.current?.calendarPeriods) { + // console.log("calendarPeriodsChanged") + // setCalendarPeriods(calendarObj.current?.calendarPeriods) + // } + // }) + + // calendarObj.current.addListener("calendarEventsChanged", () => { + // if (calendarObj.current?.calendarEvents) { + // console.log("calendarEventsChanged") + // setCalendarEvents([...(calendarObj.current?.calendarEvents ?? [])]) + // } + // }) + // } else { + // if (calendarObj.current?.datesMarkedAndPeriods) { + // setMarkedDates(calendarObj.current?.datesMarkedAndPeriods) + // setCalendarPeriods(calendarObj.current?.calendarPeriods) + // } + // } + // } + + // initCalendar() + + // return () => { + // calendarObj?.current?.removeAllListeners("markedDatesSet") + // calendarObj?.current?.removeAllListeners("calendarPeriodsChanged") + // calendarObj?.current?.removeAllListeners("calendarEventsChanged") + // } + // }, []) + + // useEffect(() => { + // if (calendarEvents.length > 0) { + // const filteredEvents = calendarEvents.filter( + // event => + // new Date(event.start).getMonth() === month && + // new Date(event.start).getFullYear() === year + // ) + + // setCalendarEventsMonth(filteredEvents) + // } + // }, [calendarEvents, month, year]) + + // useEffect(() => { + // if (calendarEvents.length > 0) { + // const filteredEvents = calendarEvents.filter( + // event => + // new Date(event.start).getDate() === new Date(selectedDay).getDate() && + // new Date(event.start).getMonth() === month && + // new Date(event.start).getFullYear() === year + // ) + + // setCalendarEventsDaily(filteredEvents) + // } + // }, [calendarEvents, selectedDay]) // hide or show peridos based on bottom sheet status - useEffect(() => { - if ( - bottomSheetStatus !== CalendarBottomSheetStatus.PERIODS && - bottomSheetStatus !== CalendarBottomSheetStatus.ALL_MONTHS - ) { - if (calendarObj.current?.hidePeriods == false) { - calendarObj.current?.hideAllPerdiods() - } - } else if (bottomSheetStatus === CalendarBottomSheetStatus.PERIODS) { - calendarObj.current?.showSwitchedOnPeriods() - } - }, [bottomSheetStatus]) + // useEffect(() => { + // if ( + // bottomSheetStatus !== CalendarBottomSheetStatus.PERIODS && + // bottomSheetStatus !== CalendarBottomSheetStatus.ALL_MONTHS + // ) { + // if (calendarObj.current?.hidePeriods == false) { + // calendarObj.current?.hideAllPerdiods() + // } + // } else if (bottomSheetStatus === CalendarBottomSheetStatus.PERIODS) { + // calendarObj.current?.showSwitchedOnPeriods() + // } + // }, [bottomSheetStatus]) // change matricola - useEffect(() => { - if ( - calendarObj.current && - matricola && - calendarObj.current.matricola !== matricola - ) { - calendarObj.current?.changeMatricola(matricola) - } - }, [matricola]) + // useEffect(() => { + // if ( + // calendarObj.current && + // matricola && + // calendarObj.current.matricola !== matricola + // ) { + // calendarObj.current?.changeMatricola(matricola) + // } + // }, [matricola]) const DCC = useCallback< (props: DayProps & { date?: DateData }) => JSX.Element @@ -308,11 +268,11 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { }} > - bottomSheetStatus === CalendarBottomSheetStatus.ALL_MONTHS - ? setBottomSheetStatus(CalendarBottomSheetStatus.PERIODS) - : setBottomSheetStatus(CalendarBottomSheetStatus.ALL_MONTHS) - } + // onPress={() => + // bottomSheetStatus === CalendarBottomSheetStatus.ALL_MONTHS + // ? setBottomSheetStatus(CalendarBottomSheetStatus.PERIODS) + // : setBottomSheetStatus(CalendarBottomSheetStatus.ALL_MONTHS) + // } > @@ -320,218 +280,124 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { { - if ( - bottomSheetStatus !== CalendarBottomSheetStatus.MONTHLY_EVENTS - ) { - setBottomSheetStatus(CalendarBottomSheetStatus.MONTHLY_EVENTS) - } else { - setBottomSheetStatus(CalendarBottomSheetStatus.PERIODS) - } + // if ( + // bottomSheetStatus !== CalendarBottomSheetStatus.MONTHLY_EVENTS + // ) { + // setBottomSheetStatus(CalendarBottomSheetStatus.MONTHLY_EVENTS) + // } else { + // setBottomSheetStatus(CalendarBottomSheetStatus.PERIODS) + // } }} > { - if (bottomSheetStatus !== CalendarBottomSheetStatus.PERIODS) { - setBottomSheetStatus(CalendarBottomSheetStatus.PERIODS) - } + // if (bottomSheetStatus !== CalendarBottomSheetStatus.PERIODS) { + // setBottomSheetStatus(CalendarBottomSheetStatus.PERIODS) + // } }} > - {bottomSheetStatus != CalendarBottomSheetStatus.ALL_MONTHS && ( - <> - + {daysOfWeekLetters.map((day, index) => ( + - {daysOfWeekLetters.map((day, index) => ( - - {day} - - ))} - - - - )} + {day} + + ))} + + - {bottomSheetStatus != CalendarBottomSheetStatus.ALL_MONTHS && ( - <> - { - const date = new Date(day.dateString) - const now = new Date() - - //set hours and minutes of date to now - date.setHours(now.getHours()) - date.setMinutes(now.getMinutes()) - setSelectedDay(date.toISOString()) - setBottomSheetStatus(CalendarBottomSheetStatus.DAILY_EVENTS) - }} - style={{ - marginTop: 176, - height: 270, - backgroundColor: "transparent", - }} - markedDates={{ - ...markedDates, - // eslint-disable-next-line @typescript-eslint/naming-convention - "2023-07-15": { - marked: true, - startingDay: true, - endingDay: true, - color: "orange", - }, - }} - renderHeader={() => null} - hideExtraDays={true} - showSixWeeks={true} - hideDayNames={true} - markingType="period" - current={visibleDay} - onMonthChange={date => { - setMonth(date.month - 1) - setYear(date.year) - }} - dayComponent={DCC} - /> - - {bottomSheetStatus === CalendarBottomSheetStatus.PERIODS && ( - - calendarObj.current?.updatePeriods(title, value) - } - /> - )} - {bottomSheetStatus === CalendarBottomSheetStatus.MONTHLY_EVENTS && ( - { - calendarObj.current?.removeEvent(id) - }} - onSelectedEvent={(event: CalendarEvent) => { - setSelectedEvent(event) - setBottomSheetStatus(CalendarBottomSheetStatus.EVENT_DETAILS) - }} - /> - )} - {bottomSheetStatus === CalendarBottomSheetStatus.ADD_EVENT && ( - { - calendarObj.current?.addEvent(event) - setBottomSheetStatus(CalendarBottomSheetStatus.MONTHLY_EVENTS) - }} - date={selectedDay} - /> - )} - {bottomSheetStatus == CalendarBottomSheetStatus.DAILY_EVENTS && ( - { - calendarObj.current?.changeEventStatus(id, status) - }} - goToAddEvent={() => { - setBottomSheetStatus(CalendarBottomSheetStatus.ADD_EVENT) - }} - /> - )} - {bottomSheetStatus == CalendarBottomSheetStatus.EVENT_DETAILS && ( - { - calendarObj.current?.updateNotes(id, notes) - }} - /> - )} - - - )} - - {bottomSheetStatus == CalendarBottomSheetStatus.ALL_MONTHS && ( - {scrollMonths} - )} + { + // setVisibleDay(day.dateString) + }} + style={{ + marginTop: 176, + height: 270, + backgroundColor: "transparent", + }} + markedDates={{ + ...markedDates, + // eslint-disable-next-line @typescript-eslint/naming-convention + "2024-03-02": { + marked: true, + }, + }} + renderArrow={() => null} + renderHeader={() => null} + hideExtraDays={true} + showSixWeeks={true} + hideDayNames={true} + markingType="period" + onMonthChange={date => { + setMonth(date.month - 1) + setYear(date.year) + }} + dayComponent={DCC} + /> { - if (bottomSheetStatus === CalendarBottomSheetStatus.EVENT_DETAILS) { - setBottomSheetStatus(CalendarBottomSheetStatus.MONTHLY_EVENTS) - } else if ( - bottomSheetStatus === CalendarBottomSheetStatus.MONTHLY_EVENTS - ) { - setBottomSheetStatus(CalendarBottomSheetStatus.PERIODS) - } else if ( - bottomSheetStatus === CalendarBottomSheetStatus.ADD_EVENT - ) { - setBottomSheetStatus(CalendarBottomSheetStatus.DAILY_EVENTS) - } else if ( - bottomSheetStatus === CalendarBottomSheetStatus.DAILY_EVENTS - ) { - setBottomSheetStatus(CalendarBottomSheetStatus.MONTHLY_EVENTS) - } else if ( - bottomSheetStatus === CalendarBottomSheetStatus.ALL_MONTHS - ) { - setBottomSheetStatus(CalendarBottomSheetStatus.PERIODS) - } else { - navigation.goBack() - } - }} + // overrideBackBehavior={() => { + // if (bottomSheetStatus === CalendarBottomSheetStatus.EVENT_DETAILS) { + // setBottomSheetStatus(CalendarBottomSheetStatus.MONTHLY_EVENTS) + // } else if ( + // bottomSheetStatus === CalendarBottomSheetStatus.MONTHLY_EVENTS + // ) { + // setBottomSheetStatus(CalendarBottomSheetStatus.PERIODS) + // } else if ( + // bottomSheetStatus === CalendarBottomSheetStatus.ADD_EVENT + // ) { + // setBottomSheetStatus(CalendarBottomSheetStatus.DAILY_EVENTS) + // } else if ( + // bottomSheetStatus === CalendarBottomSheetStatus.DAILY_EVENTS + // ) { + // setBottomSheetStatus(CalendarBottomSheetStatus.MONTHLY_EVENTS) + // } else if ( + // bottomSheetStatus === CalendarBottomSheetStatus.ALL_MONTHS + // ) { + // setBottomSheetStatus(CalendarBottomSheetStatus.PERIODS) + // } else { + // navigation.goBack() + // } + // }} /> ) diff --git a/src/utils/calendar.tsx b/src/utils/calendar.tsx index 1b84912f..c5d0db23 100644 --- a/src/utils/calendar.tsx +++ b/src/utils/calendar.tsx @@ -46,7 +46,6 @@ export interface CalendarPeriod { titleEn?: string subtitle?: string color: string - shown: boolean } export interface CalendarEvent { @@ -103,7 +102,6 @@ const calendarPeriods: CalendarPeriod[] = [ titleEn: "Holidays", subtitle: "1/08 - 24/08", color: palette.goldish, - shown: true, }, { dates: [ @@ -131,7 +129,6 @@ const calendarPeriods: CalendarPeriod[] = [ titleEn: "Profit exams", subtitle: "23/08 - 31/08", color: purpleBerry, - shown: true, }, { dates: [ @@ -143,7 +140,6 @@ const calendarPeriods: CalendarPeriod[] = [ title: "Prove in Itinere", titleEn: "Midterm exams", color: "#F29999", - shown: true, }, { dates: [ @@ -154,7 +150,6 @@ const calendarPeriods: CalendarPeriod[] = [ title: "Lauree 1° Livello", titleEn: "Bachelor's degree", color: "#F28C52", - shown: true, }, { dates: [ @@ -167,7 +162,6 @@ const calendarPeriods: CalendarPeriod[] = [ title: "Lauree Magistrali", titleEn: "Master's degree", color: "#96CEAD", - shown: true, }, { dates: [ @@ -179,10 +173,81 @@ const calendarPeriods: CalendarPeriod[] = [ title: "Festività", titleEn: "Festivities", color: "#F29999", - shown: true, }, ] +export function addMarkForEvents( + events: Event[] | null, + markedDates: MarkedDates = {} +): MarkedDates { + if (events) { + events.forEach(event => { + const start = event.date_start.substring(0, 10) + const md = markedDates[start] + if (md) md.marked = true + else markedDates[start] = { marked: true } + }) + } + + return markedDates +} + +export function generateMarkedDatesFromPeriods( + periodFilters: number[] +): MarkedDates { + const markedDates: MarkedDates = {} + calendarPeriods + .filter((_, i) => !periodFilters.includes(i)) + .forEach(period => + period.dates.forEach(date => { + let tmpDate: string + let tmpDateObj: Date + let tmpDateEndObj: Date + + if (date.start && date.end) { + if (date.start === date.end) { + markedDates[date.start] = { + color: period.color, + startingDay: true, + endingDay: true, + } + } else { + tmpDate = date.start + tmpDateObj = new Date(tmpDate) + tmpDateEndObj = new Date(date.end) + + //add first day + markedDates[tmpDate] = { + color: period.color, + startingDay: true, + } + + const res = getNextDayFormattedDate(tmpDateObj) + tmpDate = res.dateString + tmpDateObj = res.dateObj + + while (tmpDateObj.getTime() < tmpDateEndObj.getTime()) { + //add day in the middle + markedDates[tmpDate] = { + color: period.color, + } + const res = getNextDayFormattedDate(tmpDateObj) + tmpDate = res.dateString + tmpDateObj = res.dateObj + } + + //add last day + markedDates[tmpDate] = { + color: period.color, + endingDay: true, + } + } + } + }) + ) + return markedDates +} + export declare interface CalendarSingletonWrapperInterface { on(event: "calendarPeriodsChanged", listener: () => void): this @@ -448,7 +513,6 @@ export class CalendarSingletonWrapper const periods = this._hidePeriods ? [] : this._calendarPeriods periods?.forEach(period => { - if (!period.shown) return period.dates.forEach(date => { const periodTmp: MarkedDates = {} let tmpDate: string @@ -508,7 +572,6 @@ export class CalendarSingletonWrapper const periods = this._calendarPeriods ?? [] for (let i = 0; i < periods.length; i++) { if (periods[i].title === title) { - periods[i].shown = val break } } From f3f0b053724f1508d310760c3e9ca8f4f6928760 Mon Sep 17 00:00:00 2001 From: Tommaso Morganti Date: Sat, 2 Mar 2024 06:16:33 +0100 Subject: [PATCH 24/31] streamlined marked dates --- src/pages/Calendar.tsx | 15 ++++----- src/utils/calendar.tsx | 76 ++++++++++++++++++++++-------------------- 2 files changed, 46 insertions(+), 45 deletions(-) diff --git a/src/pages/Calendar.tsx b/src/pages/Calendar.tsx index 2a538989..fe493619 100644 --- a/src/pages/Calendar.tsx +++ b/src/pages/Calendar.tsx @@ -9,7 +9,7 @@ import { useCallback, useContext, useMemo, useState } from "react" import { daysOfWeekLetters, addMarkForEvents, - generateMarkedDatesFromPeriods, + addMarkForPeriods, } from "utils/calendar" import { DayComponentCustom } from "components/Calendar/DayComponentCustom" import { DateData, MarkedDates } from "react-native-calendars/src/types" @@ -45,7 +45,10 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { ) const markedDates = useMemo(() => { - return addMarkForEvents(events, generateMarkedDatesFromPeriods([])) + let markedDates = {} + markedDates = addMarkForEvents(markedDates, events) + markedDates = addMarkForPeriods(markedDates, []) + return markedDates }, [events]) // I thought memoizing would improve performance, but it appears to be still very slow!! @@ -354,13 +357,7 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { height: 270, backgroundColor: "transparent", }} - markedDates={{ - ...markedDates, - // eslint-disable-next-line @typescript-eslint/naming-convention - "2024-03-02": { - marked: true, - }, - }} + markedDates={markedDates} renderArrow={() => null} renderHeader={() => null} hideExtraDays={true} diff --git a/src/utils/calendar.tsx b/src/utils/calendar.tsx index c5d0db23..1fe0f491 100644 --- a/src/utils/calendar.tsx +++ b/src/utils/calendar.tsx @@ -177,70 +177,74 @@ const calendarPeriods: CalendarPeriod[] = [ ] export function addMarkForEvents( - events: Event[] | null, - markedDates: MarkedDates = {} + markedDates: MarkedDates, + events: Event[] | null ): MarkedDates { if (events) { events.forEach(event => { const start = event.date_start.substring(0, 10) - const md = markedDates[start] - if (md) md.marked = true - else markedDates[start] = { marked: true } + markedDates[start] = { + ...markedDates[start], + marked: true, + } }) } return markedDates } -export function generateMarkedDatesFromPeriods( +export function addMarkForPeriods( + markedDates: MarkedDates, periodFilters: number[] ): MarkedDates { - const markedDates: MarkedDates = {} calendarPeriods .filter((_, i) => !periodFilters.includes(i)) .forEach(period => period.dates.forEach(date => { + if (!date.start || !date.end) return let tmpDate: string let tmpDateObj: Date let tmpDateEndObj: Date - if (date.start && date.end) { - if (date.start === date.end) { - markedDates[date.start] = { - color: period.color, - startingDay: true, - endingDay: true, - } - } else { - tmpDate = date.start - tmpDateObj = new Date(tmpDate) - tmpDateEndObj = new Date(date.end) + if (date.start === date.end) { + markedDates[date.start] = { + ...markedDates[date.start], + color: period.color, + startingDay: true, + endingDay: true, + } + } else { + tmpDate = date.start + tmpDateObj = new Date(tmpDate) + tmpDateEndObj = new Date(date.end) + + //add first day + markedDates[tmpDate] = { + ...markedDates[tmpDate], + color: period.color, + startingDay: true, + } - //add first day + const res = getNextDayFormattedDate(tmpDateObj) + tmpDate = res.dateString + tmpDateObj = res.dateObj + + while (tmpDateObj.getTime() < tmpDateEndObj.getTime()) { + //add day in the middle markedDates[tmpDate] = { + ...markedDates[tmpDate], color: period.color, - startingDay: true, } - const res = getNextDayFormattedDate(tmpDateObj) tmpDate = res.dateString tmpDateObj = res.dateObj + } - while (tmpDateObj.getTime() < tmpDateEndObj.getTime()) { - //add day in the middle - markedDates[tmpDate] = { - color: period.color, - } - const res = getNextDayFormattedDate(tmpDateObj) - tmpDate = res.dateString - tmpDateObj = res.dateObj - } - - //add last day - markedDates[tmpDate] = { - color: period.color, - endingDay: true, - } + //add last day + markedDates[tmpDate] = { + ...markedDates[tmpDate], + color: period.color, + endingDay: true, } } }) From 9df89de38df5dfc48c3aaa188d08e1984f1c5b11 Mon Sep 17 00:00:00 2001 From: Tommaso Morganti Date: Sat, 2 Mar 2024 06:19:31 +0100 Subject: [PATCH 25/31] lint temp fix --- src/components/Calendar/CalendarPeriodsSwitches.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Calendar/CalendarPeriodsSwitches.tsx b/src/components/Calendar/CalendarPeriodsSwitches.tsx index bcaae7be..0ee8a297 100644 --- a/src/components/Calendar/CalendarPeriodsSwitches.tsx +++ b/src/components/Calendar/CalendarPeriodsSwitches.tsx @@ -70,7 +70,7 @@ export const CalendarPeriodsSwitches: FC< props.onSwitchChange(value, period.title)} /> From 05b4436c911aa9792480ba829f0b9418712ab477 Mon Sep 17 00:00:00 2001 From: Tommaso Morganti Date: Sat, 2 Mar 2024 08:03:30 +0100 Subject: [PATCH 26/31] bottom sheet proof of concept --- .../Calendar/CalendarBottomSheet.tsx | 63 +++++++++++++++++++ .../Calendar/CalendarBottomSheetHandle.tsx | 56 +++++++++++++++++ .../Calendar/CalendarMonthlyEvents.tsx | 46 ++++---------- src/pages/Calendar.tsx | 33 ++++++---- src/utils/calendar.tsx | 4 +- 5 files changed, 156 insertions(+), 46 deletions(-) create mode 100644 src/components/Calendar/CalendarBottomSheet.tsx create mode 100644 src/components/Calendar/CalendarBottomSheetHandle.tsx diff --git a/src/components/Calendar/CalendarBottomSheet.tsx b/src/components/Calendar/CalendarBottomSheet.tsx new file mode 100644 index 00000000..7a9fc03c --- /dev/null +++ b/src/components/Calendar/CalendarBottomSheet.tsx @@ -0,0 +1,63 @@ +import BottomSheet, { BottomSheetScrollView } from "@gorhom/bottom-sheet" +import { FC } from "react" +import { usePalette } from "utils/colors" +import { getUsableScreenHeight } from "utils/layout" +import { CalendarBottomSheetHandle } from "./CalendarBottomSheetHandle" +import { Event } from "api/collections/event" +import { CalendarMonthlyEvents } from "./CalendarMonthlyEvents" +import { monthsIt } from "utils/calendar" +import { DateData } from "react-native-calendars" + +export interface CalendarBottomSheetProps { + events: Event[] | null + currentMonthDateData: DateData +} + +const distanceFromTop = { + closed: 426, + opened: 106, +} + +export const CalendarBottomSheet: FC = props => { + const { background } = usePalette() + + return ( + + + + + + ) +} diff --git a/src/components/Calendar/CalendarBottomSheetHandle.tsx b/src/components/Calendar/CalendarBottomSheetHandle.tsx new file mode 100644 index 00000000..3981cd99 --- /dev/null +++ b/src/components/Calendar/CalendarBottomSheetHandle.tsx @@ -0,0 +1,56 @@ +import { FC } from "react" +import { View, StyleSheet, Dimensions } from "react-native" +import { BoxShadowCanvas } from "components/BoxShadow" +import { usePalette } from "utils/colors" + +const offset = 79 + +/** + * this needs to be a separate component because declearing it inline changes its + * reference and the shadows get all fucky if you keep re-rendering them + */ +export const CalendarBottomSheetHandle: FC = () => { + const { background, isLight, palette } = usePalette() + + return ( + + + + + + + ) +} + +const styles = StyleSheet.create({ + topBar: { + justifyContent: "center", + paddingHorizontal: 26, + borderTopLeftRadius: 30, + borderTopRightRadius: 30, + paddingBottom: 8, + height: 60, + }, +}) diff --git a/src/components/Calendar/CalendarMonthlyEvents.tsx b/src/components/Calendar/CalendarMonthlyEvents.tsx index 576f47d0..246a323f 100644 --- a/src/components/Calendar/CalendarMonthlyEvents.tsx +++ b/src/components/Calendar/CalendarMonthlyEvents.tsx @@ -1,24 +1,18 @@ import { FC } from "react" -import { View, ScrollView, StyleSheet, Pressable } from "react-native" -import { - CalendarEvent, - formatCalendarEventDay, - getSourceEmoticon, -} from "utils/calendar" +import { View, StyleSheet, Pressable } from "react-native" +import { formatCalendarEventDay, getSourceEmoticon } from "utils/calendar" import { Text } from "components/Text" import { usePalette } from "utils/colors" import { Icon } from "components/Icon" import { Divider } from "components/Divider" -import deleteSvg from "assets/modal/delete.svg" import { useTranslation } from "react-i18next" +import { Event } from "api/collections/event" interface CalendarMonthlyEventsProps { - events: CalendarEvent[] + events: Event[] month: string year: number lan: string - onDeleteEvent: (id: string) => void - onSelectedEvent: (event: CalendarEvent) => void } export const CalendarMonthlyEvents: FC = props => { @@ -29,13 +23,7 @@ export const CalendarMonthlyEvents: FC = props => { const { t } = useTranslation("calendar") return ( - + = props => { {events.map(event => { return ( props.onSelectedEvent(event)} + key={event.event_id} + onPress={() => { + // TODO: on press + }} > = props => { }} > - + = props => { ]} numberOfLines={1} > - {lan === "it" ? event.title : event.titleEn ?? event.title} + {lan === "it" ? event.title.it : event.title.en} - {(event.isPolimiEvent == undefined || - event.isPolimiEvent == false) && ( - props.onDeleteEvent(event.id)}> - - - )} = props => { ]} numberOfLines={1} > - {event.notes ?? t("addNotes")} + {t("addNotes")} ) })} - + ) } diff --git a/src/pages/Calendar.tsx b/src/pages/Calendar.tsx index fe493619..2e920758 100644 --- a/src/pages/Calendar.tsx +++ b/src/pages/Calendar.tsx @@ -2,7 +2,7 @@ import { MainStackScreen } from "navigation/NavigationTypes" /* import { useTranslation } from "react-i18next" */ import { NavBar } from "components/NavBar" import { Pressable, View } from "react-native" -import { usePalette } from "utils/colors" +import { palette, usePalette } from "utils/colors" import { StyleSheet } from "react-native" import { CalendarList } from "react-native-calendars" import { useCallback, useContext, useMemo, useState } from "react" @@ -22,15 +22,24 @@ import { LoginContext } from "contexts/login" import { DayProps } from "react-native-calendars/src/calendar/day" import { useApiCall } from "api/useApiCall" import { api } from "api" +import { CalendarBottomSheet } from "components/Calendar/CalendarBottomSheet" export const CalendarPage: MainStackScreen<"Calendar"> = () => { - const { homeBackground, background, dotColor, isLight } = usePalette() + const { homeBackground, dotColor, isLight } = usePalette() const { userInfo } = useContext(LoginContext) const { matricola } = userInfo?.careers?.[0] ?? {} - const [month, setMonth] = useState(new Date().getMonth()) - const [year, setYear] = useState(new Date().getFullYear()) + const [monthDateData, setMonthDateData] = useState({ + day: new Date().getDate(), + timestamp: Date.now(), + dateString: new Date().toISOString().slice(0, 10), + month: new Date().getMonth() + 1, + year: new Date().getFullYear(), + }) + const [selectedDay, setSelectedDay] = useState( + new Date().toISOString().slice(0, 10) + ) const [events] = useApiCall( api.events.getEvents, @@ -259,7 +268,6 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { top: 120, height: 40, width: "100%", - zIndex: 2, paddingHorizontal: 28, }} > @@ -342,7 +350,7 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { todayTextColor: "yellow", dayTextColor: "#fff", dotStyle: { width: 6, height: 6, borderRadius: 3 }, - dotColor: dotColor, + dotColor: palette.accent, stylesheet: { day: { period: { isLight: isLight }, @@ -350,7 +358,7 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { }, }} onDayPress={day => { - // setVisibleDay(day.dateString) + setSelectedDay(day.dateString) }} style={{ marginTop: 176, @@ -363,14 +371,17 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { hideExtraDays={true} showSixWeeks={true} hideDayNames={true} + current={selectedDay} markingType="period" - onMonthChange={date => { - setMonth(date.month - 1) - setYear(date.year) - }} + onMonthChange={date => setMonthDateData(date)} dayComponent={DCC} /> + + { // if (bottomSheetStatus === CalendarBottomSheetStatus.EVENT_DETAILS) { diff --git a/src/utils/calendar.tsx b/src/utils/calendar.tsx index 1fe0f491..7f33d169 100644 --- a/src/utils/calendar.tsx +++ b/src/utils/calendar.tsx @@ -783,8 +783,8 @@ const daysOfWeekEn = [ "Sunday", ] -export const formatCalendarEventDay = (event: CalendarEvent, lan: string) => { - const date = new Date(event.start) +export const formatCalendarEventDay = (event: Event, lan: string) => { + const date = new Date(event.date_start) const day = date.getDate() From 027e3dafe84683ef209c49aec615514b67998fb2 Mon Sep 17 00:00:00 2001 From: Tommaso Morganti Date: Sat, 2 Mar 2024 08:03:41 +0100 Subject: [PATCH 27/31] aren't full colors just beautiful --- .../Calendar/DayComponentCustom.tsx | 117 ++++++------------ 1 file changed, 35 insertions(+), 82 deletions(-) diff --git a/src/components/Calendar/DayComponentCustom.tsx b/src/components/Calendar/DayComponentCustom.tsx index 3b87ab36..bcec811d 100644 --- a/src/components/Calendar/DayComponentCustom.tsx +++ b/src/components/Calendar/DayComponentCustom.tsx @@ -1,5 +1,5 @@ import { FC, useEffect, useMemo, useState } from "react" -import { TouchableOpacity, View, ViewStyle } from "react-native" +import { TouchableOpacity, View } from "react-native" import { DayProps } from "react-native-calendars/src/calendar/day" import { Text } from "components/Text" import { Canvas, Path, Skia } from "@shopify/react-native-skia" @@ -30,102 +30,55 @@ export const DayComponentCustom: FC< setIsMarked(marking?.marked ?? false) }, [marking?.marked]) - const fillerStyles = useMemo(() => { - const leftFillerStyle: ViewStyle = { flex: 1 } - const rightFillerStyle: ViewStyle = { flex: 1 } - let globalfiller: ViewStyle = {} - - if (start && !end) { - rightFillerStyle.borderBottomColor = color - rightFillerStyle.borderBottomWidth = 2 - rightFillerStyle.borderTopColor = color - rightFillerStyle.borderTopWidth = 2 - } else if (end && !start) { - leftFillerStyle.borderBottomColor = color - leftFillerStyle.borderBottomWidth = 2 - leftFillerStyle.borderTopColor = color - leftFillerStyle.borderTopWidth = 2 - } else if (color && !start && !end) { - globalfiller = { - borderBottomColor: color, - borderBottomWidth: 2, - borderTopColor: color, - borderTopWidth: 2, - } - } - return { leftFillerStyle, rightFillerStyle, globalfiller } - }, [start, end, color]) - const path = useMemo(() => { - let startAngle: number | undefined - let sweepAngle: number | undefined - + const path = Skia.Path.Make() if ((start && end) || state == "today") { - startAngle = 90 - sweepAngle = 360 + path.addArc( + { height: height, width: height, y: 0, x: height * 1.5 }, + 90, + 360 + ) } else if (start) { - startAngle = 90 - sweepAngle = 180 + path.addRect({ height: height, width: height * 2, y: 0, x: height * 2 }) + path.addArc( + { height: height, width: height, y: 0, x: height * 1.5 }, + 90, + 180 + ) } else if (end) { - startAngle = 270 - sweepAngle = 180 + path.addRect({ height: height, width: height * 2, y: 0, x: 0 }) + path.addArc( + { height: height, width: height, y: 0, x: height * 1.5 }, + 270, + 180 + ) } else { - return undefined + path.addRect({ height: height, width: height * 4, y: 0, x: 0 }) } - - const path = Skia.Path.Make() - // path.moveTo(18, 1) - //this looks kinda random - path.addArc( - { height: height - 2, width: height - 2, y: 1, x: 1 }, - startAngle, - sweepAngle - ) - return path }, [start, end, state]) return ( onPress?.(date)} onLongPress={() => onLongPress?.(date)} > - - - - - {path && ( - - - - )} + + Date: Tue, 5 Mar 2024 12:21:52 +0100 Subject: [PATCH 28/31] a different take on design --- .../Calendar/CalendarBottomSheet.tsx | 2 +- .../Calendar/CalendarBottomSheetHandle.tsx | 2 +- .../Calendar/DayComponentCustom.tsx | 183 ++++++++---------- src/pages/Calendar.tsx | 12 +- 4 files changed, 88 insertions(+), 111 deletions(-) diff --git a/src/components/Calendar/CalendarBottomSheet.tsx b/src/components/Calendar/CalendarBottomSheet.tsx index 7a9fc03c..844570f0 100644 --- a/src/components/Calendar/CalendarBottomSheet.tsx +++ b/src/components/Calendar/CalendarBottomSheet.tsx @@ -14,7 +14,7 @@ export interface CalendarBottomSheetProps { } const distanceFromTop = { - closed: 426, + closed: 516, opened: 106, } diff --git a/src/components/Calendar/CalendarBottomSheetHandle.tsx b/src/components/Calendar/CalendarBottomSheetHandle.tsx index 3981cd99..3c81a394 100644 --- a/src/components/Calendar/CalendarBottomSheetHandle.tsx +++ b/src/components/Calendar/CalendarBottomSheetHandle.tsx @@ -10,7 +10,7 @@ const offset = 79 * reference and the shadows get all fucky if you keep re-rendering them */ export const CalendarBottomSheetHandle: FC = () => { - const { background, isLight, palette } = usePalette() + const { background } = usePalette() return ( = ({ - theme, - marking, - date, - onPress, - onLongPress, - state, - children, - height, - dark, -}) => { - const [isMarked, setIsMarked] = useState(marking?.marked ?? false) +const height = 30 - const start = marking?.startingDay ?? false - const end = marking?.endingDay ?? false - const color = marking?.color ?? "transparent" +export const DayComponentCustom: FC = memo( + function dayComponent({ + theme, + marking, + date, + onPress, + onLongPress, + state, + children, + }) { + const start = marking?.startingDay ?? false + const end = marking?.endingDay ?? false + const color = marking?.color ?? "transparent" - useEffect(() => { - // console.log("marked changed") - setIsMarked(marking?.marked ?? false) - }, [marking?.marked]) + const path = useMemo(() => { + const path = Skia.Path.Make() + if ((start && end) || state == "today") { + path.addArc({ height, width: height, y: 0, x: height * 1.5 }, 90, 360) + } else if (start) { + path.addRect({ height, width: height * 2, y: 0, x: height * 2 }) + path.addArc({ height, width: height, y: 0, x: height * 1.5 }, 90, 180) + } else if (end) { + path.addRect({ height, width: height * 2, y: 0, x: 0 }) + path.addArc({ height, width: height, y: 0, x: height * 1.5 }, 270, 180) + } else { + path.addRect({ height, width: height * 4, y: 0, x: 0 }) + } + return path + }, [start, end, state]) - const path = useMemo(() => { - const path = Skia.Path.Make() - if ((start && end) || state == "today") { - path.addArc( - { height: height, width: height, y: 0, x: height * 1.5 }, - 90, - 360 - ) - } else if (start) { - path.addRect({ height: height, width: height * 2, y: 0, x: height * 2 }) - path.addArc( - { height: height, width: height, y: 0, x: height * 1.5 }, - 90, - 180 - ) - } else if (end) { - path.addRect({ height: height, width: height * 2, y: 0, x: 0 }) - path.addArc( - { height: height, width: height, y: 0, x: height * 1.5 }, - 270, - 180 - ) - } else { - path.addRect({ height: height, width: height * 4, y: 0, x: 0 }) - } - return path - }, [start, end, state]) - - return ( - onPress?.(date)} - onLongPress={() => onLongPress?.(date)} - > - - - - + return ( + onPress?.(date)} + onLongPress={() => onLongPress?.(date)} + > - - {String(children)} - - {isMarked && ( - - )} + + + + {String(children)} + + - - - ) -} + {marking?.marked && ( + + )} + + ) + } +) diff --git a/src/pages/Calendar.tsx b/src/pages/Calendar.tsx index 2e920758..ed4b2c0c 100644 --- a/src/pages/Calendar.tsx +++ b/src/pages/Calendar.tsx @@ -5,7 +5,7 @@ import { Pressable, View } from "react-native" import { palette, usePalette } from "utils/colors" import { StyleSheet } from "react-native" import { CalendarList } from "react-native-calendars" -import { useCallback, useContext, useMemo, useState } from "react" +import { useContext, useMemo, useState } from "react" import { daysOfWeekLetters, addMarkForEvents, @@ -19,13 +19,12 @@ import calendarIcon from "assets/calendar/calendar.svg" import capeIcon from "assets/calendar/cape_calendar.svg" import userIcon from "assets/calendar/user_calendar.svg" import { LoginContext } from "contexts/login" -import { DayProps } from "react-native-calendars/src/calendar/day" import { useApiCall } from "api/useApiCall" import { api } from "api" import { CalendarBottomSheet } from "components/Calendar/CalendarBottomSheet" export const CalendarPage: MainStackScreen<"Calendar"> = () => { - const { homeBackground, dotColor, isLight } = usePalette() + const { homeBackground, isLight } = usePalette() const { userInfo } = useContext(LoginContext) const { matricola } = userInfo?.careers?.[0] ?? {} @@ -256,10 +255,6 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { // } // }, [matricola]) - const DCC = useCallback< - (props: DayProps & { date?: DateData }) => JSX.Element - >(props => , []) - return ( = () => { staticHeader={true} scrollEnabled={true} scrollsToTop={false} - initialNumToRender={10} pastScrollRange={12} futureScrollRange={12} horizontal={true} @@ -374,7 +368,7 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { current={selectedDay} markingType="period" onMonthChange={date => setMonthDateData(date)} - dayComponent={DCC} + dayComponent={DayComponentCustom} /> Date: Sat, 4 May 2024 08:11:38 +0200 Subject: [PATCH 29/31] correct markings for selected day and today --- .../Calendar/DayComponentCustom.tsx | 24 +++++++++++++++---- src/pages/Calendar.tsx | 9 ++++--- src/utils/{calendar.tsx => calendar.ts} | 11 +++++++++ 3 files changed, 35 insertions(+), 9 deletions(-) rename src/utils/{calendar.tsx => calendar.ts} (99%) diff --git a/src/components/Calendar/DayComponentCustom.tsx b/src/components/Calendar/DayComponentCustom.tsx index 337f4e62..b5e663bb 100644 --- a/src/components/Calendar/DayComponentCustom.tsx +++ b/src/components/Calendar/DayComponentCustom.tsx @@ -4,6 +4,7 @@ import { DayProps } from "react-native-calendars/src/calendar/day" import { Text } from "components/Text" import { Canvas, Path, Skia } from "@shopify/react-native-skia" import { DateData } from "react-native-calendars" +import { palette } from "utils/colors" const height = 30 @@ -17,25 +18,32 @@ export const DayComponentCustom: FC = memo( state, children, }) { + const isToday = state === "today" + const isSelected = marking?.selected ?? false + const isInsidePeriod = marking?.color !== undefined // if inside period, color is defined const start = marking?.startingDay ?? false const end = marking?.endingDay ?? false const color = marking?.color ?? "transparent" const path = useMemo(() => { const path = Skia.Path.Make() - if ((start && end) || state == "today") { + if ((start && end) || isToday || !isInsidePeriod) { + // still a circle if today or not inside period path.addArc({ height, width: height, y: 0, x: height * 1.5 }, 90, 360) } else if (start) { + // only start, draw half circle path.addRect({ height, width: height * 2, y: 0, x: height * 2 }) path.addArc({ height, width: height, y: 0, x: height * 1.5 }, 90, 180) } else if (end) { + // only end, draw half circle path.addRect({ height, width: height * 2, y: 0, x: 0 }) path.addArc({ height, width: height, y: 0, x: height * 1.5 }, 270, 180) } else { + // inside period, draw rectangle path.addRect({ height, width: height * 4, y: 0, x: 0 }) } return path - }, [start, end, state]) + }, [start, end, isToday, isInsidePeriod]) return ( = memo( > @@ -76,7 +84,15 @@ export const DayComponentCustom: FC = memo( }} > {String(children)} diff --git a/src/pages/Calendar.tsx b/src/pages/Calendar.tsx index ed4b2c0c..9a82e8fa 100644 --- a/src/pages/Calendar.tsx +++ b/src/pages/Calendar.tsx @@ -10,6 +10,7 @@ import { daysOfWeekLetters, addMarkForEvents, addMarkForPeriods, + addMarkForSelectedDate, } from "utils/calendar" import { DayComponentCustom } from "components/Calendar/DayComponentCustom" import { DateData, MarkedDates } from "react-native-calendars/src/types" @@ -54,10 +55,11 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { const markedDates = useMemo(() => { let markedDates = {} + markedDates = addMarkForSelectedDate(markedDates, selectedDay) markedDates = addMarkForEvents(markedDates, events) markedDates = addMarkForPeriods(markedDates, []) return markedDates - }, [events]) + }, [selectedDay, events]) // I thought memoizing would improve performance, but it appears to be still very slow!! // const scrollMonths = useMemo(() => { @@ -351,9 +353,7 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { }, }, }} - onDayPress={day => { - setSelectedDay(day.dateString) - }} + onDayPress={day => setSelectedDay(day.dateString)} style={{ marginTop: 176, height: 270, @@ -365,7 +365,6 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { hideExtraDays={true} showSixWeeks={true} hideDayNames={true} - current={selectedDay} markingType="period" onMonthChange={date => setMonthDateData(date)} dayComponent={DayComponentCustom} diff --git a/src/utils/calendar.tsx b/src/utils/calendar.ts similarity index 99% rename from src/utils/calendar.tsx rename to src/utils/calendar.ts index 7f33d169..73dd0e63 100644 --- a/src/utils/calendar.tsx +++ b/src/utils/calendar.ts @@ -176,6 +176,17 @@ const calendarPeriods: CalendarPeriod[] = [ }, ] +export function addMarkForSelectedDate( + markedDates: MarkedDates, + date: string +): MarkedDates { + markedDates[date] = { + ...markedDates[date], + selected: true, + } + return markedDates +} + export function addMarkForEvents( markedDates: MarkedDates, events: Event[] | null From 8cdcff5eae58ea83fa1775505f93ce73377f3a1e Mon Sep 17 00:00:00 2001 From: Tommaso Morganti Date: Sat, 4 May 2024 08:31:33 +0200 Subject: [PATCH 30/31] formatDateOnlyString function --- src/components/Calendar/SingleMonth.tsx | 7 +++---- src/components/Home/Highlights/HighlightsManager.tsx | 3 ++- src/pages/Calendar.tsx | 9 ++++----- src/utils/calendar.ts | 3 ++- src/utils/functions.ts | 10 ++++++++++ src/utils/timetable.ts | 3 ++- 6 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/components/Calendar/SingleMonth.tsx b/src/components/Calendar/SingleMonth.tsx index 299a3680..69165374 100644 --- a/src/components/Calendar/SingleMonth.tsx +++ b/src/components/Calendar/SingleMonth.tsx @@ -3,6 +3,7 @@ import { View, ViewStyle } from "react-native" import { Calendar } from "react-native-calendars" import { useCurrentLanguage } from "utils/language" import { monthsIt, monthsEn, daysOfWeekLetters } from "utils/calendar" +import { formatDateOnlyString } from "utils/functions" import { usePalette } from "utils/colors" import { Text } from "components/Text" import { DateData, MarkedDates } from "react-native-calendars/src/types" @@ -25,7 +26,7 @@ export const SingleMonth: FC = props => { const DCC = useCallback< (props: DayProps & { date?: DateData }) => JSX.Element - >(props => , []) + >(props => , []) return ( = props => { dayTextColor: "#fff", weekVerticalMargin: 2, }} - initialDate={new Date(props.year, props.month, 2) - .toISOString() - .slice(0, 10)} + initialDate={formatDateOnlyString(new Date(props.year, props.month, 2))} disableMonthChange={true} customHeaderTitle={undefined} hideExtraDays={true} diff --git a/src/components/Home/Highlights/HighlightsManager.tsx b/src/components/Home/Highlights/HighlightsManager.tsx index 225b80ab..cfada12c 100644 --- a/src/components/Home/Highlights/HighlightsManager.tsx +++ b/src/components/Home/Highlights/HighlightsManager.tsx @@ -7,6 +7,7 @@ import { api } from "api" import { NotificationCenter } from "notifications/NotificationCenter" import { extractAllEvents } from "utils/notifications" import { useApiCall } from "api/useApiCall" +import { formatDateOnlyString } from "utils/functions" const notificationCenter = NotificationCenter.getInstance() @@ -19,7 +20,7 @@ export const HighlightsManager: FC = () => { const { loggedIn, userInfo } = useContext(LoginContext) const { matricola } = userInfo?.careers?.[0] ?? {} - const startDate = new Date().toISOString().substring(0, 10) + const startDate = formatDateOnlyString() const [events] = useApiCall( api.events.getEvents, { diff --git a/src/pages/Calendar.tsx b/src/pages/Calendar.tsx index 9a82e8fa..b9012dd2 100644 --- a/src/pages/Calendar.tsx +++ b/src/pages/Calendar.tsx @@ -12,6 +12,7 @@ import { addMarkForPeriods, addMarkForSelectedDate, } from "utils/calendar" +import { formatDateOnlyString } from "utils/functions" import { DayComponentCustom } from "components/Calendar/DayComponentCustom" import { DateData, MarkedDates } from "react-native-calendars/src/types" import { Text } from "components/Text" @@ -33,19 +34,17 @@ export const CalendarPage: MainStackScreen<"Calendar"> = () => { const [monthDateData, setMonthDateData] = useState({ day: new Date().getDate(), timestamp: Date.now(), - dateString: new Date().toISOString().slice(0, 10), + dateString: formatDateOnlyString(), month: new Date().getMonth() + 1, year: new Date().getFullYear(), }) - const [selectedDay, setSelectedDay] = useState( - new Date().toISOString().slice(0, 10) - ) + const [selectedDay, setSelectedDay] = useState(formatDateOnlyString()) const [events] = useApiCall( api.events.getEvents, { matricola: matricola ?? "", - startDate: new Date(2024, 2, 1).toISOString().substring(0, 10), + startDate: formatDateOnlyString(new Date(monthDateData.timestamp)), nEvents: 1000, }, [matricola], diff --git a/src/utils/calendar.ts b/src/utils/calendar.ts index 73dd0e63..cf9d4b19 100644 --- a/src/utils/calendar.ts +++ b/src/utils/calendar.ts @@ -23,6 +23,7 @@ import starEyesSvg from "assets/calendar/emoticons/star_eyes.svg" import { api } from "api" import { Event } from "api/collections/event" import { NotificationCenter } from "notifications/NotificationCenter" +import { formatDateOnlyString } from "./functions" export const purpleBerry = "rgba(98, 96, 166, 1)" @@ -421,7 +422,7 @@ export class CalendarSingletonWrapper const events: Event[] = await api.events.getEvents({ matricola: this._matricola, - startDate: new Date().toISOString().substring(0, 10), + startDate: formatDateOnlyString(), nEvents: 20, }) diff --git a/src/utils/functions.ts b/src/utils/functions.ts index f50a31eb..9680f785 100644 --- a/src/utils/functions.ts +++ b/src/utils/functions.ts @@ -58,3 +58,13 @@ export function capitalize(str: string, notCapitalize = 0): string { } return arr.join(" ") } + +/** + * Formats a date to a string with format YYYY-MM-DD + * @param date The date to be formatted, if not provided the current date is used + * @returns string with format YYYY-MM-DD + */ +export function formatDateOnlyString(date?: Date): string { + if (!date) date = new Date() + return date.toISOString().split("T")[0] +} diff --git a/src/utils/timetable.ts b/src/utils/timetable.ts index fd4b1cc8..1853ad2b 100644 --- a/src/utils/timetable.ts +++ b/src/utils/timetable.ts @@ -4,6 +4,7 @@ import { Event } from "api/collections/event" import * as FileSystem from "expo-file-system" import { EventType } from "./events" import { EventEmitter } from "events" +import { formatDateOnlyString } from "./functions" /** * A more systematic approach for managing margins, change here, change everywhere. @@ -633,7 +634,7 @@ export class TimetableDeducer extends EventEmitter { const events = await api.events.getEvents({ matricola: this._matricola ?? "", - startDate: startDate.toISOString().substring(0, 10), + startDate: formatDateOnlyString(startDate), nEvents: 200, }) From 58fdd07ea3658e58d2a6f2c03d0854b80b87e933 Mon Sep 17 00:00:00 2001 From: Tommaso Morganti Date: Tue, 7 May 2024 02:09:20 +0200 Subject: [PATCH 31/31] dynamic call poc --- src/api/collections/event.ts | 13 ++++- .../Calendar/CalendarDailyEvents.tsx | 51 +++++++++---------- src/pages/Calendar.tsx | 5 +- 3 files changed, 40 insertions(+), 29 deletions(-) diff --git a/src/api/collections/event.ts b/src/api/collections/event.ts index 1ff465db..1bd971fc 100644 --- a/src/api/collections/event.ts +++ b/src/api/collections/event.ts @@ -102,7 +102,12 @@ const client = HttpClient.getInstance() export const events = { getEvents( - params: { matricola: string; startDate: string; nEvents: number }, + params: { + matricola: string + startDate: string + nEvents: number + endDate?: string + }, options?: RequestOptions ) { const url = "/agenda/api/me/" + params.matricola + "/events" @@ -110,7 +115,11 @@ export const events = { url, method: "GET", authType: AuthType.POLIMI, - params: { start_date: params.startDate, n_events: params.nEvents }, + params: { + start_date: params.startDate, + n_events: params.nEvents, + end_date: params.endDate, + }, ...options, }) return mapAxiosRequest(request, response => response) diff --git a/src/components/Calendar/CalendarDailyEvents.tsx b/src/components/Calendar/CalendarDailyEvents.tsx index 5c3ddbaf..c42f8058 100644 --- a/src/components/Calendar/CalendarDailyEvents.tsx +++ b/src/components/Calendar/CalendarDailyEvents.tsx @@ -1,7 +1,6 @@ import { FC } from "react" import { View, ScrollView, StyleSheet, Pressable } from "react-native" import { - CalendarEvent, CalendarEventStatus, formatHoursFromDate, getBackColorFromEventStatus, @@ -9,7 +8,6 @@ import { getTextFromEventStatus, monthsEn, monthsIt, - shiftedEventStatus, } from "utils/calendar" import { Text } from "components/Text" import { usePalette } from "utils/colors" @@ -19,18 +17,19 @@ import tickSvg from "assets/freeClassrooms/tick.svg" import { DottedLine } from "./DottedLine" import { CalendarButton } from "./Button" import { useTranslation } from "react-i18next" +import { Event } from "api/collections/event" interface CalendarDailyEventsProps { - events: CalendarEvent[] + events: Event[] dayString: string - lan: string onChangeStatusEvent: (id: string, status: CalendarEventStatus) => void goToAddEvent: () => void } export const CalendarDailyEvents: FC = props => { - const { events, lan, dayString } = props + const { events, dayString } = props + const { t, i18n } = useTranslation("calendar") const date = new Date(dayString) @@ -38,14 +37,13 @@ export const CalendarDailyEvents: FC = props => { const monthNumber = date.getMonth() - const month = lan === "it" ? monthsIt[monthNumber] : monthsEn[monthNumber] + const month = + i18n.language == "it" ? monthsIt[monthNumber] : monthsEn[monthNumber] const year = date.getFullYear() const { isLight, homeBackground, palette } = usePalette() - const { t } = useTranslation("calendar") - return ( = props => { {events.map((event, index) => { return ( - props.onChangeStatusEvent( - event.id, - shiftedEventStatus(event.status) - ) - } + key={event.event_id} + onPress={() => { + // props.onChangeStatusEvent( + // event.event_id, + // shiftedEventStatus(event.status) + // ) + }} > = props => { marginTop: 12, }} > - + = props => { { color: isLight ? homeBackground : "#fff" }, ]} > - {lan === "it" - ? event.title - : event.titleEn ?? event.title} + {i18n.language === "it" ? event.title.it : event.title.en} = props => { { color: isLight ? homeBackground : "#fff" }, ]} > - {formatHoursFromDate(event.start)} - {event.polimiEventFields?.room?.acronym_dn - ? ` | ${event.polimiEventFields?.room?.acronym_dn}` + {formatHoursFromDate(event.date_start)} + {event.room?.acronym_dn + ? ` | ${event.room?.acronym_dn}` : ""} @@ -159,7 +155,7 @@ export const CalendarDailyEvents: FC = props => { alignItems: "center", flexDirection: "row", backgroundColor: getBackColorFromEventStatus( - event.status, + CalendarEventStatus.INITIAL, isLight ), }} @@ -170,11 +166,14 @@ export const CalendarDailyEvents: FC = props => { { color: isLight ? "#fff" : palette.darker }, ]} > - {getTextFromEventStatus(event.status, lan)} + {getTextFromEventStatus( + CalendarEventStatus.INITIAL, + i18n.language + )} - {event.status == CalendarEventStatus.INITIAL ? ( + {event == event ? ( = props => { backgroundColor: isLight ? "#F2F2F2" : "#D7D9E2", }} /> - ) : event.status === CalendarEventStatus.PROGRESS ? ( + ) : event == event ? ( = () => { { matricola: matricola ?? "", startDate: formatDateOnlyString(new Date(monthDateData.timestamp)), + endDate: formatDateOnlyString( + new Date(monthDateData.timestamp + 31 * 24 * 60 * 60 * 1000) + ), nEvents: 1000, }, - [matricola], + [matricola, monthDateData], {}, matricola === undefined )