From bc665f8e530b424703e16efcae9451bf5112397d Mon Sep 17 00:00:00 2001 From: vinaybadgujar102 Date: Mon, 1 Jul 2024 12:57:16 +0530 Subject: [PATCH 1/2] refactor: use enum for local storage keys --- src/components/BottomNavbar/BottomNavbar.tsx | 3 ++- .../ShareGoalModal/AddContactModal.tsx | 5 +++-- src/components/Header/HeaderBtn.tsx | 5 +++-- src/components/Header/Settings.tsx | 3 ++- .../HeaderDashboard/LandingHeader.tsx | 9 +++++---- src/components/LanguageChoice/LanguagesList.tsx | 3 ++- src/constants/localStorageKeys.ts | 15 +++++++++++++++ src/hooks/useApp.tsx | 17 +++++++++-------- src/models/db.ts | 5 +++-- src/pages/FAQPage/FAQPage.tsx | 8 ++++---- src/pages/InvitePage/InvitePage.tsx | 7 ++++--- src/services/contact.service.ts | 7 +++++-- src/store/DarkModeState.ts | 3 ++- src/store/LanguageSelectionState.ts | 5 ++++- src/store/ThemeState.ts | 3 ++- src/store/index.ts | 5 +++-- src/utils/index.ts | 5 +++-- 17 files changed, 71 insertions(+), 37 deletions(-) create mode 100644 src/constants/localStorageKeys.ts diff --git a/src/components/BottomNavbar/BottomNavbar.tsx b/src/components/BottomNavbar/BottomNavbar.tsx index 6c46f6026..ebd78f68e 100644 --- a/src/components/BottomNavbar/BottomNavbar.tsx +++ b/src/components/BottomNavbar/BottomNavbar.tsx @@ -13,6 +13,7 @@ import GlobalAddBtn from "@components/GlobalAddBtn"; import "./BottomNavbar.scss"; import Icon from "@src/common/Icon"; +import { LocalStorageKeys } from "@src/constants/localStorageKeys"; const BottomNavbar = ({ title }: { title: string }) => { const { t } = useTranslation(); @@ -34,7 +35,7 @@ const BottomNavbar = ({ title }: { title: string }) => { choice = 8; } const newTheme = { ...theme, [darkModeStatus ? "dark" : "light"]: choice }; - localStorage.setItem("theme", JSON.stringify(newTheme)); + localStorage.setItem(LocalStorageKeys.THEME, JSON.stringify(newTheme)); setTheme({ ...newTheme }); }; diff --git a/src/components/GoalsComponents/ShareGoalModal/AddContactModal.tsx b/src/components/GoalsComponents/ShareGoalModal/AddContactModal.tsx index c07a5c27a..0f4a9f3a4 100644 --- a/src/components/GoalsComponents/ShareGoalModal/AddContactModal.tsx +++ b/src/components/GoalsComponents/ShareGoalModal/AddContactModal.tsx @@ -7,6 +7,7 @@ import { darkModeState, displayToast } from "@src/store"; import React, { useState } from "react"; import { useRecoilValue, useSetRecoilState } from "recoil"; import ZModal from "@src/common/ZModal"; +import { LocalStorageKeys } from "@src/constants/localStorageKeys"; interface AddContactModalProps { showAddContactModal: boolean; @@ -30,9 +31,9 @@ const AddContactModal: React.FC = ({ showAddContactModal } const { relId } = res.response; await addContact(newContact?.contactName, relId, "sender"); setNewContact({ ...newContact, relId }); - const defaultPartner = localStorage.getItem("defaultPartner"); + const defaultPartner = localStorage.getItem(LocalStorageKeys.DEFAULT_PARTNER); if (!defaultPartner) { - localStorage.setItem("defaultPartner", relId); + localStorage.setItem(LocalStorageKeys.DEFAULT_PARTNER, relId); } link = `${window.location.origin}/invite/${res.response.relId}`; } else { diff --git a/src/components/Header/HeaderBtn.tsx b/src/components/Header/HeaderBtn.tsx index e0332ec41..9fcbd3e94 100644 --- a/src/components/Header/HeaderBtn.tsx +++ b/src/components/Header/HeaderBtn.tsx @@ -2,6 +2,7 @@ import React from "react"; import { displayToast, darkModeState } from "@src/store"; import { useLocation, useNavigate } from "react-router-dom"; import { useSetRecoilState, useRecoilState } from "recoil"; +import { LocalStorageKeys } from "@src/constants/localStorageKeys"; import Settings from "./Settings"; const HeaderBtn = ({ path, alt }: { path: string; alt: string }) => { @@ -16,10 +17,10 @@ const HeaderBtn = ({ path, alt }: { path: string; alt: string }) => { } else if (alt === "zinzen search") { navigate("/MyGoals", { state: { ...state, displaySearch: true } }); } else if (alt === "light mode") { - localStorage.setItem("darkMode", darkModeStatus ? "off" : "on"); + localStorage.setItem(LocalStorageKeys.DARK_MODE, darkModeStatus ? "off" : "on"); setDarkModeStatus(!darkModeStatus); } else if (alt === "dark mode") { - localStorage.setItem("darkMode", darkModeStatus ? "off" : "on"); + localStorage.setItem(LocalStorageKeys.DARK_MODE, darkModeStatus ? "off" : "on"); setDarkModeStatus(!darkModeStatus); } }; diff --git a/src/components/Header/Settings.tsx b/src/components/Header/Settings.tsx index 292dd220f..fec698899 100644 --- a/src/components/Header/Settings.tsx +++ b/src/components/Header/Settings.tsx @@ -8,6 +8,7 @@ import verticalDots from "@assets/images/verticalDots.svg"; import { darkModeState } from "@src/store"; import { themeState } from "@src/store/ThemeState"; import useGlobalStore from "@src/hooks/useGlobalStore"; +import { LocalStorageKeys } from "@src/constants/localStorageKeys"; const Settings = () => { const { t } = useTranslation(); @@ -21,7 +22,7 @@ const Settings = () => { const dropdownOptions = [t("donate"), t("feedback"), t("blog"), t("backup"), t("changeLanguage"), t("changeTheme")]; const toggleDarkModeStatus = () => { - localStorage.setItem("darkMode", darkModeStatus ? "off" : "on"); + localStorage.setItem(LocalStorageKeys.DARK_MODE, darkModeStatus ? "off" : "on"); setDarkModeStatus(!darkModeStatus); }; diff --git a/src/components/HeaderDashboard/LandingHeader.tsx b/src/components/HeaderDashboard/LandingHeader.tsx index f1e188b84..5092aa7b3 100644 --- a/src/components/HeaderDashboard/LandingHeader.tsx +++ b/src/components/HeaderDashboard/LandingHeader.tsx @@ -13,6 +13,7 @@ import { displaySidebar } from "@src/store/SidebarState"; import "@translations/i18n"; import "./HeaderDashboard.scss"; +import { LocalStorageKeys } from "@src/constants/localStorageKeys"; export const LandingHeader = ({ avatar }: { avatar: string | null }) => { const navigate = useNavigate(); @@ -28,10 +29,10 @@ export const LandingHeader = ({ avatar }: { avatar: string | null }) => { alt="Back arrow" id="main-header-homeLogo" onClick={() => { - if (localStorage.getItem("checkedIn") !== "yes") { - localStorage.setItem("checkedIn", "yes"); - const invite = localStorage.getItem("pendingInvite"); - localStorage.removeItem("pendingInvite"); + if (localStorage.getItem(LocalStorageKeys.CHECKED_IN) !== "yes") { + localStorage.setItem(LocalStorageKeys.CHECKED_IN, "yes"); + const invite = localStorage.getItem(LocalStorageKeys.PENDING_INVITE); + localStorage.removeItem(LocalStorageKeys.PENDING_INVITE); if (invite && invite !== "none") { navigate(`/invite/${invite}`); } else { diff --git a/src/components/LanguageChoice/LanguagesList.tsx b/src/components/LanguageChoice/LanguagesList.tsx index 2d0c9dbf7..55f2770ad 100644 --- a/src/components/LanguageChoice/LanguagesList.tsx +++ b/src/components/LanguageChoice/LanguagesList.tsx @@ -5,6 +5,7 @@ import { useRecoilState } from "recoil"; import { ILanguageListProps, ILanguage } from "@src/Interfaces/ILanguage"; import { vibrateWorks } from "@src/constants/vibrateCheck"; import { languageSelectionState } from "@src/store"; +import { LocalStorageKeys } from "@src/constants/localStorageKeys"; export const LanguagesList = (props: ILanguageListProps) => { const { languages, navigationCallback, type, hideSelected } = props; @@ -17,7 +18,7 @@ export const LanguagesList = (props: ILanguageListProps) => { } setIsLanguageChosen(langId); i18n.changeLanguage(langId); - localStorage.setItem("language", JSON.stringify(langId)); + localStorage.setItem(LocalStorageKeys.LANGUAGE, langId); if (type === "fragment" && navigationCallback) navigationCallback("/ZinZenFAQ"); else window.history.back(); }; diff --git a/src/constants/localStorageKeys.ts b/src/constants/localStorageKeys.ts new file mode 100644 index 000000000..118657b15 --- /dev/null +++ b/src/constants/localStorageKeys.ts @@ -0,0 +1,15 @@ +/* eslint-disable no-shadow */ + +export enum LocalStorageKeys { + THEME = "theme", + DEFAULT_PARTNER = "defaultPartner", + DARK_MODE = "darkMode", + CHECKED_IN = "checkedIn", + LANGUAGE = "language", + INSTALL_ID = "installId", + CONFIRMATION_STATE = "confirmationState", + LAST_REFRESH = "lastRefresh", + DEXIE_VERSION = "dexieVersion", + PENDING_INVITE = "pendingInvite", + LAST_PROCESSED_TIMESTAMP = "lastProcessedTimestamp", +} diff --git a/src/hooks/useApp.tsx b/src/hooks/useApp.tsx index 004f6cae1..afd2d19f4 100644 --- a/src/hooks/useApp.tsx +++ b/src/hooks/useApp.tsx @@ -13,8 +13,9 @@ import { getContactSharedGoals, shareGoalWithContact } from "@src/services/conta import { updateAllUnacceptedContacts, getContactByRelId, clearTheQueue } from "@src/api/ContactsAPI"; import { useSetRecoilState, useRecoilValue, useRecoilState } from "recoil"; import { scheduledHintCalls } from "@src/api/HintsAPI/ScheduledHintCall"; +import { LocalStorageKeys } from "@src/constants/localStorageKeys"; -const langFromStorage = localStorage.getItem("language")?.slice(1, -1); +const langFromStorage = localStorage.getItem(LocalStorageKeys.LANGUAGE)?.slice(1, -1); const exceptionRoutes = ["/", "/invest", "/feedback", "/donate"]; function useApp() { @@ -114,11 +115,11 @@ function useApp() { }); } }; - const installId = localStorage.getItem("installId"); + const installId = localStorage.getItem(LocalStorageKeys.INSTALL_ID); if (!installId) { - localStorage.setItem("installId", uuidv4()); - localStorage.setItem("darkMode", "on"); - localStorage.setItem("theme", JSON.stringify(getTheme())); + localStorage.setItem(LocalStorageKeys.INSTALL_ID, uuidv4()); + localStorage.setItem(LocalStorageKeys.CHECKED_IN, "on"); + localStorage.setItem(LocalStorageKeys.THEME, JSON.stringify(getTheme())); } else { init(); } @@ -129,7 +130,7 @@ function useApp() { }, [langFromStorage]); useEffect(() => { - localStorage.setItem("confirmationState", JSON.stringify(confirmationState)); + localStorage.setItem(LocalStorageKeys.CONFIRMATION_STATE, JSON.stringify(confirmationState)); }, [confirmationState]); // Check for missed hint calls @@ -167,11 +168,11 @@ function useApp() { }, []); useEffect(() => { - const lastRefresh = localStorage.getItem("lastRefresh"); + const lastRefresh = localStorage.getItem(LocalStorageKeys.LAST_REFRESH); const today = new Date().toLocaleDateString(); if (lastRefresh !== today) { refreshTaskCollection().then(() => { - localStorage.setItem("lastRefresh", today); + localStorage.setItem(LocalStorageKeys.LAST_REFRESH, today); setLastAction("TaskCollectionRefreshed"); }); } diff --git a/src/models/db.ts b/src/models/db.ts index 2f0f1ea9d..376ea99b4 100755 --- a/src/models/db.ts +++ b/src/models/db.ts @@ -1,5 +1,6 @@ /* eslint-disable no-param-reassign */ import Dexie, { Table } from "dexie"; +import { LocalStorageKeys } from "@src/constants/localStorageKeys"; import { IFeelingItem } from "./FeelingItem"; import { GoalItem } from "./GoalItem"; import ContactItem from "./ContactItem"; @@ -14,8 +15,8 @@ import { dbStoreSchema, syncVersion } from "./dexie"; export const dexieVersion = 21; -const currentVersion = Number(localStorage.getItem("dexieVersion") || dexieVersion); -localStorage.setItem("dexieVersion", `${dexieVersion}`); +const currentVersion = Number(localStorage.getItem(LocalStorageKeys.DEXIE_VERSION) || dexieVersion); +localStorage.setItem(LocalStorageKeys.DEXIE_VERSION, `${dexieVersion}`); export class ZinZenDB extends Dexie { feelingsCollection!: Table; diff --git a/src/pages/FAQPage/FAQPage.tsx b/src/pages/FAQPage/FAQPage.tsx index 954aac0cc..02b265c35 100644 --- a/src/pages/FAQPage/FAQPage.tsx +++ b/src/pages/FAQPage/FAQPage.tsx @@ -12,6 +12,7 @@ import { useRecoilValue } from "recoil"; import { darkModeState } from "@src/store"; import "./FAQPage.scss"; import "@translations/i18n"; +import { LocalStorageKeys } from "@src/constants/localStorageKeys"; export const FAQPage = () => { const darkModeStatus = useRecoilValue(darkModeState); @@ -25,8 +26,8 @@ export const FAQPage = () => { ]; const handleClick = () => { - localStorage.setItem("checkedIn", "yes"); - const invite = localStorage.getItem("pendingInvite"); + localStorage.setItem(LocalStorageKeys.CHECKED_IN, "yes"); + const invite = localStorage.getItem(LocalStorageKeys.PENDING_INVITE); localStorage.removeItem("pendingInvite"); vibrateWorks ? navigator.vibrate(100) : null; if (invite && invite !== "none") { @@ -62,8 +63,7 @@ export const FAQPage = () => { ), }))} /> - diff --git a/src/pages/InvitePage/InvitePage.tsx b/src/pages/InvitePage/InvitePage.tsx index 2c5c08395..791a00691 100644 --- a/src/pages/InvitePage/InvitePage.tsx +++ b/src/pages/InvitePage/InvitePage.tsx @@ -7,6 +7,7 @@ import { addContact, getAllContacts } from "@src/api/ContactsAPI"; import { acceptRelationship } from "@src/services/contact.service"; import OnboardingLayout from "@src/layouts/OnboardingLayout"; import { displayPartnerModeTour } from "@src/store/TourState"; +import { LocalStorageKeys } from "@src/constants/localStorageKeys"; const InvitePage = () => { const navigate = useNavigate(); @@ -41,12 +42,12 @@ const InvitePage = () => { }; useEffect(() => { - const checkin = localStorage.getItem("checkedIn"); + const checkin = localStorage.getItem(LocalStorageKeys.CHECKED_IN); if (!checkin) { - localStorage.setItem("checkedIn", "no"); + localStorage.setItem(LocalStorageKeys.CHECKED_IN, "no"); } if (checkin !== "yes") { - localStorage.setItem("pendingInvite", window.location.href.split("invite/")[1]); + localStorage.setItem(LocalStorageKeys.PENDING_INVITE, window.location.href.split("invite/")[1]); navigate("/"); } }, []); diff --git a/src/services/contact.service.ts b/src/services/contact.service.ts index 93818b538..93995f8a5 100644 --- a/src/services/contact.service.ts +++ b/src/services/contact.service.ts @@ -1,3 +1,4 @@ +import { LocalStorageKeys } from "@src/constants/localStorageKeys"; import { GoalItem, IParticipant } from "@src/models/GoalItem"; import { typeOfChange } from "@src/models/InboxItem"; import { createContactRequest, getInstallId } from "@src/utils"; @@ -43,14 +44,16 @@ export const collaborateWithContact = async (relId: string, goal: GoalItem) => { }; export const getContactSharedGoals = async () => { - const lastProcessedTimestamp = new Date(Number(localStorage.getItem("lastProcessedTimestamp"))).toISOString(); + const lastProcessedTimestamp = new Date( + Number(localStorage.getItem(LocalStorageKeys.LAST_PROCESSED_TIMESTAMP)), + ).toISOString(); const url = "https://x7phxjeuwd4aqpgbde6f74s4ey0yobfi.lambda-url.eu-west-1.on.aws/"; const res = await createContactRequest(url, { method: "getMessages", installId: getInstallId(), ...(lastProcessedTimestamp ? { lastProcessedTimestamp } : {}), }); - localStorage.setItem("lastProcessedTimestamp", `${Date.now()}`); + localStorage.setItem(LocalStorageKeys.LAST_PROCESSED_TIMESTAMP, `${Date.now()}`); return res; }; diff --git a/src/store/DarkModeState.ts b/src/store/DarkModeState.ts index 8d5140e0c..e0bf02803 100644 --- a/src/store/DarkModeState.ts +++ b/src/store/DarkModeState.ts @@ -1,7 +1,8 @@ +import { LocalStorageKeys } from "@src/constants/localStorageKeys"; import { atom } from "recoil"; export const getDarkModeValue = () => { - const mode = localStorage.getItem("darkMode"); + const mode = localStorage.getItem(LocalStorageKeys.DARK_MODE); if (mode && (mode === "on" || mode === "off")) { return mode; } diff --git a/src/store/LanguageSelectionState.ts b/src/store/LanguageSelectionState.ts index d201ebd0c..da40cc116 100644 --- a/src/store/LanguageSelectionState.ts +++ b/src/store/LanguageSelectionState.ts @@ -1,6 +1,9 @@ +import { LocalStorageKeys } from "@src/constants/localStorageKeys"; import { atom } from "recoil"; export const languageSelectionState = atom({ key: "keyModalState", - default: localStorage.getItem("language") ? localStorage.getItem("language") : "No language chosen.", + default: localStorage.getItem(LocalStorageKeys.LANGUAGE) + ? localStorage.getItem(LocalStorageKeys.LANGUAGE) + : "No language chosen.", }); diff --git a/src/store/ThemeState.ts b/src/store/ThemeState.ts index f0d48f2e8..cc2da0a91 100644 --- a/src/store/ThemeState.ts +++ b/src/store/ThemeState.ts @@ -1,7 +1,8 @@ import { atom } from "recoil"; +import { LocalStorageKeys } from "@src/constants/localStorageKeys"; export const getTheme = () => { - const x = localStorage.getItem("theme"); + const x = localStorage.getItem(LocalStorageKeys.THEME); if (x && x.search(/^\{"light":\d,"dark":\d\}$/i) === 0) { return JSON.parse(x); } diff --git a/src/store/index.ts b/src/store/index.ts index 7e93b1b95..5007d41e8 100755 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -2,6 +2,7 @@ import { atom } from "recoil"; import { confirmActionState } from "@src/Interfaces/IPopupModals"; import ContactItem from "@src/models/ContactItem"; import { isJSONParsable } from "@src/utils/patterns"; +import { LocalStorageKeys } from "@src/constants/localStorageKeys"; import { darkModeState } from "./DarkModeState"; import { languageSelectionState } from "./LanguageSelectionState"; @@ -25,9 +26,9 @@ const defaultConfirmationObj: confirmActionState = { }, }; -if (isJSONParsable(localStorage.getItem("confirmationState"))) { +if (isJSONParsable(localStorage.getItem(LocalStorageKeys.CONFIRMATION_STATE))) { // @ts-ignore - const savedConfirmationState = JSON.parse(localStorage.getItem("confirmationService")); + const savedConfirmationState = JSON.parse(localStorage.getItem(LocalStorageKeys.CONFIRMATION_STATE)); defaultConfirmationObj.goal = { ...defaultConfirmationObj.goal, ...(savedConfirmationState?.goal || {}) }; defaultConfirmationObj.collaboration = { ...defaultConfirmationObj.collaboration, diff --git a/src/utils/index.ts b/src/utils/index.ts index 835efb996..1153a77b9 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -2,6 +2,7 @@ import { useTranslation } from "react-i18next"; import { GoalItem } from "@src/models/GoalItem"; import { languagesFullForms } from "@src/translations/i18n"; import i18next from "i18next"; +import { LocalStorageKeys } from "@src/constants/localStorageKeys"; export async function createContactRequest(url: string, body: object | null = null, method = "POST") { try { @@ -129,11 +130,11 @@ export function inheritParentProps(newGoal: GoalItem, parentGoal: GoalItem) { export const convertNumberToHr = (hr: number) => `${hr > 9 ? "" : "0"}${hr} : 00`; export function getInstallId() { - return localStorage.getItem("installId"); + return localStorage.getItem(LocalStorageKeys.INSTALL_ID); } export function getSelectedLanguage() { - const langFromStorage = localStorage.getItem("language")?.slice(1, -1); + const langFromStorage = localStorage.getItem(LocalStorageKeys.LANGUAGE)?.slice(1, -1); const lang = langFromStorage ? languagesFullForms[langFromStorage] : languagesFullForms.en; return lang; } From f8ff7d6ee3bcffea7109e8251b7ac7554a68a0e9 Mon Sep 17 00:00:00 2001 From: vinaybadgujar102 Date: Mon, 1 Jul 2024 13:43:44 +0530 Subject: [PATCH 2/2] chore: add TypeScript declarations for image imports --- src/pages/FAQPage/FAQPage.tsx | 2 +- src/react-app-env.t.ts | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/pages/FAQPage/FAQPage.tsx b/src/pages/FAQPage/FAQPage.tsx index 02b265c35..e78acc8dc 100644 --- a/src/pages/FAQPage/FAQPage.tsx +++ b/src/pages/FAQPage/FAQPage.tsx @@ -28,7 +28,7 @@ export const FAQPage = () => { const handleClick = () => { localStorage.setItem(LocalStorageKeys.CHECKED_IN, "yes"); const invite = localStorage.getItem(LocalStorageKeys.PENDING_INVITE); - localStorage.removeItem("pendingInvite"); + localStorage.removeItem(LocalStorageKeys.PENDING_INVITE); vibrateWorks ? navigator.vibrate(100) : null; if (invite && invite !== "none") { navigate(`/invite/${invite}`); diff --git a/src/react-app-env.t.ts b/src/react-app-env.t.ts index 7073a6082..df1bdd0f7 100644 --- a/src/react-app-env.t.ts +++ b/src/react-app-env.t.ts @@ -1,2 +1,6 @@ // declare module "*.mp3"; +declare module "*.svg"; +declare module "*.png"; +declare module "*.jpeg"; +declare module "*.jpg";