From 7ed8cade332590fa10ef5860f37df421dd09951b Mon Sep 17 00:00:00 2001 From: Sunday Ogbonna Date: Fri, 27 Jan 2023 19:47:40 +0100 Subject: [PATCH 01/25] feat: add profile update api function --- lib/hooks/update-user.ts | 26 ++++++++++++++++++++++++++ lib/hooks/useFetchUser.ts | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 lib/hooks/update-user.ts diff --git a/lib/hooks/update-user.ts b/lib/hooks/update-user.ts new file mode 100644 index 000000000..838f89c21 --- /dev/null +++ b/lib/hooks/update-user.ts @@ -0,0 +1,26 @@ +interface useUpdateUserProps { + token: string; + data: { email?: string; interests?: string[] }; + params?: string +} + +const baseUrl = process.env.NEXT_PUBLIC_API_URL; +const UpdateUser = async ({ token, data, params }: useUpdateUserProps) => { + try { + const res = await fetch(`${baseUrl}/auth/profile/${params || ""}`, { + headers: { Accept: "application/json", "Content-Type": "application/json", Authorization: `Bearer ${token}` }, + method: "PATCH", + body: JSON.stringify({ ...data }) + }); + + if (res.status === 200) { + return res; + } else { + return res; + } + } catch (e) { + console.log(e); + } +}; + +export { UpdateUser }; diff --git a/lib/hooks/useFetchUser.ts b/lib/hooks/useFetchUser.ts index 58fc92dd8..60948f7fb 100644 --- a/lib/hooks/useFetchUser.ts +++ b/lib/hooks/useFetchUser.ts @@ -1,7 +1,7 @@ import publicApiFetcher from "lib/utils/public-api-fetcher"; import useSWR, { Fetcher } from "swr"; -interface UserResponse extends DbUser {} +export interface UserResponse extends DbUser {} const useFetchUser = (username: string) => { const { data, error } = useSWR( username ? `users/${username}` : null, From 5649bdecb1b89ffc4c1cc6a97503242a068462bb Mon Sep 17 00:00:00 2001 From: Sunday Ogbonna Date: Fri, 27 Jan 2023 19:48:10 +0100 Subject: [PATCH 02/25] refactor: minor updates --- components/atoms/Avatar/avatar.tsx | 2 +- components/atoms/TextInput/text-input.tsx | 24 +++++++++++++---------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/components/atoms/Avatar/avatar.tsx b/components/atoms/Avatar/avatar.tsx index 034bc6559..26baee1ea 100644 --- a/components/atoms/Avatar/avatar.tsx +++ b/components/atoms/Avatar/avatar.tsx @@ -28,7 +28,7 @@ const Avatar = (props: AvatarProps): JSX.Element => { case "string": return ; case "number": - return ; + return ; default: return invalid avatar size props!!!; diff --git a/components/atoms/TextInput/text-input.tsx b/components/atoms/TextInput/text-input.tsx index 0494e4811..d62d3d43f 100644 --- a/components/atoms/TextInput/text-input.tsx +++ b/components/atoms/TextInput/text-input.tsx @@ -45,7 +45,7 @@ const TextInput = ({ "flex-1 px-3 text-light-slate-12 bg-white shadow-input border transition rounded-lg py-1 flex items-center", borderless && "!border-none", state === "invalid" ? " focus-within:border-light-red-10 " : "focus-within:border-light-orange-9 ", - disabled && "bg-light-slate-3", + disabled && "bg-light-slate-3 text-light-slate-6", classNames )} > @@ -57,18 +57,22 @@ const TextInput = ({ placeholder={placeholder || ""} onChange={onChange} value={value} - className={`flex-1 focus:outline-none ${classNames}`} + className={`flex-1 focus:outline-none ${classNames} ${disabled && "bg-light-slate-3 text-light-slate-9"}`} autoFocus={autoFocus} disabled={disabled} /> - {state === "valid" ? ( - - ) : !!value ? ( - handleResetInput()}> - - - ) : ( - "" + {!disabled && ( + <> + {state === "valid" ? ( + + ) : !!value ? ( + handleResetInput()}> + + + ) : ( + "" + )} + )} From d1f7b7b4b6b03cb5cf122c490dbb99f9ba72c3b3 Mon Sep 17 00:00:00 2001 From: Sunday Ogbonna Date: Fri, 27 Jan 2023 19:48:28 +0100 Subject: [PATCH 03/25] feat: add settings na d profile route --- .../molecules/AuthSection/auth-section.tsx | 26 +++++++- .../UserSettingsPage/user-settings-page.tsx | 64 +++++++++++++++++-- pages/user/settings.tsx | 13 ++++ 3 files changed, 96 insertions(+), 7 deletions(-) create mode 100644 pages/user/settings.tsx diff --git a/components/molecules/AuthSection/auth-section.tsx b/components/molecules/AuthSection/auth-section.tsx index 337616564..d07546fa1 100644 --- a/components/molecules/AuthSection/auth-section.tsx +++ b/components/molecules/AuthSection/auth-section.tsx @@ -9,10 +9,11 @@ import DropdownList from "../DropdownList/dropdown-list"; import Text from "components/atoms/Typography/text"; import { Divider } from "@supabase/ui"; import useSupabaseAuth from "../../../lib/hooks/useSupabaseAuth"; -import { FiLogOut } from "react-icons/fi"; +import { FiLogOut, FiSettings } from "react-icons/fi"; import GitHubIcon from "img/icons/github-icon.svg"; import Icon from "components/atoms/Icon/icon"; import useSession from "lib/hooks/useSession"; +import Link from "next/link"; const AuthSection: React.FC = ({}) => { const { signIn, signOut, user } = useSupabaseAuth(); @@ -20,6 +21,29 @@ const AuthSection: React.FC = ({}) => { const authMenu = { authed: [ + + + {user?.user_metadata.user_name} + , + + + Settings + , await signOut()} key="authorized" diff --git a/components/organisms/UserSettingsPage/user-settings-page.tsx b/components/organisms/UserSettingsPage/user-settings-page.tsx index 5af5caef0..c9505a6b5 100644 --- a/components/organisms/UserSettingsPage/user-settings-page.tsx +++ b/components/organisms/UserSettingsPage/user-settings-page.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useState , useEffect} from "react"; import Button from "components/atoms/Button/button"; import Checkbox from "components/atoms/Checkbox/checkbox"; @@ -7,11 +7,28 @@ import Title from "components/atoms/Typography/title"; import Select from "components/atoms/Select/select"; import SelectOption from "components/atoms/Select/select-option"; import LanguagePill from "components/atoms/LanguagePill/LanguagePill"; +import useSupabaseAuth from "lib/hooks/useSupabaseAuth"; +import { UpdateUser } from "lib/hooks/update-user"; const UserSettingsPage = () => { + let error; + const { user, sessionToken } = useSupabaseAuth(); + const [email, setEmail] = useState(user?.email); const [selectedInterest, setSelectedInterest] = useState([]); const interestArray = ["javascript", "python", "rust", "ML", "AI", "react"]; + const validateEmail = (email: string) => { + return String(email) + .toLowerCase() + .match( + /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ + ); + }; + + useEffect(()=>{ + if(user) setEmail(user.email); + },[user]); + const handleSelectInterest = (interest: string) => { if (selectedInterest.length > 0 && selectedInterest.includes(interest)) { setSelectedInterest((prev) => prev.filter((item) => item !== interest)); @@ -20,23 +37,50 @@ const UserSettingsPage = () => { } }; + const handleUpdateInterest = async () => { + const data = await UpdateUser({ + token: sessionToken || "", + data: { email: user?.user_metadata.email, interests: selectedInterest }, + params: "interests" + }); + console.log(data); + }; + const handleUpdateProfile = async () => { + if(validateEmail(email || "")){ + const data = await UpdateUser({ + token: sessionToken || "", + data: { email: user?.user_metadata.email, interests: selectedInterest } + }); + console.log(data); + }else{ + console.log("email is not valid"); + error = "email is not valid"; + }; + + }; + return (
-
+
Public profile -
+ e.preventDefault()} className="flex flex-col gap-6 mt-6"> setEmail(e.target.value)} label="Email*" + value={email} + /> {/* Bio section */} @@ -46,30 +90,35 @@ const UserSettingsPage = () => { rows={4} placeholder="Tell us about yourself." className="bg-light-slate-4 rounded-lg px-3 py-2 " + readOnly >
- + Other users will see the time difference from their local time. @@ -80,7 +129,7 @@ const UserSettingsPage = () => { Select time zone
- +
@@ -108,7 +157,10 @@ const UserSettingsPage = () => {
-
diff --git a/pages/user/settings.tsx b/pages/user/settings.tsx new file mode 100644 index 000000000..11c4cbbe9 --- /dev/null +++ b/pages/user/settings.tsx @@ -0,0 +1,13 @@ +import UserSettingsPage from "components/organisms/UserSettingsPage/user-settings-page"; +import ProfileLayout from "layouts/profile"; + +const ProfileSettings = (): JSX.Element => { + return ( +
+ +
+ ); +}; + +ProfileSettings.PageLayout = ProfileLayout; +export default ProfileSettings; From 69764d020d5669697cb68c42607ec53b591e9097 Mon Sep 17 00:00:00 2001 From: Sunday Ogbonna Date: Sat, 28 Jan 2023 13:16:57 +0100 Subject: [PATCH 04/25] feat: add toast support and validation --- .../UserSettingsPage/user-settings-page.tsx | 68 ++++++++++++------- lib/hooks/update-user.ts | 2 +- lib/utils/toast-trigger.ts | 25 +++++++ npm-shrinkwrap.json | 24 +++++++ package.json | 1 + pages/_app.tsx | 2 + 6 files changed, 95 insertions(+), 27 deletions(-) create mode 100644 lib/utils/toast-trigger.ts diff --git a/components/organisms/UserSettingsPage/user-settings-page.tsx b/components/organisms/UserSettingsPage/user-settings-page.tsx index c9505a6b5..e1c490bc7 100644 --- a/components/organisms/UserSettingsPage/user-settings-page.tsx +++ b/components/organisms/UserSettingsPage/user-settings-page.tsx @@ -1,4 +1,4 @@ -import React, { useState , useEffect} from "react"; +import React, { useState, useEffect } from "react"; import Button from "components/atoms/Button/button"; import Checkbox from "components/atoms/Checkbox/checkbox"; @@ -9,10 +9,12 @@ import SelectOption from "components/atoms/Select/select-option"; import LanguagePill from "components/atoms/LanguagePill/LanguagePill"; import useSupabaseAuth from "lib/hooks/useSupabaseAuth"; import { UpdateUser } from "lib/hooks/update-user"; +import { ToastTrigger } from "lib/utils/toast-trigger"; const UserSettingsPage = () => { let error; const { user, sessionToken } = useSupabaseAuth(); + const [isValidEmail, setIsValidEmail] = useState(false); const [email, setEmail] = useState(user?.email); const [selectedInterest, setSelectedInterest] = useState([]); const interestArray = ["javascript", "python", "rust", "ML", "AI", "react"]; @@ -25,9 +27,9 @@ const UserSettingsPage = () => { ); }; - useEffect(()=>{ - if(user) setEmail(user.email); - },[user]); + useEffect(() => { + if (user) setEmail(user.email); + }, [user]); const handleSelectInterest = (interest: string) => { if (selectedInterest.length > 0 && selectedInterest.includes(interest)) { @@ -43,20 +45,26 @@ const UserSettingsPage = () => { data: { email: user?.user_metadata.email, interests: selectedInterest }, params: "interests" }); - console.log(data); + if (data) { + ToastTrigger({ message: "Updated successfully", type: "success" }); + } else { + ToastTrigger({ message: "An error occured!!!", type: "error" }); + } + }; const handleUpdateProfile = async () => { - if(validateEmail(email || "")){ - const data = await UpdateUser({ - token: sessionToken || "", - data: { email: user?.user_metadata.email, interests: selectedInterest } - }); - console.log(data); - }else{ - console.log("email is not valid"); - error = "email is not valid"; - }; - + + const data = await UpdateUser({ + token: sessionToken || "", + data: { email: email, interests: [] } + }); + if (data) { + ToastTrigger({ message: "Updated successfully", type: "success" }); + } else { + ToastTrigger({ message: "An error occured!!!", type: "error" }); + } + + }; return ( @@ -66,7 +74,7 @@ const UserSettingsPage = () => { Public profile -
e.preventDefault()} className="flex flex-col gap-6 mt-6"> + e.preventDefault()} className="flex flex-col gap-6 mt-6"> { setEmail(e.target.value)} + onChange={(e) => { + setEmail(e.target.value); + if (validateEmail(e.target.value)) { + setIsValidEmail(true); + } else { + setIsValidEmail(false); + } + }} label="Email*" value={email} - + /> {/* Bio section */} @@ -129,7 +144,7 @@ const UserSettingsPage = () => { Select time zone
- +
@@ -147,9 +162,9 @@ const UserSettingsPage = () => { /> ))}
- +
@@ -157,12 +172,13 @@ const UserSettingsPage = () => {
- +
diff --git a/lib/hooks/update-user.ts b/lib/hooks/update-user.ts index 838f89c21..5cee48d78 100644 --- a/lib/hooks/update-user.ts +++ b/lib/hooks/update-user.ts @@ -7,7 +7,7 @@ interface useUpdateUserProps { const baseUrl = process.env.NEXT_PUBLIC_API_URL; const UpdateUser = async ({ token, data, params }: useUpdateUserProps) => { try { - const res = await fetch(`${baseUrl}/auth/profile/${params || ""}`, { + const res = await fetch(`${baseUrl}/auth/profile/${params || undefined}`, { headers: { Accept: "application/json", "Content-Type": "application/json", Authorization: `Bearer ${token}` }, method: "PATCH", body: JSON.stringify({ ...data }) diff --git a/lib/utils/toast-trigger.ts b/lib/utils/toast-trigger.ts new file mode 100644 index 000000000..2b3818237 --- /dev/null +++ b/lib/utils/toast-trigger.ts @@ -0,0 +1,25 @@ +import toast from "react-hot-toast"; + +export declare interface ToastTriggerProps { + message: string; + type: "success" | "error" | "custom" | ""; +} + +// notifier function trigger +export const ToastTrigger = ({ message, type }: ToastTriggerProps) => { + switch (type) { + case "success": + toast.success(message); + break; + case "error": + toast.error(message); + break; + + // pass custom type only if your message is a jsx template + case "custom": + toast.custom(message); + break; + default: + toast(message); + } +}; \ No newline at end of file diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 9be41b398..24070093c 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -42,6 +42,7 @@ "react": "^18.2.0", "react-csv": "^2.2.2", "react-dom": "^18.2.0", + "react-hot-toast": "^2.4.0", "react-icons": "^4.4.0", "react-loading-skeleton": "^3.1.0", "react-spring": "^9.5.5", @@ -21889,6 +21890,14 @@ "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", "dev": true }, + "node_modules/goober": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.11.tgz", + "integrity": "sha512-5SS2lmxbhqH0u9ABEWq7WPU69a4i2pYcHeCxqaNq6Cw3mnrF0ghWNM4tEGid4dKy8XNIAUbuThuozDHHKJVh3A==", + "peerDependencies": { + "csstype": "^3.0.10" + } + }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -29050,6 +29059,21 @@ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true }, + "node_modules/react-hot-toast": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.4.0.tgz", + "integrity": "sha512-qnnVbXropKuwUpriVVosgo8QrB+IaPJCpL8oBI6Ov84uvHZ5QQcTp2qg6ku2wNfgJl6rlQXJIQU5q+5lmPOutA==", + "dependencies": { + "goober": "^2.1.10" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, "node_modules/react-icons": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.4.0.tgz", diff --git a/package.json b/package.json index 9945906ff..b911d978c 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,7 @@ "react": "^18.2.0", "react-csv": "^2.2.2", "react-dom": "^18.2.0", + "react-hot-toast": "^2.4.0", "react-icons": "^4.4.0", "react-loading-skeleton": "^3.1.0", "react-spring": "^9.5.5", diff --git a/pages/_app.tsx b/pages/_app.tsx index 6d875f08b..993be9867 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -17,6 +17,7 @@ import changeCapitalization from "lib/utils/change-capitalization"; import apiFetcher from "lib/hooks/useSWR"; import { initiateAnalytics } from "lib/utils/analytics"; import { supabase } from "lib/utils/supabase"; +import { Toaster } from "react-hot-toast"; type ComponentWithPageLayout = AppProps & { Component: AppProps["Component"] & { @@ -99,6 +100,7 @@ function MyApp({ Component, pageProps }: ComponentWithPageLayout) { provider: localStorageProvider }} > + {Component.PageLayout ? ( From 991bc88499d84e8bcb17e1a01c2ef0b3c6988c67 Mon Sep 17 00:00:00 2001 From: Sunday Ogbonna Date: Sat, 28 Jan 2023 13:52:23 +0100 Subject: [PATCH 05/25] chore: minor api call fixes --- .../organisms/UserSettingsPage/user-settings-page.tsx | 6 +++--- lib/hooks/update-user.ts | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/components/organisms/UserSettingsPage/user-settings-page.tsx b/components/organisms/UserSettingsPage/user-settings-page.tsx index e1c490bc7..6b512aff3 100644 --- a/components/organisms/UserSettingsPage/user-settings-page.tsx +++ b/components/organisms/UserSettingsPage/user-settings-page.tsx @@ -12,13 +12,13 @@ import { UpdateUser } from "lib/hooks/update-user"; import { ToastTrigger } from "lib/utils/toast-trigger"; const UserSettingsPage = () => { - let error; + const { user, sessionToken } = useSupabaseAuth(); const [isValidEmail, setIsValidEmail] = useState(false); const [email, setEmail] = useState(user?.email); const [selectedInterest, setSelectedInterest] = useState([]); const interestArray = ["javascript", "python", "rust", "ML", "AI", "react"]; - + console.log(sessionToken); const validateEmail = (email: string) => { return String(email) .toLowerCase() @@ -56,7 +56,7 @@ const UserSettingsPage = () => { const data = await UpdateUser({ token: sessionToken || "", - data: { email: email, interests: [] } + data: { email: email, interests: [""] } }); if (data) { ToastTrigger({ message: "Updated successfully", type: "success" }); diff --git a/lib/hooks/update-user.ts b/lib/hooks/update-user.ts index 5cee48d78..29e36cfa1 100644 --- a/lib/hooks/update-user.ts +++ b/lib/hooks/update-user.ts @@ -7,16 +7,17 @@ interface useUpdateUserProps { const baseUrl = process.env.NEXT_PUBLIC_API_URL; const UpdateUser = async ({ token, data, params }: useUpdateUserProps) => { try { - const res = await fetch(`${baseUrl}/auth/profile/${params || undefined}`, { + const res = await fetch(`${baseUrl}/auth/profile${params && `/${params}`}`, { headers: { Accept: "application/json", "Content-Type": "application/json", Authorization: `Bearer ${token}` }, method: "PATCH", body: JSON.stringify({ ...data }) }); if (res.status === 200) { - return res; + return res.ok; } else { - return res; + console.log(res); + return false; } } catch (e) { console.log(e); From 8f063a5bf41f576f4879e209aa52e55e8e8cf3b9 Mon Sep 17 00:00:00 2001 From: Sunday Ogbonna Date: Sat, 28 Jan 2023 13:52:49 +0100 Subject: [PATCH 06/25] refactor: remove unwanted code --- components/organisms/UserSettingsPage/user-settings-page.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/organisms/UserSettingsPage/user-settings-page.tsx b/components/organisms/UserSettingsPage/user-settings-page.tsx index 6b512aff3..65e7b3417 100644 --- a/components/organisms/UserSettingsPage/user-settings-page.tsx +++ b/components/organisms/UserSettingsPage/user-settings-page.tsx @@ -18,7 +18,7 @@ const UserSettingsPage = () => { const [email, setEmail] = useState(user?.email); const [selectedInterest, setSelectedInterest] = useState([]); const interestArray = ["javascript", "python", "rust", "ML", "AI", "react"]; - console.log(sessionToken); + const validateEmail = (email: string) => { return String(email) .toLowerCase() @@ -56,7 +56,7 @@ const UserSettingsPage = () => { const data = await UpdateUser({ token: sessionToken || "", - data: { email: email, interests: [""] } + data: { email: email, interests: [] } }); if (data) { ToastTrigger({ message: "Updated successfully", type: "success" }); From b9a22c277bf1681f8b00ed8c3b71176c9e53d67c Mon Sep 17 00:00:00 2001 From: Sunday Ogbonna Date: Mon, 30 Jan 2023 18:33:33 +0100 Subject: [PATCH 07/25] refactor: update default values --- .../UserSettingsPage/user-settings-page.tsx | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/components/organisms/UserSettingsPage/user-settings-page.tsx b/components/organisms/UserSettingsPage/user-settings-page.tsx index 65e7b3417..d975adb0c 100644 --- a/components/organisms/UserSettingsPage/user-settings-page.tsx +++ b/components/organisms/UserSettingsPage/user-settings-page.tsx @@ -12,7 +12,6 @@ import { UpdateUser } from "lib/hooks/update-user"; import { ToastTrigger } from "lib/utils/toast-trigger"; const UserSettingsPage = () => { - const { user, sessionToken } = useSupabaseAuth(); const [isValidEmail, setIsValidEmail] = useState(false); const [email, setEmail] = useState(user?.email); @@ -50,10 +49,8 @@ const UserSettingsPage = () => { } else { ToastTrigger({ message: "An error occured!!!", type: "error" }); } - }; const handleUpdateProfile = async () => { - const data = await UpdateUser({ token: sessionToken || "", data: { email: email, interests: [] } @@ -63,8 +60,6 @@ const UserSettingsPage = () => { } else { ToastTrigger({ message: "An error occured!!!", type: "error" }); } - - }; return ( @@ -95,7 +90,6 @@ const UserSettingsPage = () => { }} label="Email*" value={email} - /> {/* Bio section */} @@ -133,7 +127,7 @@ const UserSettingsPage = () => { disabled />
- + Other users will see the time difference from their local time. @@ -144,7 +138,9 @@ const UserSettingsPage = () => { Select time zone
- +
@@ -162,21 +158,27 @@ const UserSettingsPage = () => { /> ))}
-
- - + +
-
From d96d29caaa31f0f86fd8a1e519eae1c416f6578d Mon Sep 17 00:00:00 2001 From: Sunday Ogbonna Date: Mon, 30 Jan 2023 18:46:27 +0100 Subject: [PATCH 08/25] refactor: add timezone array to select options --- .../UserSettingsPage/user-settings-page.tsx | 1191 ++++++++++++++++- 1 file changed, 1188 insertions(+), 3 deletions(-) diff --git a/components/organisms/UserSettingsPage/user-settings-page.tsx b/components/organisms/UserSettingsPage/user-settings-page.tsx index d975adb0c..eaceba34b 100644 --- a/components/organisms/UserSettingsPage/user-settings-page.tsx +++ b/components/organisms/UserSettingsPage/user-settings-page.tsx @@ -11,6 +11,1186 @@ import useSupabaseAuth from "lib/hooks/useSupabaseAuth"; import { UpdateUser } from "lib/hooks/update-user"; import { ToastTrigger } from "lib/utils/toast-trigger"; +const timezones = [ + { + value: "Dateline Standard Time", + abbr: "DST", + offset: -12, + isdst: false, + text: "(UTC-12:00) International Date Line West", + utc: ["Etc/GMT+12"] + }, + { + value: "UTC-11", + abbr: "U", + offset: -11, + isdst: false, + text: "(UTC-11:00) Coordinated Universal Time-11", + utc: ["Etc/GMT+11", "Pacific/Midway", "Pacific/Niue", "Pacific/Pago_Pago"] + }, + { + value: "Hawaiian Standard Time", + abbr: "HST", + offset: -10, + isdst: false, + text: "(UTC-10:00) Hawaii", + utc: ["Etc/GMT+10", "Pacific/Honolulu", "Pacific/Johnston", "Pacific/Rarotonga", "Pacific/Tahiti"] + }, + { + value: "Alaskan Standard Time", + abbr: "AKDT", + offset: -8, + isdst: true, + text: "(UTC-09:00) Alaska", + utc: ["America/Anchorage", "America/Juneau", "America/Nome", "America/Sitka", "America/Yakutat"] + }, + { + value: "Pacific Standard Time (Mexico)", + abbr: "PDT", + offset: -7, + isdst: true, + text: "(UTC-08:00) Baja California", + utc: ["America/Santa_Isabel"] + }, + { + value: "Pacific Daylight Time", + abbr: "PDT", + offset: -7, + isdst: true, + text: "(UTC-07:00) Pacific Daylight Time (US & Canada)", + utc: ["America/Los_Angeles", "America/Tijuana", "America/Vancouver"] + }, + { + value: "Pacific Standard Time", + abbr: "PST", + offset: -8, + isdst: false, + text: "(UTC-08:00) Pacific Standard Time (US & Canada)", + utc: ["America/Los_Angeles", "America/Tijuana", "America/Vancouver", "PST8PDT"] + }, + { + value: "US Mountain Standard Time", + abbr: "UMST", + offset: -7, + isdst: false, + text: "(UTC-07:00) Arizona", + utc: [ + "America/Creston", + "America/Dawson", + "America/Dawson_Creek", + "America/Hermosillo", + "America/Phoenix", + "America/Whitehorse", + "Etc/GMT+7" + ] + }, + { + value: "Mountain Standard Time (Mexico)", + abbr: "MDT", + offset: -6, + isdst: true, + text: "(UTC-07:00) Chihuahua, La Paz, Mazatlan", + utc: ["America/Chihuahua", "America/Mazatlan"] + }, + { + value: "Mountain Standard Time", + abbr: "MDT", + offset: -6, + isdst: true, + text: "(UTC-07:00) Mountain Time (US & Canada)", + utc: [ + "America/Boise", + "America/Cambridge_Bay", + "America/Denver", + "America/Edmonton", + "America/Inuvik", + "America/Ojinaga", + "America/Yellowknife", + "MST7MDT" + ] + }, + { + value: "Central America Standard Time", + abbr: "CAST", + offset: -6, + isdst: false, + text: "(UTC-06:00) Central America", + utc: [ + "America/Belize", + "America/Costa_Rica", + "America/El_Salvador", + "America/Guatemala", + "America/Managua", + "America/Tegucigalpa", + "Etc/GMT+6", + "Pacific/Galapagos" + ] + }, + { + value: "Central Standard Time", + abbr: "CDT", + offset: -5, + isdst: true, + text: "(UTC-06:00) Central Time (US & Canada)", + utc: [ + "America/Chicago", + "America/Indiana/Knox", + "America/Indiana/Tell_City", + "America/Matamoros", + "America/Menominee", + "America/North_Dakota/Beulah", + "America/North_Dakota/Center", + "America/North_Dakota/New_Salem", + "America/Rainy_River", + "America/Rankin_Inlet", + "America/Resolute", + "America/Winnipeg", + "CST6CDT" + ] + }, + { + value: "Central Standard Time (Mexico)", + abbr: "CDT", + offset: -5, + isdst: true, + text: "(UTC-06:00) Guadalajara, Mexico City, Monterrey", + utc: ["America/Bahia_Banderas", "America/Cancun", "America/Merida", "America/Mexico_City", "America/Monterrey"] + }, + { + value: "Canada Central Standard Time", + abbr: "CCST", + offset: -6, + isdst: false, + text: "(UTC-06:00) Saskatchewan", + utc: ["America/Regina", "America/Swift_Current"] + }, + { + value: "SA Pacific Standard Time", + abbr: "SPST", + offset: -5, + isdst: false, + text: "(UTC-05:00) Bogota, Lima, Quito", + utc: [ + "America/Bogota", + "America/Cayman", + "America/Coral_Harbour", + "America/Eirunepe", + "America/Guayaquil", + "America/Jamaica", + "America/Lima", + "America/Panama", + "America/Rio_Branco", + "Etc/GMT+5" + ] + }, + { + value: "Eastern Standard Time", + abbr: "EST", + offset: -5, + isdst: false, + text: "(UTC-05:00) Eastern Time (US & Canada)", + utc: [ + "America/Detroit", + "America/Havana", + "America/Indiana/Petersburg", + "America/Indiana/Vincennes", + "America/Indiana/Winamac", + "America/Iqaluit", + "America/Kentucky/Monticello", + "America/Louisville", + "America/Montreal", + "America/Nassau", + "America/New_York", + "America/Nipigon", + "America/Pangnirtung", + "America/Port-au-Prince", + "America/Thunder_Bay", + "America/Toronto" + ] + }, + { + value: "Eastern Daylight Time", + abbr: "EDT", + offset: -4, + isdst: true, + text: "(UTC-04:00) Eastern Daylight Time (US & Canada)", + utc: [ + "America/Detroit", + "America/Havana", + "America/Indiana/Petersburg", + "America/Indiana/Vincennes", + "America/Indiana/Winamac", + "America/Iqaluit", + "America/Kentucky/Monticello", + "America/Louisville", + "America/Montreal", + "America/Nassau", + "America/New_York", + "America/Nipigon", + "America/Pangnirtung", + "America/Port-au-Prince", + "America/Thunder_Bay", + "America/Toronto" + ] + }, + { + value: "US Eastern Standard Time", + abbr: "UEDT", + offset: -5, + isdst: false, + text: "(UTC-05:00) Indiana (East)", + utc: ["America/Indiana/Marengo", "America/Indiana/Vevay", "America/Indianapolis"] + }, + { + value: "Venezuela Standard Time", + abbr: "VST", + offset: -4.5, + isdst: false, + text: "(UTC-04:30) Caracas", + utc: ["America/Caracas"] + }, + { + value: "Paraguay Standard Time", + abbr: "PYT", + offset: -4, + isdst: false, + text: "(UTC-04:00) Asuncion", + utc: ["America/Asuncion"] + }, + { + value: "Atlantic Standard Time", + abbr: "ADT", + offset: -3, + isdst: true, + text: "(UTC-04:00) Atlantic Time (Canada)", + utc: [ + "America/Glace_Bay", + "America/Goose_Bay", + "America/Halifax", + "America/Moncton", + "America/Thule", + "Atlantic/Bermuda" + ] + }, + { + value: "Central Brazilian Standard Time", + abbr: "CBST", + offset: -4, + isdst: false, + text: "(UTC-04:00) Cuiaba", + utc: ["America/Campo_Grande", "America/Cuiaba"] + }, + { + value: "SA Western Standard Time", + abbr: "SWST", + offset: -4, + isdst: false, + text: "(UTC-04:00) Georgetown, La Paz, Manaus, San Juan", + utc: [ + "America/Anguilla", + "America/Antigua", + "America/Aruba", + "America/Barbados", + "America/Blanc-Sablon", + "America/Boa_Vista", + "America/Curacao", + "America/Dominica", + "America/Grand_Turk", + "America/Grenada", + "America/Guadeloupe", + "America/Guyana", + "America/Kralendijk", + "America/La_Paz", + "America/Lower_Princes", + "America/Manaus", + "America/Marigot", + "America/Martinique", + "America/Montserrat", + "America/Port_of_Spain", + "America/Porto_Velho", + "America/Puerto_Rico", + "America/Santo_Domingo", + "America/St_Barthelemy", + "America/St_Kitts", + "America/St_Lucia", + "America/St_Thomas", + "America/St_Vincent", + "America/Tortola", + "Etc/GMT+4" + ] + }, + { + value: "Pacific SA Standard Time", + abbr: "PSST", + offset: -4, + isdst: false, + text: "(UTC-04:00) Santiago", + utc: ["America/Santiago", "Antarctica/Palmer"] + }, + { + value: "Newfoundland Standard Time", + abbr: "NDT", + offset: -2.5, + isdst: true, + text: "(UTC-03:30) Newfoundland", + utc: ["America/St_Johns"] + }, + { + value: "E. South America Standard Time", + abbr: "ESAST", + offset: -3, + isdst: false, + text: "(UTC-03:00) Brasilia", + utc: ["America/Sao_Paulo"] + }, + { + value: "Argentina Standard Time", + abbr: "AST", + offset: -3, + isdst: false, + text: "(UTC-03:00) Buenos Aires", + utc: [ + "America/Argentina/La_Rioja", + "America/Argentina/Rio_Gallegos", + "America/Argentina/Salta", + "America/Argentina/San_Juan", + "America/Argentina/San_Luis", + "America/Argentina/Tucuman", + "America/Argentina/Ushuaia", + "America/Buenos_Aires", + "America/Catamarca", + "America/Cordoba", + "America/Jujuy", + "America/Mendoza" + ] + }, + { + value: "SA Eastern Standard Time", + abbr: "SEST", + offset: -3, + isdst: false, + text: "(UTC-03:00) Cayenne, Fortaleza", + utc: [ + "America/Araguaina", + "America/Belem", + "America/Cayenne", + "America/Fortaleza", + "America/Maceio", + "America/Paramaribo", + "America/Recife", + "America/Santarem", + "Antarctica/Rothera", + "Atlantic/Stanley", + "Etc/GMT+3" + ] + }, + { + value: "Greenland Standard Time", + abbr: "GDT", + offset: -3, + isdst: true, + text: "(UTC-03:00) Greenland", + utc: ["America/Godthab"] + }, + { + value: "Montevideo Standard Time", + abbr: "MST", + offset: -3, + isdst: false, + text: "(UTC-03:00) Montevideo", + utc: ["America/Montevideo"] + }, + { + value: "Bahia Standard Time", + abbr: "BST", + offset: -3, + isdst: false, + text: "(UTC-03:00) Salvador", + utc: ["America/Bahia"] + }, + { + value: "UTC-02", + abbr: "U", + offset: -2, + isdst: false, + text: "(UTC-02:00) Coordinated Universal Time-02", + utc: ["America/Noronha", "Atlantic/South_Georgia", "Etc/GMT+2"] + }, + { + value: "Mid-Atlantic Standard Time", + abbr: "MDT", + offset: -1, + isdst: true, + text: "(UTC-02:00) Mid-Atlantic - Old", + utc: [] + }, + { + value: "Azores Standard Time", + abbr: "ADT", + offset: 0, + isdst: true, + text: "(UTC-01:00) Azores", + utc: ["America/Scoresbysund", "Atlantic/Azores"] + }, + { + value: "Cape Verde Standard Time", + abbr: "CVST", + offset: -1, + isdst: false, + text: "(UTC-01:00) Cape Verde Is.", + utc: ["Atlantic/Cape_Verde", "Etc/GMT+1"] + }, + { + value: "Morocco Standard Time", + abbr: "MDT", + offset: 1, + isdst: true, + text: "(UTC) Casablanca", + utc: ["Africa/Casablanca", "Africa/El_Aaiun"] + }, + { + value: "UTC", + abbr: "UTC", + offset: 0, + isdst: false, + text: "(UTC) Coordinated Universal Time", + utc: ["America/Danmarkshavn", "Etc/GMT"] + }, + { + value: "GMT Standard Time", + abbr: "GMT", + offset: 0, + isdst: false, + text: "(UTC) Edinburgh, London", + utc: ["Europe/Isle_of_Man", "Europe/Guernsey", "Europe/Jersey", "Europe/London"] + }, + { + value: "British Summer Time", + abbr: "BST", + offset: 1, + isdst: true, + text: "(UTC+01:00) Edinburgh, London", + utc: ["Europe/Isle_of_Man", "Europe/Guernsey", "Europe/Jersey", "Europe/London"] + }, + { + value: "GMT Standard Time", + abbr: "GDT", + offset: 1, + isdst: true, + text: "(UTC) Dublin, Lisbon", + utc: ["Atlantic/Canary", "Atlantic/Faeroe", "Atlantic/Madeira", "Europe/Dublin", "Europe/Lisbon"] + }, + { + value: "Greenwich Standard Time", + abbr: "GST", + offset: 0, + isdst: false, + text: "(UTC) Monrovia, Reykjavik", + utc: [ + "Africa/Abidjan", + "Africa/Accra", + "Africa/Bamako", + "Africa/Banjul", + "Africa/Bissau", + "Africa/Conakry", + "Africa/Dakar", + "Africa/Freetown", + "Africa/Lome", + "Africa/Monrovia", + "Africa/Nouakchott", + "Africa/Ouagadougou", + "Africa/Sao_Tome", + "Atlantic/Reykjavik", + "Atlantic/St_Helena" + ] + }, + { + value: "W. Europe Standard Time", + abbr: "WEDT", + offset: 2, + isdst: true, + text: "(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna", + utc: [ + "Arctic/Longyearbyen", + "Europe/Amsterdam", + "Europe/Andorra", + "Europe/Berlin", + "Europe/Busingen", + "Europe/Gibraltar", + "Europe/Luxembourg", + "Europe/Malta", + "Europe/Monaco", + "Europe/Oslo", + "Europe/Rome", + "Europe/San_Marino", + "Europe/Stockholm", + "Europe/Vaduz", + "Europe/Vatican", + "Europe/Vienna", + "Europe/Zurich" + ] + }, + { + value: "Central Europe Standard Time", + abbr: "CEDT", + offset: 2, + isdst: true, + text: "(UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague", + utc: [ + "Europe/Belgrade", + "Europe/Bratislava", + "Europe/Budapest", + "Europe/Ljubljana", + "Europe/Podgorica", + "Europe/Prague", + "Europe/Tirane" + ] + }, + { + value: "Romance Standard Time", + abbr: "RDT", + offset: 2, + isdst: true, + text: "(UTC+01:00) Brussels, Copenhagen, Madrid, Paris", + utc: ["Africa/Ceuta", "Europe/Brussels", "Europe/Copenhagen", "Europe/Madrid", "Europe/Paris"] + }, + { + value: "Central European Standard Time", + abbr: "CEDT", + offset: 2, + isdst: true, + text: "(UTC+01:00) Sarajevo, Skopje, Warsaw, Zagreb", + utc: ["Europe/Sarajevo", "Europe/Skopje", "Europe/Warsaw", "Europe/Zagreb"] + }, + { + value: "W. Central Africa Standard Time", + abbr: "WCAST", + offset: 1, + isdst: false, + text: "(UTC+01:00) West Central Africa", + utc: [ + "Africa/Algiers", + "Africa/Bangui", + "Africa/Brazzaville", + "Africa/Douala", + "Africa/Kinshasa", + "Africa/Lagos", + "Africa/Libreville", + "Africa/Luanda", + "Africa/Malabo", + "Africa/Ndjamena", + "Africa/Niamey", + "Africa/Porto-Novo", + "Africa/Tunis", + "Etc/GMT-1" + ] + }, + { + value: "Namibia Standard Time", + abbr: "NST", + offset: 1, + isdst: false, + text: "(UTC+01:00) Windhoek", + utc: ["Africa/Windhoek"] + }, + { + value: "GTB Standard Time", + abbr: "GDT", + offset: 3, + isdst: true, + text: "(UTC+02:00) Athens, Bucharest", + utc: ["Asia/Nicosia", "Europe/Athens", "Europe/Bucharest", "Europe/Chisinau"] + }, + { + value: "Middle East Standard Time", + abbr: "MEDT", + offset: 3, + isdst: true, + text: "(UTC+02:00) Beirut", + utc: ["Asia/Beirut"] + }, + { + value: "Egypt Standard Time", + abbr: "EST", + offset: 2, + isdst: false, + text: "(UTC+02:00) Cairo", + utc: ["Africa/Cairo"] + }, + { + value: "Syria Standard Time", + abbr: "SDT", + offset: 3, + isdst: true, + text: "(UTC+02:00) Damascus", + utc: ["Asia/Damascus"] + }, + { + value: "E. Europe Standard Time", + abbr: "EEDT", + offset: 3, + isdst: true, + text: "(UTC+02:00) E. Europe", + utc: [ + "Asia/Nicosia", + "Europe/Athens", + "Europe/Bucharest", + "Europe/Chisinau", + "Europe/Helsinki", + "Europe/Kiev", + "Europe/Mariehamn", + "Europe/Nicosia", + "Europe/Riga", + "Europe/Sofia", + "Europe/Tallinn", + "Europe/Uzhgorod", + "Europe/Vilnius", + "Europe/Zaporozhye" + ] + }, + { + value: "South Africa Standard Time", + abbr: "SAST", + offset: 2, + isdst: false, + text: "(UTC+02:00) Harare, Pretoria", + utc: [ + "Africa/Blantyre", + "Africa/Bujumbura", + "Africa/Gaborone", + "Africa/Harare", + "Africa/Johannesburg", + "Africa/Kigali", + "Africa/Lubumbashi", + "Africa/Lusaka", + "Africa/Maputo", + "Africa/Maseru", + "Africa/Mbabane", + "Etc/GMT-2" + ] + }, + { + value: "FLE Standard Time", + abbr: "FDT", + offset: 3, + isdst: true, + text: "(UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius", + utc: [ + "Europe/Helsinki", + "Europe/Kiev", + "Europe/Mariehamn", + "Europe/Riga", + "Europe/Sofia", + "Europe/Tallinn", + "Europe/Uzhgorod", + "Europe/Vilnius", + "Europe/Zaporozhye" + ] + }, + { + value: "Turkey Standard Time", + abbr: "TDT", + offset: 3, + isdst: false, + text: "(UTC+03:00) Istanbul", + utc: ["Europe/Istanbul"] + }, + { + value: "Israel Standard Time", + abbr: "JDT", + offset: 3, + isdst: true, + text: "(UTC+02:00) Jerusalem", + utc: ["Asia/Jerusalem"] + }, + { + value: "Libya Standard Time", + abbr: "LST", + offset: 2, + isdst: false, + text: "(UTC+02:00) Tripoli", + utc: ["Africa/Tripoli"] + }, + { + value: "Jordan Standard Time", + abbr: "JST", + offset: 3, + isdst: false, + text: "(UTC+03:00) Amman", + utc: ["Asia/Amman"] + }, + { + value: "Arabic Standard Time", + abbr: "AST", + offset: 3, + isdst: false, + text: "(UTC+03:00) Baghdad", + utc: ["Asia/Baghdad"] + }, + { + value: "Kaliningrad Standard Time", + abbr: "KST", + offset: 3, + isdst: false, + text: "(UTC+02:00) Kaliningrad", + utc: ["Europe/Kaliningrad"] + }, + { + value: "Arab Standard Time", + abbr: "AST", + offset: 3, + isdst: false, + text: "(UTC+03:00) Kuwait, Riyadh", + utc: ["Asia/Aden", "Asia/Bahrain", "Asia/Kuwait", "Asia/Qatar", "Asia/Riyadh"] + }, + { + value: "E. Africa Standard Time", + abbr: "EAST", + offset: 3, + isdst: false, + text: "(UTC+03:00) Nairobi", + utc: [ + "Africa/Addis_Ababa", + "Africa/Asmera", + "Africa/Dar_es_Salaam", + "Africa/Djibouti", + "Africa/Juba", + "Africa/Kampala", + "Africa/Khartoum", + "Africa/Mogadishu", + "Africa/Nairobi", + "Antarctica/Syowa", + "Etc/GMT-3", + "Indian/Antananarivo", + "Indian/Comoro", + "Indian/Mayotte" + ] + }, + { + value: "Moscow Standard Time", + abbr: "MSK", + offset: 3, + isdst: false, + text: "(UTC+03:00) Moscow, St. Petersburg, Volgograd, Minsk", + utc: ["Europe/Kirov", "Europe/Moscow", "Europe/Simferopol", "Europe/Volgograd", "Europe/Minsk"] + }, + { + value: "Samara Time", + abbr: "SAMT", + offset: 4, + isdst: false, + text: "(UTC+04:00) Samara, Ulyanovsk, Saratov", + utc: ["Europe/Astrakhan", "Europe/Samara", "Europe/Ulyanovsk"] + }, + { + value: "Iran Standard Time", + abbr: "IDT", + offset: 4.5, + isdst: true, + text: "(UTC+03:30) Tehran", + utc: ["Asia/Tehran"] + }, + { + value: "Arabian Standard Time", + abbr: "AST", + offset: 4, + isdst: false, + text: "(UTC+04:00) Abu Dhabi, Muscat", + utc: ["Asia/Dubai", "Asia/Muscat", "Etc/GMT-4"] + }, + { + value: "Azerbaijan Standard Time", + abbr: "ADT", + offset: 5, + isdst: true, + text: "(UTC+04:00) Baku", + utc: ["Asia/Baku"] + }, + { + value: "Mauritius Standard Time", + abbr: "MST", + offset: 4, + isdst: false, + text: "(UTC+04:00) Port Louis", + utc: ["Indian/Mahe", "Indian/Mauritius", "Indian/Reunion"] + }, + { + value: "Georgian Standard Time", + abbr: "GET", + offset: 4, + isdst: false, + text: "(UTC+04:00) Tbilisi", + utc: ["Asia/Tbilisi"] + }, + { + value: "Caucasus Standard Time", + abbr: "CST", + offset: 4, + isdst: false, + text: "(UTC+04:00) Yerevan", + utc: ["Asia/Yerevan"] + }, + { + value: "Afghanistan Standard Time", + abbr: "AST", + offset: 4.5, + isdst: false, + text: "(UTC+04:30) Kabul", + utc: ["Asia/Kabul"] + }, + { + value: "West Asia Standard Time", + abbr: "WAST", + offset: 5, + isdst: false, + text: "(UTC+05:00) Ashgabat, Tashkent", + utc: [ + "Antarctica/Mawson", + "Asia/Aqtau", + "Asia/Aqtobe", + "Asia/Ashgabat", + "Asia/Dushanbe", + "Asia/Oral", + "Asia/Samarkand", + "Asia/Tashkent", + "Etc/GMT-5", + "Indian/Kerguelen", + "Indian/Maldives" + ] + }, + { + value: "Yekaterinburg Time", + abbr: "YEKT", + offset: 5, + isdst: false, + text: "(UTC+05:00) Yekaterinburg", + utc: ["Asia/Yekaterinburg"] + }, + { + value: "Pakistan Standard Time", + abbr: "PKT", + offset: 5, + isdst: false, + text: "(UTC+05:00) Islamabad, Karachi", + utc: ["Asia/Karachi"] + }, + { + value: "India Standard Time", + abbr: "IST", + offset: 5.5, + isdst: false, + text: "(UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi", + utc: ["Asia/Kolkata", "Asia/Calcutta"] + }, + { + value: "Sri Lanka Standard Time", + abbr: "SLST", + offset: 5.5, + isdst: false, + text: "(UTC+05:30) Sri Jayawardenepura", + utc: ["Asia/Colombo"] + }, + { + value: "Nepal Standard Time", + abbr: "NST", + offset: 5.75, + isdst: false, + text: "(UTC+05:45) Kathmandu", + utc: ["Asia/Kathmandu"] + }, + { + value: "Central Asia Standard Time", + abbr: "CAST", + offset: 6, + isdst: false, + text: "(UTC+06:00) Nur-Sultan (Astana)", + utc: [ + "Antarctica/Vostok", + "Asia/Almaty", + "Asia/Bishkek", + "Asia/Qyzylorda", + "Asia/Urumqi", + "Etc/GMT-6", + "Indian/Chagos" + ] + }, + { + value: "Bangladesh Standard Time", + abbr: "BST", + offset: 6, + isdst: false, + text: "(UTC+06:00) Dhaka", + utc: ["Asia/Dhaka", "Asia/Thimphu"] + }, + { + value: "Myanmar Standard Time", + abbr: "MST", + offset: 6.5, + isdst: false, + text: "(UTC+06:30) Yangon (Rangoon)", + utc: ["Asia/Rangoon", "Indian/Cocos"] + }, + { + value: "SE Asia Standard Time", + abbr: "SAST", + offset: 7, + isdst: false, + text: "(UTC+07:00) Bangkok, Hanoi, Jakarta", + utc: [ + "Antarctica/Davis", + "Asia/Bangkok", + "Asia/Hovd", + "Asia/Jakarta", + "Asia/Phnom_Penh", + "Asia/Pontianak", + "Asia/Saigon", + "Asia/Vientiane", + "Etc/GMT-7", + "Indian/Christmas" + ] + }, + { + value: "N. Central Asia Standard Time", + abbr: "NCAST", + offset: 7, + isdst: false, + text: "(UTC+07:00) Novosibirsk", + utc: ["Asia/Novokuznetsk", "Asia/Novosibirsk", "Asia/Omsk"] + }, + { + value: "China Standard Time", + abbr: "CST", + offset: 8, + isdst: false, + text: "(UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi", + utc: ["Asia/Hong_Kong", "Asia/Macau", "Asia/Shanghai"] + }, + { + value: "North Asia Standard Time", + abbr: "NAST", + offset: 8, + isdst: false, + text: "(UTC+08:00) Krasnoyarsk", + utc: ["Asia/Krasnoyarsk"] + }, + { + value: "Singapore Standard Time", + abbr: "MPST", + offset: 8, + isdst: false, + text: "(UTC+08:00) Kuala Lumpur, Singapore", + utc: [ + "Asia/Brunei", + "Asia/Kuala_Lumpur", + "Asia/Kuching", + "Asia/Makassar", + "Asia/Manila", + "Asia/Singapore", + "Etc/GMT-8" + ] + }, + { + value: "W. Australia Standard Time", + abbr: "WAST", + offset: 8, + isdst: false, + text: "(UTC+08:00) Perth", + utc: ["Antarctica/Casey", "Australia/Perth"] + }, + { + value: "Taipei Standard Time", + abbr: "TST", + offset: 8, + isdst: false, + text: "(UTC+08:00) Taipei", + utc: ["Asia/Taipei"] + }, + { + value: "Ulaanbaatar Standard Time", + abbr: "UST", + offset: 8, + isdst: false, + text: "(UTC+08:00) Ulaanbaatar", + utc: ["Asia/Choibalsan", "Asia/Ulaanbaatar"] + }, + { + value: "North Asia East Standard Time", + abbr: "NAEST", + offset: 8, + isdst: false, + text: "(UTC+08:00) Irkutsk", + utc: ["Asia/Irkutsk"] + }, + { + value: "Japan Standard Time", + abbr: "JST", + offset: 9, + isdst: false, + text: "(UTC+09:00) Osaka, Sapporo, Tokyo", + utc: ["Asia/Dili", "Asia/Jayapura", "Asia/Tokyo", "Etc/GMT-9", "Pacific/Palau"] + }, + { + value: "Korea Standard Time", + abbr: "KST", + offset: 9, + isdst: false, + text: "(UTC+09:00) Seoul", + utc: ["Asia/Pyongyang", "Asia/Seoul"] + }, + { + value: "Cen. Australia Standard Time", + abbr: "CAST", + offset: 9.5, + isdst: false, + text: "(UTC+09:30) Adelaide", + utc: ["Australia/Adelaide", "Australia/Broken_Hill"] + }, + { + value: "AUS Central Standard Time", + abbr: "ACST", + offset: 9.5, + isdst: false, + text: "(UTC+09:30) Darwin", + utc: ["Australia/Darwin"] + }, + { + value: "E. Australia Standard Time", + abbr: "EAST", + offset: 10, + isdst: false, + text: "(UTC+10:00) Brisbane", + utc: ["Australia/Brisbane", "Australia/Lindeman"] + }, + { + value: "AUS Eastern Standard Time", + abbr: "AEST", + offset: 10, + isdst: false, + text: "(UTC+10:00) Canberra, Melbourne, Sydney", + utc: ["Australia/Melbourne", "Australia/Sydney"] + }, + { + value: "West Pacific Standard Time", + abbr: "WPST", + offset: 10, + isdst: false, + text: "(UTC+10:00) Guam, Port Moresby", + utc: [ + "Antarctica/DumontDUrville", + "Etc/GMT-10", + "Pacific/Guam", + "Pacific/Port_Moresby", + "Pacific/Saipan", + "Pacific/Truk" + ] + }, + { + value: "Tasmania Standard Time", + abbr: "TST", + offset: 10, + isdst: false, + text: "(UTC+10:00) Hobart", + utc: ["Australia/Currie", "Australia/Hobart"] + }, + { + value: "Yakutsk Standard Time", + abbr: "YST", + offset: 9, + isdst: false, + text: "(UTC+09:00) Yakutsk", + utc: ["Asia/Chita", "Asia/Khandyga", "Asia/Yakutsk"] + }, + { + value: "Central Pacific Standard Time", + abbr: "CPST", + offset: 11, + isdst: false, + text: "(UTC+11:00) Solomon Is., New Caledonia", + utc: [ + "Antarctica/Macquarie", + "Etc/GMT-11", + "Pacific/Efate", + "Pacific/Guadalcanal", + "Pacific/Kosrae", + "Pacific/Noumea", + "Pacific/Ponape" + ] + }, + { + value: "Vladivostok Standard Time", + abbr: "VST", + offset: 11, + isdst: false, + text: "(UTC+11:00) Vladivostok", + utc: ["Asia/Sakhalin", "Asia/Ust-Nera", "Asia/Vladivostok"] + }, + { + value: "New Zealand Standard Time", + abbr: "NZST", + offset: 12, + isdst: false, + text: "(UTC+12:00) Auckland, Wellington", + utc: ["Antarctica/McMurdo", "Pacific/Auckland"] + }, + { + value: "UTC+12", + abbr: "U", + offset: 12, + isdst: false, + text: "(UTC+12:00) Coordinated Universal Time+12", + utc: [ + "Etc/GMT-12", + "Pacific/Funafuti", + "Pacific/Kwajalein", + "Pacific/Majuro", + "Pacific/Nauru", + "Pacific/Tarawa", + "Pacific/Wake", + "Pacific/Wallis" + ] + }, + { + value: "Fiji Standard Time", + abbr: "FST", + offset: 12, + isdst: false, + text: "(UTC+12:00) Fiji", + utc: ["Pacific/Fiji"] + }, + { + value: "Magadan Standard Time", + abbr: "MST", + offset: 12, + isdst: false, + text: "(UTC+12:00) Magadan", + utc: ["Asia/Anadyr", "Asia/Kamchatka", "Asia/Magadan", "Asia/Srednekolymsk"] + }, + { + value: "Kamchatka Standard Time", + abbr: "KDT", + offset: 13, + isdst: true, + text: "(UTC+12:00) Petropavlovsk-Kamchatsky - Old", + utc: ["Asia/Kamchatka"] + }, + { + value: "Tonga Standard Time", + abbr: "TST", + offset: 13, + isdst: false, + text: "(UTC+13:00) Nuku'alofa", + utc: ["Etc/GMT-13", "Pacific/Enderbury", "Pacific/Fakaofo", "Pacific/Tongatapu"] + }, + { + value: "Samoa Standard Time", + abbr: "SST", + offset: 13, + isdst: false, + text: "(UTC+13:00) Samoa", + utc: ["Pacific/Apia"] + } +]; + const UserSettingsPage = () => { const { user, sessionToken } = useSupabaseAuth(); const [isValidEmail, setIsValidEmail] = useState(false); @@ -127,7 +1307,7 @@ const UserSettingsPage = () => { disabled />
- + Other users will see the time difference from their local time. @@ -135,7 +1315,12 @@ const UserSettingsPage = () => {
diff --git a/lib/hooks/updateEmailPreference.ts b/lib/hooks/updateEmailPreference.ts new file mode 100644 index 000000000..55994b4da --- /dev/null +++ b/lib/hooks/updateEmailPreference.ts @@ -0,0 +1,32 @@ +import { supabase } from "lib/utils/supabase"; + +interface UpdateEmailProps { + display_email?: boolean; + receive_collaboration?: boolean; +} + +const baseUrl = process.env.NEXT_PUBLIC_API_URL; +const updateEmailPreferences = async (data: UpdateEmailProps) => { + const sessionResponse = await supabase.auth.getSession(); + const sessionToken = sessionResponse?.data.session?.access_token; + try { + const res = await fetch(`${baseUrl}/auth/profile/email`, { + headers: { + Accept: "application/json", + "Content-Type": "application/json", + Authorization: `Bearer ${sessionToken}` + }, + method: "PATCH", + body: JSON.stringify({ ...data }) + }); + + if (res.status === 200) { + return res; + } + } catch (e) { + console.log(e); + return false; + } +}; + +export { updateEmailPreferences }; diff --git a/pages/user/settings.tsx b/pages/user/settings.tsx index fdd3739ff..7cda4878a 100644 --- a/pages/user/settings.tsx +++ b/pages/user/settings.tsx @@ -9,7 +9,7 @@ const ProfileSettings = (): JSX.Element => { return ( <> {sessionToken ? ( -
+
) : ( From 92a1a23622f9fc92b87bf1e0d38efba80e406ac8 Mon Sep 17 00:00:00 2001 From: Sunday Ogbonna Date: Tue, 31 Jan 2023 18:50:32 +0100 Subject: [PATCH 22/25] refactor: cleanup anf fininshing touches --- .../UserSettingsPage/user-settings-page.tsx | 4 +--- lib/hooks/update-user.ts | 14 +++++++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/components/organisms/UserSettingsPage/user-settings-page.tsx b/components/organisms/UserSettingsPage/user-settings-page.tsx index 227b2b98d..37c1e628e 100644 --- a/components/organisms/UserSettingsPage/user-settings-page.tsx +++ b/components/organisms/UserSettingsPage/user-settings-page.tsx @@ -74,7 +74,6 @@ const UserSettingsPage = ({ user, sessionToken }: userSettingsPageProps) => { const handleUpdateInterest = async () => { const data = await updateUser({ - token: sessionToken || "", data: { interests: selectedInterest }, params: "interests" }); @@ -86,7 +85,6 @@ const UserSettingsPage = ({ user, sessionToken }: userSettingsPageProps) => { }; const handleUpdateProfile = async () => { const data = await updateUser({ - token: sessionToken || "", data: { email } }); if (data) { @@ -168,7 +166,7 @@ const UserSettingsPage = ({ user, sessionToken }: userSettingsPageProps) => { value={userInfo?.location || "Canada"} />
- + Other users will see the time difference from their local time. diff --git a/lib/hooks/update-user.ts b/lib/hooks/update-user.ts index e165bedec..6d0e16d6d 100644 --- a/lib/hooks/update-user.ts +++ b/lib/hooks/update-user.ts @@ -1,14 +1,22 @@ +import { supabase } from "lib/utils/supabase"; + interface useUpdateUserProps { - token: string; + data: { email?: string; interests?: string[] }; params?: string; } const baseUrl = process.env.NEXT_PUBLIC_API_URL; -const updateUser = async ({ token, data, params }: useUpdateUserProps) => { +const updateUser = async ({ data, params }: useUpdateUserProps) => { + const sessionResponse = await supabase.auth.getSession(); + const sessionToken = sessionResponse?.data.session?.access_token; try { const res = await fetch(`${baseUrl}/auth/profile${params ? `/${params}` : ""}`, { - headers: { Accept: "application/json", "Content-Type": "application/json", Authorization: `Bearer ${token}` }, + headers: { + Accept: "application/json", + "Content-Type": "application/json", + Authorization: `Bearer ${sessionToken}` + }, method: "PATCH", body: JSON.stringify({ ...data }) }); From 56c1607cc35e931f93d4fc3d9da436916f2240d0 Mon Sep 17 00:00:00 2001 From: Sunday Ogbonna Date: Tue, 31 Jan 2023 20:53:23 +0100 Subject: [PATCH 23/25] chore: general refactor and cleanup --- .../UserSettingsPage/user-settings-page.tsx | 19 +++++++++------ lib/hooks/authSession.ts | 24 +++++++++++++++++++ lib/hooks/update-user.ts | 7 +++--- lib/hooks/useAuthSession.ts | 15 ------------ pages/user/settings.tsx | 6 ++--- 5 files changed, 42 insertions(+), 29 deletions(-) create mode 100644 lib/hooks/authSession.ts delete mode 100644 lib/hooks/useAuthSession.ts diff --git a/components/organisms/UserSettingsPage/user-settings-page.tsx b/components/organisms/UserSettingsPage/user-settings-page.tsx index 37c1e628e..69f6a9b9f 100644 --- a/components/organisms/UserSettingsPage/user-settings-page.tsx +++ b/components/organisms/UserSettingsPage/user-settings-page.tsx @@ -12,7 +12,7 @@ import LanguagePill from "components/atoms/LanguagePill/LanguagePill"; import { updateUser } from "lib/hooks/update-user"; import { ToastTrigger } from "lib/utils/toast-trigger"; -import { useAuthSession } from "lib/hooks/useAuthSession"; +import { authSession } from "lib/hooks/authSession"; import { validateEmail } from "lib/utils/validate-email"; import { timezones } from "lib/utils/timezones"; import { updateEmailPreferences } from "lib/hooks/updateEmailPreference"; @@ -20,19 +20,18 @@ import { useFetchUser } from "lib/hooks/useFetchUser"; interface userSettingsPageProps { user: User | null; - sessionToken: string; } type EmailPreferenceType = { display_email?: boolean; receive_collaboration?: boolean; }; -const UserSettingsPage = ({ user, sessionToken }: userSettingsPageProps) => { +const UserSettingsPage = ({ user }: userSettingsPageProps) => { const { data: insightsUser } = useFetchUser(user?.user_metadata.user_name); - const { data: userInfo } = useAuthSession(); - const [isValidEmail, setIsValidEmail] = useState(false); - const [email, setEmail] = useState(user?.email); + const [isValidEmail, setIsValidEmail] = useState(true); + const [userInfo, setUserInfo] = useState(); + const [email, setEmail] = useState(userInfo?.email || user?.email); const [emailPreference, setEmailPreference] = useState({ // eslint-disable-next-line camelcase display_email: false, @@ -43,6 +42,11 @@ const UserSettingsPage = ({ user, sessionToken }: userSettingsPageProps) => { const interestArray = ["javascript", "python", "rust", "ML", "AI", "react"]; useEffect(() => { + async function fetchAuthSession() { + const response = await authSession(); + if (response !== false) setUserInfo(response); + } + if (user) setEmail(user.email); if (insightsUser) { setEmailPreference({ @@ -53,6 +57,7 @@ const UserSettingsPage = ({ user, sessionToken }: userSettingsPageProps) => { }); setSelectedInterest(insightsUser?.interests.split(",")); } + fetchAuthSession(); }, [user, insightsUser]); const handleSelectInterest = (interest: string) => { @@ -121,7 +126,7 @@ const UserSettingsPage = ({ user, sessionToken }: userSettingsPageProps) => { } }} label="Email*" - value={userInfo?.email || email} + value={email} /> {/* Bio section */} diff --git a/lib/hooks/authSession.ts b/lib/hooks/authSession.ts new file mode 100644 index 000000000..741799f88 --- /dev/null +++ b/lib/hooks/authSession.ts @@ -0,0 +1,24 @@ +import { supabase } from "lib/utils/supabase"; + +const baseUrl = process.env.NEXT_PUBLIC_API_URL; +export interface UserResponse extends DbUser {} +const authSession = async () => { + const sessionResponse = await supabase.auth.getSession(); + const sessionToken = sessionResponse?.data.session?.access_token; + // const { data, error } = useSWR("auth/session", publicApiFetcher as Fetcher); + const response = await fetch(`${baseUrl}/auth/session`, { + headers: { + Accept: "application/json", + "Content-Type": "application/json", + Authorization: `Bearer ${sessionToken}` + } + }); + + if (response.status === 200) { + return response.json(); + } else { + return false; + } +}; + +export { authSession }; diff --git a/lib/hooks/update-user.ts b/lib/hooks/update-user.ts index 6d0e16d6d..e771cebfd 100644 --- a/lib/hooks/update-user.ts +++ b/lib/hooks/update-user.ts @@ -1,13 +1,12 @@ import { supabase } from "lib/utils/supabase"; interface useUpdateUserProps { - data: { email?: string; interests?: string[] }; params?: string; } const baseUrl = process.env.NEXT_PUBLIC_API_URL; -const updateUser = async ({ data, params }: useUpdateUserProps) => { +const updateUser = async ({ data, params }: useUpdateUserProps) => { const sessionResponse = await supabase.auth.getSession(); const sessionToken = sessionResponse?.data.session?.access_token; try { @@ -22,12 +21,12 @@ const updateUser = async ({ data, params }: useUpdateUserProps) => { }); if (res.status === 200) { - return res.ok; + return res.json(); } else { return false; } } catch (e) { - console.log(e); + return false; } }; diff --git a/lib/hooks/useAuthSession.ts b/lib/hooks/useAuthSession.ts deleted file mode 100644 index 6b0d69ab9..000000000 --- a/lib/hooks/useAuthSession.ts +++ /dev/null @@ -1,15 +0,0 @@ -import publicApiFetcher from "lib/utils/public-api-fetcher"; -import useSWR, { Fetcher } from "swr"; - -export interface UserResponse extends DbUser {} -const useAuthSession = () => { - const { data, error } = useSWR("auth/session", publicApiFetcher as Fetcher); - - return { - data: data || undefined, - isLoading: !error && !data, - isError: !!error - }; -}; - -export { useAuthSession }; diff --git a/pages/user/settings.tsx b/pages/user/settings.tsx index 7cda4878a..2f11a98b2 100644 --- a/pages/user/settings.tsx +++ b/pages/user/settings.tsx @@ -4,13 +4,13 @@ import UserSettingsPage from "components/organisms/UserSettingsPage/user-setting import ProfileLayout from "layouts/profile"; const ProfileSettings = (): JSX.Element => { - const { sessionToken, user } = useSupabaseAuth(); + const { user } = useSupabaseAuth(); return ( <> - {sessionToken ? ( + {user ? (
- +
) : ( "" From 92f13b2572e01285b03659e0d88f8c46894e0940 Mon Sep 17 00:00:00 2001 From: Sunday Ogbonna Date: Tue, 31 Jan 2023 20:53:47 +0100 Subject: [PATCH 24/25] chore: update api call response --- lib/hooks/updateEmailPreference.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/hooks/updateEmailPreference.ts b/lib/hooks/updateEmailPreference.ts index 55994b4da..7c33d9869 100644 --- a/lib/hooks/updateEmailPreference.ts +++ b/lib/hooks/updateEmailPreference.ts @@ -21,10 +21,9 @@ const updateEmailPreferences = async (data: UpdateEmailProps) => { }); if (res.status === 200) { - return res; + return res.json(); } } catch (e) { - console.log(e); return false; } }; From f240786a2ac794da96b49d07531ef0f2bc2cff0e Mon Sep 17 00:00:00 2001 From: Sunday Ogbonna Date: Tue, 31 Jan 2023 21:18:59 +0100 Subject: [PATCH 25/25] fix: build error --- stories/organisms/user-settings-page.stories.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/stories/organisms/user-settings-page.stories.tsx b/stories/organisms/user-settings-page.stories.tsx index 94ebdc480..e579832b7 100644 --- a/stories/organisms/user-settings-page.stories.tsx +++ b/stories/organisms/user-settings-page.stories.tsx @@ -6,8 +6,6 @@ const StoryConfig = { }; export default StoryConfig; -const UserSettingsPageTemplate: ComponentStory = () => ( - -); +const UserSettingsPageTemplate: ComponentStory = () => ; export const Default = UserSettingsPageTemplate.bind({});