From 148176a91dc751bcfd24ef95888c225c3e4b24cc Mon Sep 17 00:00:00 2001 From: ksjaay Date: Sat, 18 May 2024 17:06:36 +0100 Subject: [PATCH 01/28] Addss console.log and updates package version --- app/handlers/login.js | 2 + app/handlers/monitor.js | 1 + app/handlers/register.js | 1 + app/hooks/useGraphStatus.jsx | 1 + app/hooks/useRegister.jsx | 1 + app/layout/global.jsx | 1 + package-lock.json | 124 ++++++++++++++++++++++++++++++++++- package.json | 2 +- 8 files changed, 130 insertions(+), 3 deletions(-) diff --git a/app/handlers/login.js b/app/handlers/login.js index 6fe47d3..a445bcb 100644 --- a/app/handlers/login.js +++ b/app/handlers/login.js @@ -22,6 +22,8 @@ const handleLogin = async (inputs, setErrors, navigate) => { return navigate('/'); } } catch (error) { + console.log(error); + if (error.response?.status === 418) { return navigate('/verify'); } diff --git a/app/handlers/monitor.js b/app/handlers/monitor.js index 378ddd5..9831d7d 100644 --- a/app/handlers/monitor.js +++ b/app/handlers/monitor.js @@ -36,6 +36,7 @@ const handleMonitor = async (form, isEdit, closeModal, setMonitor) => { toast.success(`Monitor been ${isEdit ? 'added' : 'edited'} successfully`); return closeModal(); } catch (error) { + console.log(error); toast.error('Something went wrong, please try again later.'); } }; diff --git a/app/handlers/register.js b/app/handlers/register.js index afedf8e..2732f56 100644 --- a/app/handlers/register.js +++ b/app/handlers/register.js @@ -33,6 +33,7 @@ const handleRegister = async (inputs, setErrors, setPage, navigate) => { setPage('verify'); } catch (error) { + console.log(error); if (error?.response?.data?.message) { return setErrors(error?.response?.data?.message); } diff --git a/app/hooks/useGraphStatus.jsx b/app/hooks/useGraphStatus.jsx index 6eacf96..caa5a10 100644 --- a/app/hooks/useGraphStatus.jsx +++ b/app/hooks/useGraphStatus.jsx @@ -21,6 +21,7 @@ const useGraphStatus = (monitor = {}) => { return setStatusHeartbeats(query.data); } } catch (error) { + console.log(error); toast.error('Failed to fetch monitor heartbeats'); } }; diff --git a/app/hooks/useRegister.jsx b/app/hooks/useRegister.jsx index beba6f3..7414302 100644 --- a/app/hooks/useRegister.jsx +++ b/app/hooks/useRegister.jsx @@ -47,6 +47,7 @@ const useRegister = () => { })); } } catch (error) { + console.log(error); return toast.error('Error occurred while checking if email exists.'); } } diff --git a/app/layout/global.jsx b/app/layout/global.jsx index ea4a4b3..3369927 100644 --- a/app/layout/global.jsx +++ b/app/layout/global.jsx @@ -36,6 +36,7 @@ const GlobalLayout = ({ children }) => { setMonitors(data); setTimeouts(data, fetchMonitorById); } catch (error) { + console.log(error); if (error.response?.status === 401) { return navigate('/login'); } diff --git a/package-lock.json b/package-lock.json index e0d7fbf..1c578ea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "lunalytics", - "version": "0.4.7", + "version": "0.5.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "lunalytics", - "version": "0.4.7", + "version": "0.5.0", "license": "SEE LICENSE IN LICENSE", "dependencies": { "axios": "^1.6.2", @@ -1260,6 +1260,14 @@ "node": ">= 8" } }, + "node_modules/@polka/url": { + "version": "1.0.0-next.25", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.25.tgz", + "integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==", + "dev": true, + "optional": true, + "peer": true + }, "node_modules/@remix-run/router": { "version": "1.15.1", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.1.tgz", @@ -1694,6 +1702,29 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/@vitest/ui": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-1.6.0.tgz", + "integrity": "sha512-k3Lyo+ONLOgylctiGovRKy7V4+dIN2yxstX3eY5cWFXH6WP+ooVX79YSyi0GagdTQzLmT43BF27T0s6dOIPBXA==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "@vitest/utils": "1.6.0", + "fast-glob": "^3.3.2", + "fflate": "^0.8.1", + "flatted": "^3.2.9", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "sirv": "^2.0.4" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": "1.6.0" + } + }, "node_modules/@vitest/utils": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.0.tgz", @@ -4707,6 +4738,38 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -4741,6 +4804,14 @@ "pend": "~1.2.0" } }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "dev": true, + "optional": true, + "peer": true + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -7272,6 +7343,17 @@ "dev": true, "license": "MIT" }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "optional": true, + "peer": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -7497,6 +7579,17 @@ "node": "*" } }, + "node_modules/mrmime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", + "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", + "dev": true, + "optional": true, + "peer": true, + "engines": { + "node": ">=10" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -9309,6 +9402,22 @@ "node": ">=10" } }, + "node_modules/sirv": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/slice-ansi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", @@ -9894,6 +10003,17 @@ "node": ">=0.6" } }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true, + "optional": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/touch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", diff --git a/package.json b/package.json index bd1e250..d4cb606 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lunalytics", - "version": "0.4.7", + "version": "0.5.0", "description": "Open source Node.js server/website monitoring tool", "private": true, "author": "KSJaay ", From 5b9343fbe6cd00140d0095922b2ea14c967d6b9f Mon Sep 17 00:00:00 2001 From: ksjaay Date: Sat, 18 May 2024 21:15:32 +0100 Subject: [PATCH 02/28] Rework timezones constants file --- app/constant/timeformats.json | 1698 --------------------------------- app/constant/timezones.json | 426 +++++++++ 2 files changed, 426 insertions(+), 1698 deletions(-) delete mode 100644 app/constant/timeformats.json create mode 100644 app/constant/timezones.json diff --git a/app/constant/timeformats.json b/app/constant/timeformats.json deleted file mode 100644 index 63ba729..0000000 --- a/app/constant/timeformats.json +++ /dev/null @@ -1,1698 +0,0 @@ -[ - { - "name": "Pacific/Midway (GMT-11:00)", - "value": "Pacific/Midway" - }, - { - "name": "Pacific/Niue (GMT-11:00)", - "value": "Pacific/Niue" - }, - { - "name": "Pacific/Pago_Pago (GMT-11:00)", - "value": "Pacific/Pago_Pago" - }, - { - "name": "America/Adak (GMT-10:00)", - "value": "America/Adak" - }, - { - "name": "Pacific/Honolulu (GMT-10:00)", - "value": "Pacific/Honolulu" - }, - { - "name": "Pacific/Rarotonga (GMT-10:00)", - "value": "Pacific/Rarotonga" - }, - { - "name": "Pacific/Tahiti (GMT-10:00)", - "value": "Pacific/Tahiti" - }, - { - "name": "Pacific/Marquesas (GMT-09:30)", - "value": "Pacific/Marquesas" - }, - { - "name": "America/Anchorage (GMT-09:00)", - "value": "America/Anchorage" - }, - { - "name": "America/Juneau (GMT-09:00)", - "value": "America/Juneau" - }, - { - "name": "America/Metlakatla (GMT-09:00)", - "value": "America/Metlakatla" - }, - { - "name": "America/Nome (GMT-09:00)", - "value": "America/Nome" - }, - { - "name": "America/Sitka (GMT-09:00)", - "value": "America/Sitka" - }, - { - "name": "America/Yakutat (GMT-09:00)", - "value": "America/Yakutat" - }, - { - "name": "Pacific/Gambier (GMT-09:00)", - "value": "Pacific/Gambier" - }, - { - "name": "America/Los_Angeles (GMT-08:00)", - "value": "America/Los_Angeles" - }, - { - "name": "America/Tijuana (GMT-08:00)", - "value": "America/Tijuana" - }, - { - "name": "America/Vancouver (GMT-08:00)", - "value": "America/Vancouver" - }, - { - "name": "Pacific/Pitcairn (GMT-08:00)", - "value": "Pacific/Pitcairn" - }, - { - "name": "America/Boise (GMT-07:00)", - "value": "America/Boise" - }, - { - "name": "America/Cambridge_Bay (GMT-07:00)", - "value": "America/Cambridge_Bay" - }, - { - "name": "America/Chihuahua (GMT-07:00)", - "value": "America/Chihuahua" - }, - { - "name": "America/Creston (GMT-07:00)", - "value": "America/Creston" - }, - { - "name": "America/Dawson (GMT-07:00)", - "value": "America/Dawson" - }, - { - "name": "America/Dawson_Creek (GMT-07:00)", - "value": "America/Dawson_Creek" - }, - { - "name": "America/Denver (GMT-07:00)", - "value": "America/Denver" - }, - { - "name": "America/Edmonton (GMT-07:00)", - "value": "America/Edmonton" - }, - { - "name": "America/Fort_Nelson (GMT-07:00)", - "value": "America/Fort_Nelson" - }, - { - "name": "America/Hermosillo (GMT-07:00)", - "value": "America/Hermosillo" - }, - { - "name": "America/Inuvik (GMT-07:00)", - "value": "America/Inuvik" - }, - { - "name": "America/Mazatlan (GMT-07:00)", - "value": "America/Mazatlan" - }, - { - "name": "America/Ojinaga (GMT-07:00)", - "value": "America/Ojinaga" - }, - { - "name": "America/Phoenix (GMT-07:00)", - "value": "America/Phoenix" - }, - { - "name": "America/Whitehorse (GMT-07:00)", - "value": "America/Whitehorse" - }, - { - "name": "America/Yellowknife (GMT-07:00)", - "value": "America/Yellowknife" - }, - { - "name": "America/Bahia_Banderas (GMT-06:00)", - "value": "America/Bahia_Banderas" - }, - { - "name": "America/Belize (GMT-06:00)", - "value": "America/Belize" - }, - { - "name": "America/Chicago (GMT-06:00)", - "value": "America/Chicago" - }, - { - "name": "America/Costa_Rica (GMT-06:00)", - "value": "America/Costa_Rica" - }, - { - "name": "America/El_Salvador (GMT-06:00)", - "value": "America/El_Salvador" - }, - { - "name": "America/Guatemala (GMT-06:00)", - "value": "America/Guatemala" - }, - { - "name": "America/Indiana/Knox (GMT-06:00)", - "value": "America/Indiana/Knox" - }, - { - "name": "America/Indiana/Tell_City (GMT-06:00)", - "value": "America/Indiana/Tell_City" - }, - { - "name": "America/Managua (GMT-06:00)", - "value": "America/Managua" - }, - { - "name": "America/Matamoros (GMT-06:00)", - "value": "America/Matamoros" - }, - { - "name": "America/Menominee (GMT-06:00)", - "value": "America/Menominee" - }, - { - "name": "America/Merida (GMT-06:00)", - "value": "America/Merida" - }, - { - "name": "America/Mexico_City (GMT-06:00)", - "value": "America/Mexico_City" - }, - { - "name": "America/Monterrey (GMT-06:00)", - "value": "America/Monterrey" - }, - { - "name": "America/North_Dakota/Beulah (GMT-06:00)", - "value": "America/North_Dakota/Beulah" - }, - { - "name": "America/North_Dakota/Center (GMT-06:00)", - "value": "America/North_Dakota/Center" - }, - { - "name": "America/North_Dakota/New_Salem (GMT-06:00)", - "value": "America/North_Dakota/New_Salem" - }, - { - "name": "America/Rainy_River (GMT-06:00)", - "value": "America/Rainy_River" - }, - { - "name": "America/Rankin_Inlet (GMT-06:00)", - "value": "America/Rankin_Inlet" - }, - { - "name": "America/Regina (GMT-06:00)", - "value": "America/Regina" - }, - { - "name": "America/Resolute (GMT-06:00)", - "value": "America/Resolute" - }, - { - "name": "America/Swift_Current (GMT-06:00)", - "value": "America/Swift_Current" - }, - { - "name": "America/Tegucigalpa (GMT-06:00)", - "value": "America/Tegucigalpa" - }, - { - "name": "America/Winnipeg (GMT-06:00)", - "value": "America/Winnipeg" - }, - { - "name": "Pacific/Easter (GMT-06:00)", - "value": "Pacific/Easter" - }, - { - "name": "Pacific/Galapagos (GMT-06:00)", - "value": "Pacific/Galapagos" - }, - { - "name": "America/Atikokan (GMT-05:00)", - "value": "America/Atikokan" - }, - { - "name": "America/Bogota (GMT-05:00)", - "value": "America/Bogota" - }, - { - "name": "America/Cancun (GMT-05:00)", - "value": "America/Cancun" - }, - { - "name": "America/Cayman (GMT-05:00)", - "value": "America/Cayman" - }, - { - "name": "America/Detroit (GMT-05:00)", - "value": "America/Detroit" - }, - { - "name": "America/Eirunepe (GMT-05:00)", - "value": "America/Eirunepe" - }, - { - "name": "America/Grand_Turk (GMT-05:00)", - "value": "America/Grand_Turk" - }, - { - "name": "America/Guayaquil (GMT-05:00)", - "value": "America/Guayaquil" - }, - { - "name": "America/Havana (GMT-05:00)", - "value": "America/Havana" - }, - { - "name": "America/Indiana/Indianapolis (GMT-05:00)", - "value": "America/Indiana/Indianapolis" - }, - { - "name": "America/Indiana/Marengo (GMT-05:00)", - "value": "America/Indiana/Marengo" - }, - { - "name": "America/Indiana/Petersburg (GMT-05:00)", - "value": "America/Indiana/Petersburg" - }, - { - "name": "America/Indiana/Vevay (GMT-05:00)", - "value": "America/Indiana/Vevay" - }, - { - "name": "America/Indiana/Vincennes (GMT-05:00)", - "value": "America/Indiana/Vincennes" - }, - { - "name": "America/Indiana/Winamac (GMT-05:00)", - "value": "America/Indiana/Winamac" - }, - { - "name": "America/Iqaluit (GMT-05:00)", - "value": "America/Iqaluit" - }, - { - "name": "America/Jamaica (GMT-05:00)", - "value": "America/Jamaica" - }, - { - "name": "America/Kentucky/Louisville (GMT-05:00)", - "value": "America/Kentucky/Louisville" - }, - { - "name": "America/Kentucky/Monticello (GMT-05:00)", - "value": "America/Kentucky/Monticello" - }, - { - "name": "America/Lima (GMT-05:00)", - "value": "America/Lima" - }, - { - "name": "America/Nassau (GMT-05:00)", - "value": "America/Nassau" - }, - { - "name": "America/New_York (GMT-05:00)", - "value": "America/New_York" - }, - { - "name": "America/Nipigon (GMT-05:00)", - "value": "America/Nipigon" - }, - { - "name": "America/Panama (GMT-05:00)", - "value": "America/Panama" - }, - { - "name": "America/Pangnirtung (GMT-05:00)", - "value": "America/Pangnirtung" - }, - { - "name": "America/Port-au-Prince (GMT-05:00)", - "value": "America/Port-au-Prince" - }, - { - "name": "America/Rio_Branco (GMT-05:00)", - "value": "America/Rio_Branco" - }, - { - "name": "America/Thunder_Bay (GMT-05:00)", - "value": "America/Thunder_Bay" - }, - { - "name": "America/Toronto (GMT-05:00)", - "value": "America/Toronto" - }, - { - "name": "America/Anguilla (GMT-04:00)", - "value": "America/Anguilla" - }, - { - "name": "America/Antigua (GMT-04:00)", - "value": "America/Antigua" - }, - { - "name": "America/Aruba (GMT-04:00)", - "value": "America/Aruba" - }, - { - "name": "America/Asuncion (GMT-04:00)", - "value": "America/Asuncion" - }, - { - "name": "America/Barbados (GMT-04:00)", - "value": "America/Barbados" - }, - { - "name": "America/Blanc-Sablon (GMT-04:00)", - "value": "America/Blanc-Sablon" - }, - { - "name": "America/Boa_Vista (GMT-04:00)", - "value": "America/Boa_Vista" - }, - { - "name": "America/Campo_Grande (GMT-04:00)", - "value": "America/Campo_Grande" - }, - { - "name": "America/Caracas (GMT-04:00)", - "value": "America/Caracas" - }, - { - "name": "America/Cuiaba (GMT-04:00)", - "value": "America/Cuiaba" - }, - { - "name": "America/Curacao (GMT-04:00)", - "value": "America/Curacao" - }, - { - "name": "America/Dominica (GMT-04:00)", - "value": "America/Dominica" - }, - { - "name": "America/Glace_Bay (GMT-04:00)", - "value": "America/Glace_Bay" - }, - { - "name": "America/Goose_Bay (GMT-04:00)", - "value": "America/Goose_Bay" - }, - { - "name": "America/Grenada (GMT-04:00)", - "value": "America/Grenada" - }, - { - "name": "America/Guadeloupe (GMT-04:00)", - "value": "America/Guadeloupe" - }, - { - "name": "America/Guyana (GMT-04:00)", - "value": "America/Guyana" - }, - { - "name": "America/Halifax (GMT-04:00)", - "value": "America/Halifax" - }, - { - "name": "America/Kralendijk (GMT-04:00)", - "value": "America/Kralendijk" - }, - { - "name": "America/La_Paz (GMT-04:00)", - "value": "America/La_Paz" - }, - { - "name": "America/Lower_Princes (GMT-04:00)", - "value": "America/Lower_Princes" - }, - { - "name": "America/Manaus (GMT-04:00)", - "value": "America/Manaus" - }, - { - "name": "America/Marigot (GMT-04:00)", - "value": "America/Marigot" - }, - { - "name": "America/Martinique (GMT-04:00)", - "value": "America/Martinique" - }, - { - "name": "America/Moncton (GMT-04:00)", - "value": "America/Moncton" - }, - { - "name": "America/Montserrat (GMT-04:00)", - "value": "America/Montserrat" - }, - { - "name": "America/Porto_Velho (GMT-04:00)", - "value": "America/Porto_Velho" - }, - { - "name": "America/Port_of_Spain (GMT-04:00)", - "value": "America/Port_of_Spain" - }, - { - "name": "America/Puerto_Rico (GMT-04:00)", - "value": "America/Puerto_Rico" - }, - { - "name": "America/Santiago (GMT-04:00)", - "value": "America/Santiago" - }, - { - "name": "America/Santo_Domingo (GMT-04:00)", - "value": "America/Santo_Domingo" - }, - { - "name": "America/St_Barthelemy (GMT-04:00)", - "value": "America/St_Barthelemy" - }, - { - "name": "America/St_Kitts (GMT-04:00)", - "value": "America/St_Kitts" - }, - { - "name": "America/St_Lucia (GMT-04:00)", - "value": "America/St_Lucia" - }, - { - "name": "America/St_Thomas (GMT-04:00)", - "value": "America/St_Thomas" - }, - { - "name": "America/St_Vincent (GMT-04:00)", - "value": "America/St_Vincent" - }, - { - "name": "America/Thule (GMT-04:00)", - "value": "America/Thule" - }, - { - "name": "America/Tortola (GMT-04:00)", - "value": "America/Tortola" - }, - { - "name": "Atlantic/Bermuda (GMT-04:00)", - "value": "Atlantic/Bermuda" - }, - { - "name": "America/St_Johns (GMT-03:30)", - "value": "America/St_Johns" - }, - { - "name": "America/Araguaina (GMT-03:00)", - "value": "America/Araguaina" - }, - { - "name": "America/Argentina/Buenos_Aires (GMT-03:00)", - "value": "America/Argentina/Buenos_Aires" - }, - { - "name": "America/Argentina/Catamarca (GMT-03:00)", - "value": "America/Argentina/Catamarca" - }, - { - "name": "America/Argentina/Cordoba (GMT-03:00)", - "value": "America/Argentina/Cordoba" - }, - { - "name": "America/Argentina/Jujuy (GMT-03:00)", - "value": "America/Argentina/Jujuy" - }, - { - "name": "America/Argentina/La_Rioja (GMT-03:00)", - "value": "America/Argentina/La_Rioja" - }, - { - "name": "America/Argentina/Mendoza (GMT-03:00)", - "value": "America/Argentina/Mendoza" - }, - { - "name": "America/Argentina/Rio_Gallegos (GMT-03:00)", - "value": "America/Argentina/Rio_Gallegos" - }, - { - "name": "America/Argentina/Salta (GMT-03:00)", - "value": "America/Argentina/Salta" - }, - { - "name": "America/Argentina/San_Juan (GMT-03:00)", - "value": "America/Argentina/San_Juan" - }, - { - "name": "America/Argentina/San_Luis (GMT-03:00)", - "value": "America/Argentina/San_Luis" - }, - { - "name": "America/Argentina/Tucuman (GMT-03:00)", - "value": "America/Argentina/Tucuman" - }, - { - "name": "America/Argentina/Ushuaia (GMT-03:00)", - "value": "America/Argentina/Ushuaia" - }, - { - "name": "America/Bahia (GMT-03:00)", - "value": "America/Bahia" - }, - { - "name": "America/Belem (GMT-03:00)", - "value": "America/Belem" - }, - { - "name": "America/Cayenne (GMT-03:00)", - "value": "America/Cayenne" - }, - { - "name": "America/Fortaleza (GMT-03:00)", - "value": "America/Fortaleza" - }, - { - "name": "America/Godthab (GMT-03:00)", - "value": "America/Godthab" - }, - { - "name": "America/Maceio (GMT-03:00)", - "value": "America/Maceio" - }, - { - "name": "America/Miquelon (GMT-03:00)", - "value": "America/Miquelon" - }, - { - "name": "America/Montevideo (GMT-03:00)", - "value": "America/Montevideo" - }, - { - "name": "America/Paramaribo (GMT-03:00)", - "value": "America/Paramaribo" - }, - { - "name": "America/Punta_Arenas (GMT-03:00)", - "value": "America/Punta_Arenas" - }, - { - "name": "America/Recife (GMT-03:00)", - "value": "America/Recife" - }, - { - "name": "America/Santarem (GMT-03:00)", - "value": "America/Santarem" - }, - { - "name": "America/Sao_Paulo (GMT-03:00)", - "value": "America/Sao_Paulo" - }, - { - "name": "Antarctica/Palmer (GMT-03:00)", - "value": "Antarctica/Palmer" - }, - { - "name": "Antarctica/Rothera (GMT-03:00)", - "value": "Antarctica/Rothera" - }, - { - "name": "Atlantic/Stanley (GMT-03:00)", - "value": "Atlantic/Stanley" - }, - { - "name": "America/Noronha (GMT-02:00)", - "value": "America/Noronha" - }, - { - "name": "Atlantic/South_Georgia (GMT-02:00)", - "value": "Atlantic/South_Georgia" - }, - { - "name": "America/Scoresbysund (GMT-01:00)", - "value": "America/Scoresbysund" - }, - { - "name": "Atlantic/Azores (GMT-01:00)", - "value": "Atlantic/Azores" - }, - { - "name": "Atlantic/Cape_Verde (GMT-01:00)", - "value": "Atlantic/Cape_Verde" - }, - { - "name": "Africa/Abidjan (GMT+00:00)", - "value": "Africa/Abidjan" - }, - { - "name": "Africa/Accra (GMT+00:00)", - "value": "Africa/Accra" - }, - { - "name": "Africa/Bamako (GMT+00:00)", - "value": "Africa/Bamako" - }, - { - "name": "Africa/Banjul (GMT+00:00)", - "value": "Africa/Banjul" - }, - { - "name": "Africa/Bissau (GMT+00:00)", - "value": "Africa/Bissau" - }, - { - "name": "Africa/Casablanca (GMT+00:00)", - "value": "Africa/Casablanca" - }, - { - "name": "Africa/Conakry (GMT+00:00)", - "value": "Africa/Conakry" - }, - { - "name": "Africa/Dakar (GMT+00:00)", - "value": "Africa/Dakar" - }, - { - "name": "Africa/El_Aaiun (GMT+00:00)", - "value": "Africa/El_Aaiun" - }, - { - "name": "Africa/Freetown (GMT+00:00)", - "value": "Africa/Freetown" - }, - { - "name": "Africa/Lome (GMT+00:00)", - "value": "Africa/Lome" - }, - { - "name": "Africa/Monrovia (GMT+00:00)", - "value": "Africa/Monrovia" - }, - { - "name": "Africa/Nouakchott (GMT+00:00)", - "value": "Africa/Nouakchott" - }, - { - "name": "Africa/Ouagadougou (GMT+00:00)", - "value": "Africa/Ouagadougou" - }, - { - "name": "Africa/Sao_Tome (GMT+00:00)", - "value": "Africa/Sao_Tome" - }, - { - "name": "America/Danmarkshavn (GMT+00:00)", - "value": "America/Danmarkshavn" - }, - { - "name": "Antarctica/Troll (GMT+00:00)", - "value": "Antarctica/Troll" - }, - { - "name": "Atlantic/Canary (GMT+00:00)", - "value": "Atlantic/Canary" - }, - { - "name": "Atlantic/Faroe (GMT+00:00)", - "value": "Atlantic/Faroe" - }, - { - "name": "Atlantic/Madeira (GMT+00:00)", - "value": "Atlantic/Madeira" - }, - { - "name": "Atlantic/Reykjavik (GMT+00:00)", - "value": "Atlantic/Reykjavik" - }, - { - "name": "Atlantic/St_Helena (GMT+00:00)", - "value": "Atlantic/St_Helena" - }, - { - "name": "Europe/Dublin (GMT+00:00)", - "value": "Europe/Dublin" - }, - { - "name": "Europe/Guernsey (GMT+00:00)", - "value": "Europe/Guernsey" - }, - { - "name": "Europe/Isle_of_Man (GMT+00:00)", - "value": "Europe/Isle_of_Man" - }, - { - "name": "Europe/Jersey (GMT+00:00)", - "value": "Europe/Jersey" - }, - { - "name": "Europe/Lisbon (GMT+00:00)", - "value": "Europe/Lisbon" - }, - { - "name": "Europe/London (GMT+00:00)", - "value": "Europe/London" - }, - { - "name": "Africa/Algiers (GMT+01:00)", - "value": "Africa/Algiers" - }, - { - "name": "Africa/Bangui (GMT+01:00)", - "value": "Africa/Bangui" - }, - { - "name": "Africa/Brazzaville (GMT+01:00)", - "value": "Africa/Brazzaville" - }, - { - "name": "Africa/Ceuta (GMT+01:00)", - "value": "Africa/Ceuta" - }, - { - "name": "Africa/Douala (GMT+01:00)", - "value": "Africa/Douala" - }, - { - "name": "Africa/Kinshasa (GMT+01:00)", - "value": "Africa/Kinshasa" - }, - { - "name": "Africa/Lagos (GMT+01:00)", - "value": "Africa/Lagos" - }, - { - "name": "Africa/Libreville (GMT+01:00)", - "value": "Africa/Libreville" - }, - { - "name": "Africa/Luanda (GMT+01:00)", - "value": "Africa/Luanda" - }, - { - "name": "Africa/Malabo (GMT+01:00)", - "value": "Africa/Malabo" - }, - { - "name": "Africa/Ndjamena (GMT+01:00)", - "value": "Africa/Ndjamena" - }, - { - "name": "Africa/Niamey (GMT+01:00)", - "value": "Africa/Niamey" - }, - { - "name": "Africa/Porto-Novo (GMT+01:00)", - "value": "Africa/Porto-Novo" - }, - { - "name": "Africa/Tunis (GMT+01:00)", - "value": "Africa/Tunis" - }, - { - "name": "Africa/Windhoek (GMT+01:00)", - "value": "Africa/Windhoek" - }, - { - "name": "Arctic/Longyearbyen (GMT+01:00)", - "value": "Arctic/Longyearbyen" - }, - { - "name": "Europe/Amsterdam (GMT+01:00)", - "value": "Europe/Amsterdam" - }, - { - "name": "Europe/Andorra (GMT+01:00)", - "value": "Europe/Andorra" - }, - { - "name": "Europe/Belgrade (GMT+01:00)", - "value": "Europe/Belgrade" - }, - { - "name": "Europe/Berlin (GMT+01:00)", - "value": "Europe/Berlin" - }, - { - "name": "Europe/Bratislava (GMT+01:00)", - "value": "Europe/Bratislava" - }, - { - "name": "Europe/Brussels (GMT+01:00)", - "value": "Europe/Brussels" - }, - { - "name": "Europe/Budapest (GMT+01:00)", - "value": "Europe/Budapest" - }, - { - "name": "Europe/Copenhagen (GMT+01:00)", - "value": "Europe/Copenhagen" - }, - { - "name": "Europe/Gibraltar (GMT+01:00)", - "value": "Europe/Gibraltar" - }, - { - "name": "Europe/Ljubljana (GMT+01:00)", - "value": "Europe/Ljubljana" - }, - { - "name": "Europe/Luxembourg (GMT+01:00)", - "value": "Europe/Luxembourg" - }, - { - "name": "Europe/Madrid (GMT+01:00)", - "value": "Europe/Madrid" - }, - { - "name": "Europe/Malta (GMT+01:00)", - "value": "Europe/Malta" - }, - { - "name": "Europe/Monaco (GMT+01:00)", - "value": "Europe/Monaco" - }, - { - "name": "Europe/Oslo (GMT+01:00)", - "value": "Europe/Oslo" - }, - { - "name": "Europe/Paris (GMT+01:00)", - "value": "Europe/Paris" - }, - { - "name": "Europe/Podgorica (GMT+01:00)", - "value": "Europe/Podgorica" - }, - { - "name": "Europe/Prague (GMT+01:00)", - "value": "Europe/Prague" - }, - { - "name": "Europe/Rome (GMT+01:00)", - "value": "Europe/Rome" - }, - { - "name": "Europe/San_Marino (GMT+01:00)", - "value": "Europe/San_Marino" - }, - { - "name": "Europe/Sarajevo (GMT+01:00)", - "value": "Europe/Sarajevo" - }, - { - "name": "Europe/Skopje (GMT+01:00)", - "value": "Europe/Skopje" - }, - { - "name": "Europe/Stockholm (GMT+01:00)", - "value": "Europe/Stockholm" - }, - { - "name": "Europe/Tirane (GMT+01:00)", - "value": "Europe/Tirane" - }, - { - "name": "Europe/Vaduz (GMT+01:00)", - "value": "Europe/Vaduz" - }, - { - "name": "Europe/Vatican (GMT+01:00)", - "value": "Europe/Vatican" - }, - { - "name": "Europe/Vienna (GMT+01:00)", - "value": "Europe/Vienna" - }, - { - "name": "Europe/Warsaw (GMT+01:00)", - "value": "Europe/Warsaw" - }, - { - "name": "Europe/Zagreb (GMT+01:00)", - "value": "Europe/Zagreb" - }, - { - "name": "Europe/Zurich (GMT+01:00)", - "value": "Europe/Zurich" - }, - { - "name": "Africa/Blantyre (GMT+02:00)", - "value": "Africa/Blantyre" - }, - { - "name": "Africa/Bujumbura (GMT+02:00)", - "value": "Africa/Bujumbura" - }, - { - "name": "Africa/Cairo (GMT+02:00)", - "value": "Africa/Cairo" - }, - { - "name": "Africa/Gaborone (GMT+02:00)", - "value": "Africa/Gaborone" - }, - { - "name": "Africa/Harare (GMT+02:00)", - "value": "Africa/Harare" - }, - { - "name": "Africa/Johannesburg (GMT+02:00)", - "value": "Africa/Johannesburg" - }, - { - "name": "Africa/Juba (GMT+02:00)", - "value": "Africa/Juba" - }, - { - "name": "Africa/Khartoum (GMT+02:00)", - "value": "Africa/Khartoum" - }, - { - "name": "Africa/Kigali (GMT+02:00)", - "value": "Africa/Kigali" - }, - { - "name": "Africa/Lubumbashi (GMT+02:00)", - "value": "Africa/Lubumbashi" - }, - { - "name": "Africa/Lusaka (GMT+02:00)", - "value": "Africa/Lusaka" - }, - { - "name": "Africa/Maputo (GMT+02:00)", - "value": "Africa/Maputo" - }, - { - "name": "Africa/Maseru (GMT+02:00)", - "value": "Africa/Maseru" - }, - { - "name": "Africa/Mbabane (GMT+02:00)", - "value": "Africa/Mbabane" - }, - { - "name": "Africa/Tripoli (GMT+02:00)", - "value": "Africa/Tripoli" - }, - { - "name": "Asia/Amman (GMT+02:00)", - "value": "Asia/Amman" - }, - { - "name": "Asia/Beirut (GMT+02:00)", - "value": "Asia/Beirut" - }, - { - "name": "Asia/Damascus (GMT+02:00)", - "value": "Asia/Damascus" - }, - { - "name": "Asia/Famagusta (GMT+02:00)", - "value": "Asia/Famagusta" - }, - { - "name": "Asia/Gaza (GMT+02:00)", - "value": "Asia/Gaza" - }, - { - "name": "Asia/Hebron (GMT+02:00)", - "value": "Asia/Hebron" - }, - { - "name": "Asia/Jerusalem (GMT+02:00)", - "value": "Asia/Jerusalem" - }, - { - "name": "Asia/Nicosia (GMT+02:00)", - "value": "Asia/Nicosia" - }, - { - "name": "Europe/Athens (GMT+02:00)", - "value": "Europe/Athens" - }, - { - "name": "Europe/Bucharest (GMT+02:00)", - "value": "Europe/Bucharest" - }, - { - "name": "Europe/Chisinau (GMT+02:00)", - "value": "Europe/Chisinau" - }, - { - "name": "Europe/Helsinki (GMT+02:00)", - "value": "Europe/Helsinki" - }, - { - "name": "Europe/Kaliningrad (GMT+02:00)", - "value": "Europe/Kaliningrad" - }, - { - "name": "Europe/Kyiv (GMT+02:00)", - "value": "Europe/Kyiv" - }, - { - "name": "Europe/Mariehamn (GMT+02:00)", - "value": "Europe/Mariehamn" - }, - { - "name": "Europe/Riga (GMT+02:00)", - "value": "Europe/Riga" - }, - { - "name": "Europe/Sofia (GMT+02:00)", - "value": "Europe/Sofia" - }, - { - "name": "Europe/Tallinn (GMT+02:00)", - "value": "Europe/Tallinn" - }, - { - "name": "Europe/Uzhgorod (GMT+02:00)", - "value": "Europe/Uzhgorod" - }, - { - "name": "Europe/Vilnius (GMT+02:00)", - "value": "Europe/Vilnius" - }, - { - "name": "Europe/Zaporozhye (GMT+02:00)", - "value": "Europe/Zaporozhye" - }, - { - "name": "Africa/Addis_Ababa (GMT+03:00)", - "value": "Africa/Addis_Ababa" - }, - { - "name": "Africa/Asmara (GMT+03:00)", - "value": "Africa/Asmara" - }, - { - "name": "Africa/Dar_es_Salaam (GMT+03:00)", - "value": "Africa/Dar_es_Salaam" - }, - { - "name": "Africa/Djibouti (GMT+03:00)", - "value": "Africa/Djibouti" - }, - { - "name": "Africa/Kampala (GMT+03:00)", - "value": "Africa/Kampala" - }, - { - "name": "Africa/Mogadishu (GMT+03:00)", - "value": "Africa/Mogadishu" - }, - { - "name": "Africa/Nairobi (GMT+03:00)", - "value": "Africa/Nairobi" - }, - { - "name": "Antarctica/Syowa (GMT+03:00)", - "value": "Antarctica/Syowa" - }, - { - "name": "Asia/Aden (GMT+03:00)", - "value": "Asia/Aden" - }, - { - "name": "Asia/Baghdad (GMT+03:00)", - "value": "Asia/Baghdad" - }, - { - "name": "Asia/Bahrain (GMT+03:00)", - "value": "Asia/Bahrain" - }, - { - "name": "Asia/Kuwait (GMT+03:00)", - "value": "Asia/Kuwait" - }, - { - "name": "Asia/Qatar (GMT+03:00)", - "value": "Asia/Qatar" - }, - { - "name": "Asia/Riyadh (GMT+03:00)", - "value": "Asia/Riyadh" - }, - { - "name": "Europe/Istanbul (GMT+03:00)", - "value": "Europe/Istanbul" - }, - { - "name": "Europe/Kirov (GMT+03:00)", - "value": "Europe/Kirov" - }, - { - "name": "Europe/Minsk (GMT+03:00)", - "value": "Europe/Minsk" - }, - { - "name": "Europe/Moscow (GMT+03:00)", - "value": "Europe/Moscow" - }, - { - "name": "Europe/Simferopol (GMT+03:00)", - "value": "Europe/Simferopol" - }, - { - "name": "Europe/Volgograd (GMT+03:00)", - "value": "Europe/Volgograd" - }, - { - "name": "Indian/Antananarivo (GMT+03:00)", - "value": "Indian/Antananarivo" - }, - { - "name": "Indian/Comoro (GMT+03:00)", - "value": "Indian/Comoro" - }, - { - "name": "Indian/Mayotte (GMT+03:00)", - "value": "Indian/Mayotte" - }, - { - "name": "Asia/Tehran (GMT+03:30)", - "value": "Asia/Tehran" - }, - { - "name": "Asia/Baku (GMT+04:00)", - "value": "Asia/Baku" - }, - { - "name": "Asia/Dubai (GMT+04:00)", - "value": "Asia/Dubai" - }, - { - "name": "Asia/Muscat (GMT+04:00)", - "value": "Asia/Muscat" - }, - { - "name": "Asia/Tbilisi (GMT+04:00)", - "value": "Asia/Tbilisi" - }, - { - "name": "Asia/Yerevan (GMT+04:00)", - "value": "Asia/Yerevan" - }, - { - "name": "Europe/Astrakhan (GMT+04:00)", - "value": "Europe/Astrakhan" - }, - { - "name": "Europe/Samara (GMT+04:00)", - "value": "Europe/Samara" - }, - { - "name": "Europe/Saratov (GMT+04:00)", - "value": "Europe/Saratov" - }, - { - "name": "Europe/Ulyanovsk (GMT+04:00)", - "value": "Europe/Ulyanovsk" - }, - { - "name": "Indian/Mahe (GMT+04:00)", - "value": "Indian/Mahe" - }, - { - "name": "Indian/Mauritius (GMT+04:00)", - "value": "Indian/Mauritius" - }, - { - "name": "Indian/Reunion (GMT+04:00)", - "value": "Indian/Reunion" - }, - { - "name": "Asia/Kabul (GMT+04:30)", - "value": "Asia/Kabul" - }, - { - "name": "Antarctica/Mawson (GMT+05:00)", - "value": "Antarctica/Mawson" - }, - { - "name": "Asia/Aqtau (GMT+05:00)", - "value": "Asia/Aqtau" - }, - { - "name": "Asia/Aqtobe (GMT+05:00)", - "value": "Asia/Aqtobe" - }, - { - "name": "Asia/Ashgabat (GMT+05:00)", - "value": "Asia/Ashgabat" - }, - { - "name": "Asia/Atyrau (GMT+05:00)", - "value": "Asia/Atyrau" - }, - { - "name": "Asia/Dushanbe (GMT+05:00)", - "value": "Asia/Dushanbe" - }, - { - "name": "Asia/Karachi (GMT+05:00)", - "value": "Asia/Karachi" - }, - { - "name": "Asia/Oral (GMT+05:00)", - "value": "Asia/Oral" - }, - { - "name": "Asia/Qyzylorda (GMT+05:00)", - "value": "Asia/Qyzylorda" - }, - { - "name": "Asia/Samarkand (GMT+05:00)", - "value": "Asia/Samarkand" - }, - { - "name": "Asia/Tashkent (GMT+05:00)", - "value": "Asia/Tashkent" - }, - { - "name": "Asia/Yekaterinburg (GMT+05:00)", - "value": "Asia/Yekaterinburg" - }, - { - "name": "Indian/Kerguelen (GMT+05:00)", - "value": "Indian/Kerguelen" - }, - { - "name": "Indian/Maldives (GMT+05:00)", - "value": "Indian/Maldives" - }, - { - "name": "Asia/Colombo (GMT+05:30)", - "value": "Asia/Colombo" - }, - { - "name": "Asia/Kolkata (GMT+05:30)", - "value": "Asia/Kolkata" - }, - { - "name": "Asia/Kathmandu (GMT+05:45)", - "value": "Asia/Kathmandu" - }, - { - "name": "Antarctica/Vostok (GMT+06:00)", - "value": "Antarctica/Vostok" - }, - { - "name": "Asia/Almaty (GMT+06:00)", - "value": "Asia/Almaty" - }, - { - "name": "Asia/Bishkek (GMT+06:00)", - "value": "Asia/Bishkek" - }, - { - "name": "Asia/Dhaka (GMT+06:00)", - "value": "Asia/Dhaka" - }, - { - "name": "Asia/Omsk (GMT+06:00)", - "value": "Asia/Omsk" - }, - { - "name": "Asia/Qostanay (GMT+06:00)", - "value": "Asia/Qostanay" - }, - { - "name": "Asia/Thimphu (GMT+06:00)", - "value": "Asia/Thimphu" - }, - { - "name": "Asia/Urumqi (GMT+06:00)", - "value": "Asia/Urumqi" - }, - { - "name": "Indian/Chagos (GMT+06:00)", - "value": "Indian/Chagos" - }, - { - "name": "Asia/Yangon (GMT+06:30)", - "value": "Asia/Yangon" - }, - { - "name": "Indian/Cocos (GMT+06:30)", - "value": "Indian/Cocos" - }, - { - "name": "Antarctica/Davis (GMT+07:00)", - "value": "Antarctica/Davis" - }, - { - "name": "Asia/Bangkok (GMT+07:00)", - "value": "Asia/Bangkok" - }, - { - "name": "Asia/Barnaul (GMT+07:00)", - "value": "Asia/Barnaul" - }, - { - "name": "Asia/Hovd (GMT+07:00)", - "value": "Asia/Hovd" - }, - { - "name": "Asia/Ho_Chi_Minh (GMT+07:00)", - "value": "Asia/Ho_Chi_Minh" - }, - { - "name": "Asia/Jakarta (GMT+07:00)", - "value": "Asia/Jakarta" - }, - { - "name": "Asia/Krasnoyarsk (GMT+07:00)", - "value": "Asia/Krasnoyarsk" - }, - { - "name": "Asia/Novokuznetsk (GMT+07:00)", - "value": "Asia/Novokuznetsk" - }, - { - "name": "Asia/Novosibirsk (GMT+07:00)", - "value": "Asia/Novosibirsk" - }, - { - "name": "Asia/Phnom_Penh (GMT+07:00)", - "value": "Asia/Phnom_Penh" - }, - { - "name": "Asia/Pontianak (GMT+07:00)", - "value": "Asia/Pontianak" - }, - { - "name": "Asia/Tomsk (GMT+07:00)", - "value": "Asia/Tomsk" - }, - { - "name": "Asia/Vientiane (GMT+07:00)", - "value": "Asia/Vientiane" - }, - { - "name": "Indian/Christmas (GMT+07:00)", - "value": "Indian/Christmas" - }, - { - "name": "Asia/Brunei (GMT+08:00)", - "value": "Asia/Brunei" - }, - { - "name": "Asia/Choibalsan (GMT+08:00)", - "value": "Asia/Choibalsan" - }, - { - "name": "Asia/Hong_Kong (GMT+08:00)", - "value": "Asia/Hong_Kong" - }, - { - "name": "Asia/Irkutsk (GMT+08:00)", - "value": "Asia/Irkutsk" - }, - { - "name": "Asia/Kuala_Lumpur (GMT+08:00)", - "value": "Asia/Kuala_Lumpur" - }, - { - "name": "Asia/Kuching (GMT+08:00)", - "value": "Asia/Kuching" - }, - { - "name": "Asia/Macau (GMT+08:00)", - "value": "Asia/Macau" - }, - { - "name": "Asia/Makassar (GMT+08:00)", - "value": "Asia/Makassar" - }, - { - "name": "Asia/Manila (GMT+08:00)", - "value": "Asia/Manila" - }, - { - "name": "Asia/Shanghai (GMT+08:00)", - "value": "Asia/Shanghai" - }, - { - "name": "Asia/Singapore (GMT+08:00)", - "value": "Asia/Singapore" - }, - { - "name": "Asia/Taipei (GMT+08:00)", - "value": "Asia/Taipei" - }, - { - "name": "Asia/Ulaanbaatar (GMT+08:00)", - "value": "Asia/Ulaanbaatar" - }, - { - "name": "Australia/Perth (GMT+08:00)", - "value": "Australia/Perth" - }, - { - "name": "Australia/Eucla (GMT+08:45)", - "value": "Australia/Eucla" - }, - { - "name": "Asia/Chita (GMT+09:00)", - "value": "Asia/Chita" - }, - { - "name": "Asia/Dili (GMT+09:00)", - "value": "Asia/Dili" - }, - { - "name": "Asia/Jayapura (GMT+09:00)", - "value": "Asia/Jayapura" - }, - { - "name": "Asia/Khandyga (GMT+09:00)", - "value": "Asia/Khandyga" - }, - { - "name": "Asia/Pyongyang (GMT+09:00)", - "value": "Asia/Pyongyang" - }, - { - "name": "Asia/Seoul (GMT+09:00)", - "value": "Asia/Seoul" - }, - { - "name": "Asia/Tokyo (GMT+09:00)", - "value": "Asia/Tokyo" - }, - { - "name": "Asia/Yakutsk (GMT+09:00)", - "value": "Asia/Yakutsk" - }, - { - "name": "Pacific/Palau (GMT+09:00)", - "value": "Pacific/Palau" - }, - { - "name": "Australia/Adelaide (GMT+09:30)", - "value": "Australia/Adelaide" - }, - { - "name": "Australia/Broken_Hill (GMT+09:30)", - "value": "Australia/Broken_Hill" - }, - { - "name": "Australia/Darwin (GMT+09:30)", - "value": "Australia/Darwin" - }, - { - "name": "Antarctica/DumontDUrville (GMT+10:00)", - "value": "Antarctica/DumontDUrville" - }, - { - "name": "Antarctica/Macquarie (GMT+10:00)", - "value": "Antarctica/Macquarie" - }, - { - "name": "Asia/Ust-Nera (GMT+10:00)", - "value": "Asia/Ust-Nera" - }, - { - "name": "Asia/Vladivostok (GMT+10:00)", - "value": "Asia/Vladivostok" - }, - { - "name": "Australia/Brisbane (GMT+10:00)", - "value": "Australia/Brisbane" - }, - { - "name": "Australia/Currie (GMT+10:00)", - "value": "Australia/Currie" - }, - { - "name": "Australia/Hobart (GMT+10:00)", - "value": "Australia/Hobart" - }, - { - "name": "Australia/Lindeman (GMT+10:00)", - "value": "Australia/Lindeman" - }, - { - "name": "Australia/Melbourne (GMT+10:00)", - "value": "Australia/Melbourne" - }, - { - "name": "Australia/Sydney (GMT+10:00)", - "value": "Australia/Sydney" - }, - { - "name": "Pacific/Chuuk (GMT+10:00)", - "value": "Pacific/Chuuk" - }, - { - "name": "Pacific/Guam (GMT+10:00)", - "value": "Pacific/Guam" - }, - { - "name": "Pacific/Port_Moresby (GMT+10:00)", - "value": "Pacific/Port_Moresby" - }, - { - "name": "Pacific/Saipan (GMT+10:00)", - "value": "Pacific/Saipan" - }, - { - "name": "Australia/Lord_Howe (GMT+10:30)", - "value": "Australia/Lord_Howe" - }, - { - "name": "Antarctica/Casey (GMT+11:00)", - "value": "Antarctica/Casey" - }, - { - "name": "Asia/Magadan (GMT+11:00)", - "value": "Asia/Magadan" - }, - { - "name": "Asia/Sakhalin (GMT+11:00)", - "value": "Asia/Sakhalin" - }, - { - "name": "Asia/Srednekolymsk (GMT+11:00)", - "value": "Asia/Srednekolymsk" - }, - { - "name": "Pacific/Bougainville (GMT+11:00)", - "value": "Pacific/Bougainville" - }, - { - "name": "Pacific/Efate (GMT+11:00)", - "value": "Pacific/Efate" - }, - { - "name": "Pacific/Guadalcanal (GMT+11:00)", - "value": "Pacific/Guadalcanal" - }, - { - "name": "Pacific/Kosrae (GMT+11:00)", - "value": "Pacific/Kosrae" - }, - { - "name": "Pacific/Norfolk (GMT+11:00)", - "value": "Pacific/Norfolk" - }, - { - "name": "Pacific/Noumea (GMT+11:00)", - "value": "Pacific/Noumea" - }, - { - "name": "Pacific/Pohnpei (GMT+11:00)", - "value": "Pacific/Pohnpei" - }, - { - "name": "Antarctica/McMurdo (GMT+12:00)", - "value": "Antarctica/McMurdo" - }, - { - "name": "Asia/Anadyr (GMT+12:00)", - "value": "Asia/Anadyr" - }, - { - "name": "Asia/Kamchatka (GMT+12:00)", - "value": "Asia/Kamchatka" - }, - { - "name": "Pacific/Auckland (GMT+12:00)", - "value": "Pacific/Auckland" - }, - { - "name": "Pacific/Fiji (GMT+12:00)", - "value": "Pacific/Fiji" - }, - { - "name": "Pacific/Funafuti (GMT+12:00)", - "value": "Pacific/Funafuti" - }, - { - "name": "Pacific/Kwajalein (GMT+12:00)", - "value": "Pacific/Kwajalein" - }, - { - "name": "Pacific/Majuro (GMT+12:00)", - "value": "Pacific/Majuro" - }, - { - "name": "Pacific/Nauru (GMT+12:00)", - "value": "Pacific/Nauru" - }, - { - "name": "Pacific/Tarawa (GMT+12:00)", - "value": "Pacific/Tarawa" - }, - { - "name": "Pacific/Wake (GMT+12:00)", - "value": "Pacific/Wake" - }, - { - "name": "Pacific/Wallis (GMT+12:00)", - "value": "Pacific/Wallis" - }, - { - "name": "Pacific/Chatham (GMT+12:45)", - "value": "Pacific/Chatham" - }, - { - "name": "Pacific/Apia (GMT+13:00)", - "value": "Pacific/Apia" - }, - { - "name": "Pacific/Enderbury (GMT+13:00)", - "value": "Pacific/Enderbury" - }, - { - "name": "Pacific/Fakaofo (GMT+13:00)", - "value": "Pacific/Fakaofo" - }, - { - "name": "Pacific/Tongatapu (GMT+13:00)", - "value": "Pacific/Tongatapu" - }, - { - "name": "Pacific/Kiritimati (GMT+14:00)", - "value": "Pacific/Kiritimati" - } -] diff --git a/app/constant/timezones.json b/app/constant/timezones.json new file mode 100644 index 0000000..4f9f0bc --- /dev/null +++ b/app/constant/timezones.json @@ -0,0 +1,426 @@ +{ + "Pacific/Midway": "Pacific/Midway (GMT-11:00)", + "Pacific/Niue": "Pacific/Niue (GMT-11:00)", + "Pacific/Pago_Pago": "Pacific/Pago_Pago (GMT-11:00)", + "America/Adak": "America/Adak (GMT-10:00)", + "Pacific/Honolulu": "Pacific/Honolulu (GMT-10:00)", + "Pacific/Rarotonga": "Pacific/Rarotonga (GMT-10:00)", + "Pacific/Tahiti": "Pacific/Tahiti (GMT-10:00)", + "Pacific/Marquesas": "Pacific/Marquesas (GMT-09:30)", + "America/Anchorage": "America/Anchorage (GMT-09:00)", + "America/Juneau": "America/Juneau (GMT-09:00)", + "America/Metlakatla": "America/Metlakatla (GMT-09:00)", + "America/Nome": "America/Nome (GMT-09:00)", + "America/Sitka": "America/Sitka (GMT-09:00)", + "America/Yakutat": "America/Yakutat (GMT-09:00)", + "Pacific/Gambier": "Pacific/Gambier (GMT-09:00)", + "America/Los_Angeles": "America/Los_Angeles (GMT-08:00)", + "America/Tijuana": "America/Tijuana (GMT-08:00)", + "America/Vancouver": "America/Vancouver (GMT-08:00)", + "Pacific/Pitcairn": "Pacific/Pitcairn (GMT-08:00)", + "America/Boise": "America/Boise (GMT-07:00)", + "America/Cambridge_Bay": "America/Cambridge_Bay (GMT-07:00)", + "America/Chihuahua": "America/Chihuahua (GMT-07:00)", + "America/Creston": "America/Creston (GMT-07:00)", + "America/Dawson": "America/Dawson (GMT-07:00)", + "America/Dawson_Creek": "America/Dawson_Creek (GMT-07:00)", + "America/Denver": "America/Denver (GMT-07:00)", + "America/Edmonton": "America/Edmonton (GMT-07:00)", + "America/Fort_Nelson": "America/Fort_Nelson (GMT-07:00)", + "America/Hermosillo": "America/Hermosillo (GMT-07:00)", + "America/Inuvik": "America/Inuvik (GMT-07:00)", + "America/Mazatlan": "America/Mazatlan (GMT-07:00)", + "America/Ojinaga": "America/Ojinaga (GMT-07:00)", + "America/Phoenix": "America/Phoenix (GMT-07:00)", + "America/Whitehorse": "America/Whitehorse (GMT-07:00)", + "America/Yellowknife": "America/Yellowknife (GMT-07:00)", + "America/Bahia_Banderas": "America/Bahia_Banderas (GMT-06:00)", + "America/Belize": "America/Belize (GMT-06:00)", + "America/Chicago": "America/Chicago (GMT-06:00)", + "America/Costa_Rica": "America/Costa_Rica (GMT-06:00)", + "America/El_Salvador": "America/El_Salvador (GMT-06:00)", + "America/Guatemala": "America/Guatemala (GMT-06:00)", + "America/Indiana/Knox": "America/Indiana/Knox (GMT-06:00)", + "America/Indiana/Tell_City": "America/Indiana/Tell_City (GMT-06:00)", + "America/Managua": "America/Managua (GMT-06:00)", + "America/Matamoros": "America/Matamoros (GMT-06:00)", + "America/Menominee": "America/Menominee (GMT-06:00)", + "America/Merida": "America/Merida (GMT-06:00)", + "America/Mexico_City": "America/Mexico_City (GMT-06:00)", + "America/Monterrey": "America/Monterrey (GMT-06:00)", + "America/North_Dakota/Beulah": "America/North_Dakota/Beulah (GMT-06:00)", + "America/North_Dakota/Center": "America/North_Dakota/Center (GMT-06:00)", + "America/North_Dakota/New_Salem": "America/North_Dakota/New_Salem (GMT-06:00)", + "America/Rainy_River": "America/Rainy_River (GMT-06:00)", + "America/Rankin_Inlet": "America/Rankin_Inlet (GMT-06:00)", + "America/Regina": "America/Regina (GMT-06:00)", + "America/Resolute": "America/Resolute (GMT-06:00)", + "America/Swift_Current": "America/Swift_Current (GMT-06:00)", + "America/Tegucigalpa": "America/Tegucigalpa (GMT-06:00)", + "America/Winnipeg": "America/Winnipeg (GMT-06:00)", + "Pacific/Easter": "Pacific/Easter (GMT-06:00)", + "Pacific/Galapagos": "Pacific/Galapagos (GMT-06:00)", + "America/Atikokan": "America/Atikokan (GMT-05:00)", + "America/Bogota": "America/Bogota (GMT-05:00)", + "America/Cancun": "America/Cancun (GMT-05:00)", + "America/Cayman": "America/Cayman (GMT-05:00)", + "America/Detroit": "America/Detroit (GMT-05:00)", + "America/Eirunepe": "America/Eirunepe (GMT-05:00)", + "America/Grand_Turk": "America/Grand_Turk (GMT-05:00)", + "America/Guayaquil": "America/Guayaquil (GMT-05:00)", + "America/Havana": "America/Havana (GMT-05:00)", + "America/Indiana/Indianapolis": "America/Indiana/Indianapolis (GMT-05:00)", + "America/Indiana/Marengo": "America/Indiana/Marengo (GMT-05:00)", + "America/Indiana/Petersburg": "America/Indiana/Petersburg (GMT-05:00)", + "America/Indiana/Vevay": "America/Indiana/Vevay (GMT-05:00)", + "America/Indiana/Vincennes": "America/Indiana/Vincennes (GMT-05:00)", + "America/Indiana/Winamac": "America/Indiana/Winamac (GMT-05:00)", + "America/Iqaluit": "America/Iqaluit (GMT-05:00)", + "America/Jamaica": "America/Jamaica (GMT-05:00)", + "America/Kentucky/Louisville": "America/Kentucky/Louisville (GMT-05:00)", + "America/Kentucky/Monticello": "America/Kentucky/Monticello (GMT-05:00)", + "America/Lima": "America/Lima (GMT-05:00)", + "America/Nassau": "America/Nassau (GMT-05:00)", + "America/New_York": "America/New_York (GMT-05:00)", + "America/Nipigon": "America/Nipigon (GMT-05:00)", + "America/Panama": "America/Panama (GMT-05:00)", + "America/Pangnirtung": "America/Pangnirtung (GMT-05:00)", + "America/Port-au-Prince": "America/Port-au-Prince (GMT-05:00)", + "America/Rio_Branco": "America/Rio_Branco (GMT-05:00)", + "America/Thunder_Bay": "America/Thunder_Bay (GMT-05:00)", + "America/Toronto": "America/Toronto (GMT-05:00)", + "America/Anguilla": "America/Anguilla (GMT-04:00)", + "America/Antigua": "America/Antigua (GMT-04:00)", + "America/Aruba": "America/Aruba (GMT-04:00)", + "America/Asuncion": "America/Asuncion (GMT-04:00)", + "America/Barbados": "America/Barbados (GMT-04:00)", + "America/Blanc-Sablon": "America/Blanc-Sablon (GMT-04:00)", + "America/Boa_Vista": "America/Boa_Vista (GMT-04:00)", + "America/Campo_Grande": "America/Campo_Grande (GMT-04:00)", + "America/Caracas": "America/Caracas (GMT-04:00)", + "America/Cuiaba": "America/Cuiaba (GMT-04:00)", + "America/Curacao": "America/Curacao (GMT-04:00)", + "America/Dominica": "America/Dominica (GMT-04:00)", + "America/Glace_Bay": "America/Glace_Bay (GMT-04:00)", + "America/Goose_Bay": "America/Goose_Bay (GMT-04:00)", + "America/Grenada": "America/Grenada (GMT-04:00)", + "America/Guadeloupe": "America/Guadeloupe (GMT-04:00)", + "America/Guyana": "America/Guyana (GMT-04:00)", + "America/Halifax": "America/Halifax (GMT-04:00)", + "America/Kralendijk": "America/Kralendijk (GMT-04:00)", + "America/La_Paz": "America/La_Paz (GMT-04:00)", + "America/Lower_Princes": "America/Lower_Princes (GMT-04:00)", + "America/Manaus": "America/Manaus (GMT-04:00)", + "America/Marigot": "America/Marigot (GMT-04:00)", + "America/Martinique": "America/Martinique (GMT-04:00)", + "America/Moncton": "America/Moncton (GMT-04:00)", + "America/Montserrat": "America/Montserrat (GMT-04:00)", + "America/Porto_Velho": "America/Porto_Velho (GMT-04:00)", + "America/Port_of_Spain": "America/Port_of_Spain (GMT-04:00)", + "America/Puerto_Rico": "America/Puerto_Rico (GMT-04:00)", + "America/Santiago": "America/Santiago (GMT-04:00)", + "America/Santo_Domingo": "America/Santo_Domingo (GMT-04:00)", + "America/St_Barthelemy": "America/St_Barthelemy (GMT-04:00)", + "America/St_Kitts": "America/St_Kitts (GMT-04:00)", + "America/St_Lucia": "America/St_Lucia (GMT-04:00)", + "America/St_Thomas": "America/St_Thomas (GMT-04:00)", + "America/St_Vincent": "America/St_Vincent (GMT-04:00)", + "America/Thule": "America/Thule (GMT-04:00)", + "America/Tortola": "America/Tortola (GMT-04:00)", + "Atlantic/Bermuda": "Atlantic/Bermuda (GMT-04:00)", + "America/St_Johns": "America/St_Johns (GMT-03:30)", + "America/Araguaina": "America/Araguaina (GMT-03:00)", + "America/Argentina/Buenos_Aires": "America/Argentina/Buenos_Aires (GMT-03:00)", + "America/Argentina/Catamarca": "America/Argentina/Catamarca (GMT-03:00)", + "America/Argentina/Cordoba": "America/Argentina/Cordoba (GMT-03:00)", + "America/Argentina/Jujuy": "America/Argentina/Jujuy (GMT-03:00)", + "America/Argentina/La_Rioja": "America/Argentina/La_Rioja (GMT-03:00)", + "America/Argentina/Mendoza": "America/Argentina/Mendoza (GMT-03:00)", + "America/Argentina/Rio_Gallegos": "America/Argentina/Rio_Gallegos (GMT-03:00)", + "America/Argentina/Salta": "America/Argentina/Salta (GMT-03:00)", + "America/Argentina/San_Juan": "America/Argentina/San_Juan (GMT-03:00)", + "America/Argentina/San_Luis": "America/Argentina/San_Luis (GMT-03:00)", + "America/Argentina/Tucuman": "America/Argentina/Tucuman (GMT-03:00)", + "America/Argentina/Ushuaia": "America/Argentina/Ushuaia (GMT-03:00)", + "America/Bahia": "America/Bahia (GMT-03:00)", + "America/Belem": "America/Belem (GMT-03:00)", + "America/Cayenne": "America/Cayenne (GMT-03:00)", + "America/Fortaleza": "America/Fortaleza (GMT-03:00)", + "America/Godthab": "America/Godthab (GMT-03:00)", + "America/Maceio": "America/Maceio (GMT-03:00)", + "America/Miquelon": "America/Miquelon (GMT-03:00)", + "America/Montevideo": "America/Montevideo (GMT-03:00)", + "America/Paramaribo": "America/Paramaribo (GMT-03:00)", + "America/Punta_Arenas": "America/Punta_Arenas (GMT-03:00)", + "America/Recife": "America/Recife (GMT-03:00)", + "America/Santarem": "America/Santarem (GMT-03:00)", + "America/Sao_Paulo": "America/Sao_Paulo (GMT-03:00)", + "Antarctica/Palmer": "Antarctica/Palmer (GMT-03:00)", + "Antarctica/Rothera": "Antarctica/Rothera (GMT-03:00)", + "Atlantic/Stanley": "Atlantic/Stanley (GMT-03:00)", + "America/Noronha": "America/Noronha (GMT-02:00)", + "Atlantic/South_Georgia": "Atlantic/South_Georgia (GMT-02:00)", + "America/Scoresbysund": "America/Scoresbysund (GMT-01:00)", + "Atlantic/Azores": "Atlantic/Azores (GMT-01:00)", + "Atlantic/Cape_Verde": "Atlantic/Cape_Verde (GMT-01:00)", + "Africa/Abidjan": "Africa/Abidjan (GMT+00:00)", + "Africa/Accra": "Africa/Accra (GMT+00:00)", + "Africa/Bamako": "Africa/Bamako (GMT+00:00)", + "Africa/Banjul": "Africa/Banjul (GMT+00:00)", + "Africa/Bissau": "Africa/Bissau (GMT+00:00)", + "Africa/Casablanca": "Africa/Casablanca (GMT+00:00)", + "Africa/Conakry": "Africa/Conakry (GMT+00:00)", + "Africa/Dakar": "Africa/Dakar (GMT+00:00)", + "Africa/El_Aaiun": "Africa/El_Aaiun (GMT+00:00)", + "Africa/Freetown": "Africa/Freetown (GMT+00:00)", + "Africa/Lome": "Africa/Lome (GMT+00:00)", + "Africa/Monrovia": "Africa/Monrovia (GMT+00:00)", + "Africa/Nouakchott": "Africa/Nouakchott (GMT+00:00)", + "Africa/Ouagadougou": "Africa/Ouagadougou (GMT+00:00)", + "Africa/Sao_Tome": "Africa/Sao_Tome (GMT+00:00)", + "America/Danmarkshavn": "America/Danmarkshavn (GMT+00:00)", + "Antarctica/Troll": "Antarctica/Troll (GMT+00:00)", + "Atlantic/Canary": "Atlantic/Canary (GMT+00:00)", + "Atlantic/Faroe": "Atlantic/Faroe (GMT+00:00)", + "Atlantic/Madeira": "Atlantic/Madeira (GMT+00:00)", + "Atlantic/Reykjavik": "Atlantic/Reykjavik (GMT+00:00)", + "Atlantic/St_Helena": "Atlantic/St_Helena (GMT+00:00)", + "Europe/Dublin": "Europe/Dublin (GMT+00:00)", + "Europe/Guernsey": "Europe/Guernsey (GMT+00:00)", + "Europe/Isle_of_Man": "Europe/Isle_of_Man (GMT+00:00)", + "Europe/Jersey": "Europe/Jersey (GMT+00:00)", + "Europe/Lisbon": "Europe/Lisbon (GMT+00:00)", + "Europe/London": "Europe/London (GMT+00:00)", + "Africa/Algiers": "Africa/Algiers (GMT+01:00)", + "Africa/Bangui": "Africa/Bangui (GMT+01:00)", + "Africa/Brazzaville": "Africa/Brazzaville (GMT+01:00)", + "Africa/Ceuta": "Africa/Ceuta (GMT+01:00)", + "Africa/Douala": "Africa/Douala (GMT+01:00)", + "Africa/Kinshasa": "Africa/Kinshasa (GMT+01:00)", + "Africa/Lagos": "Africa/Lagos (GMT+01:00)", + "Africa/Libreville": "Africa/Libreville (GMT+01:00)", + "Africa/Luanda": "Africa/Luanda (GMT+01:00)", + "Africa/Malabo": "Africa/Malabo (GMT+01:00)", + "Africa/Ndjamena": "Africa/Ndjamena (GMT+01:00)", + "Africa/Niamey": "Africa/Niamey (GMT+01:00)", + "Africa/Porto-Novo": "Africa/Porto-Novo (GMT+01:00)", + "Africa/Tunis": "Africa/Tunis (GMT+01:00)", + "Africa/Windhoek": "Africa/Windhoek (GMT+01:00)", + "Arctic/Longyearbyen": "Arctic/Longyearbyen (GMT+01:00)", + "Europe/Amsterdam": "Europe/Amsterdam (GMT+01:00)", + "Europe/Andorra": "Europe/Andorra (GMT+01:00)", + "Europe/Belgrade": "Europe/Belgrade (GMT+01:00)", + "Europe/Berlin": "Europe/Berlin (GMT+01:00)", + "Europe/Bratislava": "Europe/Bratislava (GMT+01:00)", + "Europe/Brussels": "Europe/Brussels (GMT+01:00)", + "Europe/Budapest": "Europe/Budapest (GMT+01:00)", + "Europe/Copenhagen": "Europe/Copenhagen (GMT+01:00)", + "Europe/Gibraltar": "Europe/Gibraltar (GMT+01:00)", + "Europe/Ljubljana": "Europe/Ljubljana (GMT+01:00)", + "Europe/Luxembourg": "Europe/Luxembourg (GMT+01:00)", + "Europe/Madrid": "Europe/Madrid (GMT+01:00)", + "Europe/Malta": "Europe/Malta (GMT+01:00)", + "Europe/Monaco": "Europe/Monaco (GMT+01:00)", + "Europe/Oslo": "Europe/Oslo (GMT+01:00)", + "Europe/Paris": "Europe/Paris (GMT+01:00)", + "Europe/Podgorica": "Europe/Podgorica (GMT+01:00)", + "Europe/Prague": "Europe/Prague (GMT+01:00)", + "Europe/Rome": "Europe/Rome (GMT+01:00)", + "Europe/San_Marino": "Europe/San_Marino (GMT+01:00)", + "Europe/Sarajevo": "Europe/Sarajevo (GMT+01:00)", + "Europe/Skopje": "Europe/Skopje (GMT+01:00)", + "Europe/Stockholm": "Europe/Stockholm (GMT+01:00)", + "Europe/Tirane": "Europe/Tirane (GMT+01:00)", + "Europe/Vaduz": "Europe/Vaduz (GMT+01:00)", + "Europe/Vatican": "Europe/Vatican (GMT+01:00)", + "Europe/Vienna": "Europe/Vienna (GMT+01:00)", + "Europe/Warsaw": "Europe/Warsaw (GMT+01:00)", + "Europe/Zagreb": "Europe/Zagreb (GMT+01:00)", + "Europe/Zurich": "Europe/Zurich (GMT+01:00)", + "Africa/Blantyre": "Africa/Blantyre (GMT+02:00)", + "Africa/Bujumbura": "Africa/Bujumbura (GMT+02:00)", + "Africa/Cairo": "Africa/Cairo (GMT+02:00)", + "Africa/Gaborone": "Africa/Gaborone (GMT+02:00)", + "Africa/Harare": "Africa/Harare (GMT+02:00)", + "Africa/Johannesburg": "Africa/Johannesburg (GMT+02:00)", + "Africa/Juba": "Africa/Juba (GMT+02:00)", + "Africa/Khartoum": "Africa/Khartoum (GMT+02:00)", + "Africa/Kigali": "Africa/Kigali (GMT+02:00)", + "Africa/Lubumbashi": "Africa/Lubumbashi (GMT+02:00)", + "Africa/Lusaka": "Africa/Lusaka (GMT+02:00)", + "Africa/Maputo": "Africa/Maputo (GMT+02:00)", + "Africa/Maseru": "Africa/Maseru (GMT+02:00)", + "Africa/Mbabane": "Africa/Mbabane (GMT+02:00)", + "Africa/Tripoli": "Africa/Tripoli (GMT+02:00)", + "Asia/Amman": "Asia/Amman (GMT+02:00)", + "Asia/Beirut": "Asia/Beirut (GMT+02:00)", + "Asia/Damascus": "Asia/Damascus (GMT+02:00)", + "Asia/Famagusta": "Asia/Famagusta (GMT+02:00)", + "Asia/Gaza": "Asia/Gaza (GMT+02:00)", + "Asia/Hebron": "Asia/Hebron (GMT+02:00)", + "Asia/Jerusalem": "Asia/Jerusalem (GMT+02:00)", + "Asia/Nicosia": "Asia/Nicosia (GMT+02:00)", + "Europe/Athens": "Europe/Athens (GMT+02:00)", + "Europe/Bucharest": "Europe/Bucharest (GMT+02:00)", + "Europe/Chisinau": "Europe/Chisinau (GMT+02:00)", + "Europe/Helsinki": "Europe/Helsinki (GMT+02:00)", + "Europe/Kaliningrad": "Europe/Kaliningrad (GMT+02:00)", + "Europe/Kyiv": "Europe/Kyiv (GMT+02:00)", + "Europe/Mariehamn": "Europe/Mariehamn (GMT+02:00)", + "Europe/Riga": "Europe/Riga (GMT+02:00)", + "Europe/Sofia": "Europe/Sofia (GMT+02:00)", + "Europe/Tallinn": "Europe/Tallinn (GMT+02:00)", + "Europe/Uzhgorod": "Europe/Uzhgorod (GMT+02:00)", + "Europe/Vilnius": "Europe/Vilnius (GMT+02:00)", + "Europe/Zaporozhye": "Europe/Zaporozhye (GMT+02:00)", + "Africa/Addis_Ababa": "Africa/Addis_Ababa (GMT+03:00)", + "Africa/Asmara": "Africa/Asmara (GMT+03:00)", + "Africa/Dar_es_Salaam": "Africa/Dar_es_Salaam (GMT+03:00)", + "Africa/Djibouti": "Africa/Djibouti (GMT+03:00)", + "Africa/Kampala": "Africa/Kampala (GMT+03:00)", + "Africa/Mogadishu": "Africa/Mogadishu (GMT+03:00)", + "Africa/Nairobi": "Africa/Nairobi (GMT+03:00)", + "Antarctica/Syowa": "Antarctica/Syowa (GMT+03:00)", + "Asia/Aden": "Asia/Aden (GMT+03:00)", + "Asia/Baghdad": "Asia/Baghdad (GMT+03:00)", + "Asia/Bahrain": "Asia/Bahrain (GMT+03:00)", + "Asia/Kuwait": "Asia/Kuwait (GMT+03:00)", + "Asia/Qatar": "Asia/Qatar (GMT+03:00)", + "Asia/Riyadh": "Asia/Riyadh (GMT+03:00)", + "Europe/Istanbul": "Europe/Istanbul (GMT+03:00)", + "Europe/Kirov": "Europe/Kirov (GMT+03:00)", + "Europe/Minsk": "Europe/Minsk (GMT+03:00)", + "Europe/Moscow": "Europe/Moscow (GMT+03:00)", + "Europe/Simferopol": "Europe/Simferopol (GMT+03:00)", + "Europe/Volgograd": "Europe/Volgograd (GMT+03:00)", + "Indian/Antananarivo": "Indian/Antananarivo (GMT+03:00)", + "Indian/Comoro": "Indian/Comoro (GMT+03:00)", + "Indian/Mayotte": "Indian/Mayotte (GMT+03:00)", + "Asia/Tehran": "Asia/Tehran (GMT+03:30)", + "Asia/Baku": "Asia/Baku (GMT+04:00)", + "Asia/Dubai": "Asia/Dubai (GMT+04:00)", + "Asia/Muscat": "Asia/Muscat (GMT+04:00)", + "Asia/Tbilisi": "Asia/Tbilisi (GMT+04:00)", + "Asia/Yerevan": "Asia/Yerevan (GMT+04:00)", + "Europe/Astrakhan": "Europe/Astrakhan (GMT+04:00)", + "Europe/Samara": "Europe/Samara (GMT+04:00)", + "Europe/Saratov": "Europe/Saratov (GMT+04:00)", + "Europe/Ulyanovsk": "Europe/Ulyanovsk (GMT+04:00)", + "Indian/Mahe": "Indian/Mahe (GMT+04:00)", + "Indian/Mauritius": "Indian/Mauritius (GMT+04:00)", + "Indian/Reunion": "Indian/Reunion (GMT+04:00)", + "Asia/Kabul": "Asia/Kabul (GMT+04:30)", + "Antarctica/Mawson": "Antarctica/Mawson (GMT+05:00)", + "Asia/Aqtau": "Asia/Aqtau (GMT+05:00)", + "Asia/Aqtobe": "Asia/Aqtobe (GMT+05:00)", + "Asia/Ashgabat": "Asia/Ashgabat (GMT+05:00)", + "Asia/Atyrau": "Asia/Atyrau (GMT+05:00)", + "Asia/Dushanbe": "Asia/Dushanbe (GMT+05:00)", + "Asia/Karachi": "Asia/Karachi (GMT+05:00)", + "Asia/Oral": "Asia/Oral (GMT+05:00)", + "Asia/Qyzylorda": "Asia/Qyzylorda (GMT+05:00)", + "Asia/Samarkand": "Asia/Samarkand (GMT+05:00)", + "Asia/Tashkent": "Asia/Tashkent (GMT+05:00)", + "Asia/Yekaterinburg": "Asia/Yekaterinburg (GMT+05:00)", + "Indian/Kerguelen": "Indian/Kerguelen (GMT+05:00)", + "Indian/Maldives": "Indian/Maldives (GMT+05:00)", + "Asia/Colombo": "Asia/Colombo (GMT+05:30)", + "Asia/Kolkata": "Asia/Kolkata (GMT+05:30)", + "Asia/Kathmandu": "Asia/Kathmandu (GMT+05:45)", + "Antarctica/Vostok": "Antarctica/Vostok (GMT+06:00)", + "Asia/Almaty": "Asia/Almaty (GMT+06:00)", + "Asia/Bishkek": "Asia/Bishkek (GMT+06:00)", + "Asia/Dhaka": "Asia/Dhaka (GMT+06:00)", + "Asia/Omsk": "Asia/Omsk (GMT+06:00)", + "Asia/Qostanay": "Asia/Qostanay (GMT+06:00)", + "Asia/Thimphu": "Asia/Thimphu (GMT+06:00)", + "Asia/Urumqi": "Asia/Urumqi (GMT+06:00)", + "Indian/Chagos": "Indian/Chagos (GMT+06:00)", + "Asia/Yangon": "Asia/Yangon (GMT+06:30)", + "Indian/Cocos": "Indian/Cocos (GMT+06:30)", + "Antarctica/Davis": "Antarctica/Davis (GMT+07:00)", + "Asia/Bangkok": "Asia/Bangkok (GMT+07:00)", + "Asia/Barnaul": "Asia/Barnaul (GMT+07:00)", + "Asia/Hovd": "Asia/Hovd (GMT+07:00)", + "Asia/Ho_Chi_Minh": "Asia/Ho_Chi_Minh (GMT+07:00)", + "Asia/Jakarta": "Asia/Jakarta (GMT+07:00)", + "Asia/Krasnoyarsk": "Asia/Krasnoyarsk (GMT+07:00)", + "Asia/Novokuznetsk": "Asia/Novokuznetsk (GMT+07:00)", + "Asia/Novosibirsk": "Asia/Novosibirsk (GMT+07:00)", + "Asia/Phnom_Penh": "Asia/Phnom_Penh (GMT+07:00)", + "Asia/Pontianak": "Asia/Pontianak (GMT+07:00)", + "Asia/Tomsk": "Asia/Tomsk (GMT+07:00)", + "Asia/Vientiane": "Asia/Vientiane (GMT+07:00)", + "Indian/Christmas": "Indian/Christmas (GMT+07:00)", + "Asia/Brunei": "Asia/Brunei (GMT+08:00)", + "Asia/Choibalsan": "Asia/Choibalsan (GMT+08:00)", + "Asia/Hong_Kong": "Asia/Hong_Kong (GMT+08:00)", + "Asia/Irkutsk": "Asia/Irkutsk (GMT+08:00)", + "Asia/Kuala_Lumpur": "Asia/Kuala_Lumpur (GMT+08:00)", + "Asia/Kuching": "Asia/Kuching (GMT+08:00)", + "Asia/Macau": "Asia/Macau (GMT+08:00)", + "Asia/Makassar": "Asia/Makassar (GMT+08:00)", + "Asia/Manila": "Asia/Manila (GMT+08:00)", + "Asia/Shanghai": "Asia/Shanghai (GMT+08:00)", + "Asia/Singapore": "Asia/Singapore (GMT+08:00)", + "Asia/Taipei": "Asia/Taipei (GMT+08:00)", + "Asia/Ulaanbaatar": "Asia/Ulaanbaatar (GMT+08:00)", + "Australia/Perth": "Australia/Perth (GMT+08:00)", + "Australia/Eucla": "Australia/Eucla (GMT+08:45)", + "Asia/Chita": "Asia/Chita (GMT+09:00)", + "Asia/Dili": "Asia/Dili (GMT+09:00)", + "Asia/Jayapura": "Asia/Jayapura (GMT+09:00)", + "Asia/Khandyga": "Asia/Khandyga (GMT+09:00)", + "Asia/Pyongyang": "Asia/Pyongyang (GMT+09:00)", + "Asia/Seoul": "Asia/Seoul (GMT+09:00)", + "Asia/Tokyo": "Asia/Tokyo (GMT+09:00)", + "Asia/Yakutsk": "Asia/Yakutsk (GMT+09:00)", + "Pacific/Palau": "Pacific/Palau (GMT+09:00)", + "Australia/Adelaide": "Australia/Adelaide (GMT+09:30)", + "Australia/Broken_Hill": "Australia/Broken_Hill (GMT+09:30)", + "Australia/Darwin": "Australia/Darwin (GMT+09:30)", + "Antarctica/DumontDUrville": "Antarctica/DumontDUrville (GMT+10:00)", + "Antarctica/Macquarie": "Antarctica/Macquarie (GMT+10:00)", + "Asia/Ust-Nera": "Asia/Ust-Nera (GMT+10:00)", + "Asia/Vladivostok": "Asia/Vladivostok (GMT+10:00)", + "Australia/Brisbane": "Australia/Brisbane (GMT+10:00)", + "Australia/Currie": "Australia/Currie (GMT+10:00)", + "Australia/Hobart": "Australia/Hobart (GMT+10:00)", + "Australia/Lindeman": "Australia/Lindeman (GMT+10:00)", + "Australia/Melbourne": "Australia/Melbourne (GMT+10:00)", + "Australia/Sydney": "Australia/Sydney (GMT+10:00)", + "Pacific/Chuuk": "Pacific/Chuuk (GMT+10:00)", + "Pacific/Guam": "Pacific/Guam (GMT+10:00)", + "Pacific/Port_Moresby": "Pacific/Port_Moresby (GMT+10:00)", + "Pacific/Saipan": "Pacific/Saipan (GMT+10:00)", + "Australia/Lord_Howe": "Australia/Lord_Howe (GMT+10:30)", + "Antarctica/Casey": "Antarctica/Casey (GMT+11:00)", + "Asia/Magadan": "Asia/Magadan (GMT+11:00)", + "Asia/Sakhalin": "Asia/Sakhalin (GMT+11:00)", + "Asia/Srednekolymsk": "Asia/Srednekolymsk (GMT+11:00)", + "Pacific/Bougainville": "Pacific/Bougainville (GMT+11:00)", + "Pacific/Efate": "Pacific/Efate (GMT+11:00)", + "Pacific/Guadalcanal": "Pacific/Guadalcanal (GMT+11:00)", + "Pacific/Kosrae": "Pacific/Kosrae (GMT+11:00)", + "Pacific/Norfolk": "Pacific/Norfolk (GMT+11:00)", + "Pacific/Noumea": "Pacific/Noumea (GMT+11:00)", + "Pacific/Pohnpei": "Pacific/Pohnpei (GMT+11:00)", + "Antarctica/McMurdo": "Antarctica/McMurdo (GMT+12:00)", + "Asia/Anadyr": "Asia/Anadyr (GMT+12:00)", + "Asia/Kamchatka": "Asia/Kamchatka (GMT+12:00)", + "Pacific/Auckland": "Pacific/Auckland (GMT+12:00)", + "Pacific/Fiji": "Pacific/Fiji (GMT+12:00)", + "Pacific/Funafuti": "Pacific/Funafuti (GMT+12:00)", + "Pacific/Kwajalein": "Pacific/Kwajalein (GMT+12:00)", + "Pacific/Majuro": "Pacific/Majuro (GMT+12:00)", + "Pacific/Nauru": "Pacific/Nauru (GMT+12:00)", + "Pacific/Tarawa": "Pacific/Tarawa (GMT+12:00)", + "Pacific/Wake": "Pacific/Wake (GMT+12:00)", + "Pacific/Wallis": "Pacific/Wallis (GMT+12:00)", + "Pacific/Chatham": "Pacific/Chatham (GMT+12:45)", + "Pacific/Apia": "Pacific/Apia (GMT+13:00)", + "Pacific/Enderbury": "Pacific/Enderbury (GMT+13:00)", + "Pacific/Fakaofo": "Pacific/Fakaofo (GMT+13:00)", + "Pacific/Tongatapu": "Pacific/Tongatapu (GMT+13:00)", + "Pacific/Kiritimati": "Pacific/Kiritimati (GMT+14:00)" +} From a557b0197fc360ab1639c18045d8f5b8422b96d0 Mon Sep 17 00:00:00 2001 From: ksjaay Date: Sat, 18 May 2024 21:15:59 +0100 Subject: [PATCH 03/28] Remove old settings files --- .../settings/general/dropdown/colors.jsx | 48 ----------- .../settings/general/dropdown/dateFormat.jsx | 46 ----------- .../settings/general/dropdown/index.jsx | 13 --- .../settings/general/dropdown/themes.jsx | 36 --------- .../settings/general/dropdown/timeFormat.jsx | 56 ------------- .../settings/general/dropdown/timezone.jsx | 45 ----------- app/components/settings/general/index.jsx | 81 ------------------- app/components/settings/general/style.scss | 62 -------------- app/components/settings/tab.scss | 39 --------- 9 files changed, 426 deletions(-) delete mode 100644 app/components/settings/general/dropdown/colors.jsx delete mode 100644 app/components/settings/general/dropdown/dateFormat.jsx delete mode 100644 app/components/settings/general/dropdown/index.jsx delete mode 100644 app/components/settings/general/dropdown/themes.jsx delete mode 100644 app/components/settings/general/dropdown/timeFormat.jsx delete mode 100644 app/components/settings/general/dropdown/timezone.jsx delete mode 100644 app/components/settings/general/index.jsx delete mode 100644 app/components/settings/general/style.scss delete mode 100644 app/components/settings/tab.scss diff --git a/app/components/settings/general/dropdown/colors.jsx b/app/components/settings/general/dropdown/colors.jsx deleted file mode 100644 index 818293d..0000000 --- a/app/components/settings/general/dropdown/colors.jsx +++ /dev/null @@ -1,48 +0,0 @@ -import useDropdown from '../../../../hooks/useDropdown'; -import useLocalStorageContext from '../../../../hooks/useLocalstorage'; -import Dropdown from '../../../ui/dropdown/index'; - -const colors = ['Blue', 'Cyan', 'Green', 'Pink', 'Purple', 'Red', 'Yellow']; - -const ColorsDropdown = () => { - const { color: stateColor, setColor } = useLocalStorageContext(); - - const { dropdownIsOpen, toggleDropdown } = useDropdown(); - - const colorsList = colors.map((color) => ( - setColor(color)} - showDot - dotColor={color.toLowerCase()} - isSelected={stateColor === color} - > - {color} - - )); - - return ( - <> - - - - {stateColor} - - - {colorsList} - - - - ); -}; - -export default ColorsDropdown; diff --git a/app/components/settings/general/dropdown/dateFormat.jsx b/app/components/settings/general/dropdown/dateFormat.jsx deleted file mode 100644 index 7e64422..0000000 --- a/app/components/settings/general/dropdown/dateFormat.jsx +++ /dev/null @@ -1,46 +0,0 @@ -import timeformats from '../../../../constant/dateformats.json'; -import useDropdown from '../../../../hooks/useDropdown'; -import useLocalStorageContext from '../../../../hooks/useLocalstorage'; -import Dropdown from '../../../ui/dropdown/index'; - -const DateFormatDropdown = () => { - const { dateformat, setDateformat } = useLocalStorageContext(); - - const { dropdownIsOpen, toggleDropdown } = useDropdown(); - - const dateFormatsList = timeformats.map((format) => ( - setDateformat(format)} - showDot - isSelected={dateformat === format} - > - {format} - - )); - - return ( - <> - - - - {dateformat} - - - {dateFormatsList} - - - - ); -}; - -export default DateFormatDropdown; diff --git a/app/components/settings/general/dropdown/index.jsx b/app/components/settings/general/dropdown/index.jsx deleted file mode 100644 index e9f1c6e..0000000 --- a/app/components/settings/general/dropdown/index.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import TimezoneDropdown from './timezone'; -import DateformatDropdown from './dateFormat'; -import TimeformatDropdown from './timeFormat'; -import ColorsDropdown from './colors'; -import ThemesDropdown from './themes'; - -export { - TimezoneDropdown, - DateformatDropdown, - TimeformatDropdown, - ColorsDropdown, - ThemesDropdown, -}; diff --git a/app/components/settings/general/dropdown/themes.jsx b/app/components/settings/general/dropdown/themes.jsx deleted file mode 100644 index dc612b3..0000000 --- a/app/components/settings/general/dropdown/themes.jsx +++ /dev/null @@ -1,36 +0,0 @@ -import useDropdown from '../../../../hooks/useDropdown'; -import useLocalStorageContext from '../../../../hooks/useLocalstorage'; -import Dropdown from '../../../ui/dropdown/index'; - -const themes = { dark: 'Dark', light: 'Light' }; - -const ThemesDropdown = () => { - const { theme, setTheme } = useLocalStorageContext(); - const { dropdownIsOpen, toggleDropdown } = useDropdown(); - - return ( - <> - - - - {themes[theme]} - - - setTheme('dark')}>Dark - setTheme('light')}>Light - - - - ); -}; - -export default ThemesDropdown; diff --git a/app/components/settings/general/dropdown/timeFormat.jsx b/app/components/settings/general/dropdown/timeFormat.jsx deleted file mode 100644 index 564fe39..0000000 --- a/app/components/settings/general/dropdown/timeFormat.jsx +++ /dev/null @@ -1,56 +0,0 @@ -import useDropdown from '../../../../hooks/useDropdown'; -import useLocalStorageContext from '../../../../hooks/useLocalstorage'; -import Dropdown from '../../../ui/dropdown/index'; - -const times = { - 'HH:mm:ss': '23:59:59', - 'HH:mm': '23:59', - 'hh:mm': '11:59', - 'hh:mm A': '11:59 PM', -}; - -const TimeFormatDropdown = () => { - const { timeformat, setTimeformat } = useLocalStorageContext(); - const { dropdownIsOpen, toggleDropdown } = useDropdown(); - - const timeFormatList = [ - { name: '23:59:59', value: 'HH:mm:ss' }, - { name: '23:59', value: 'HH:mm' }, - { name: '11:59', value: 'hh:mm' }, - { name: '11:59 PM', value: 'hh:mm A' }, - ].map((time) => ( - setTimeformat(time.value)} - showDot - isSelected={time.value === timeformat} - > - {time.name} - - )); - - return ( - <> - - - - {times[timeformat]} - - - {timeFormatList} - - - - ); -}; - -export default TimeFormatDropdown; diff --git a/app/components/settings/general/dropdown/timezone.jsx b/app/components/settings/general/dropdown/timezone.jsx deleted file mode 100644 index 23855c3..0000000 --- a/app/components/settings/general/dropdown/timezone.jsx +++ /dev/null @@ -1,45 +0,0 @@ -import timezones from '../../../../constant/timeformats.json'; -import useDropdown from '../../../../hooks/useDropdown'; -import useLocalStorageContext from '../../../../hooks/useLocalstorage'; -import Dropdown from '../../../ui/dropdown/index'; - -const TimezoneDropdown = () => { - const { timezone, setTimezone } = useLocalStorageContext(); - const { dropdownIsOpen, toggleDropdown } = useDropdown(); - - const timezoneList = timezones.map((time) => ( - setTimezone(time.value)} - showDot - isSelected={time.value === timezone} - > - {time.name} - - )); - - return ( - <> - - - - {timezone} - - - {timezoneList} - - - - ); -}; - -export default TimezoneDropdown; diff --git a/app/components/settings/general/index.jsx b/app/components/settings/general/index.jsx deleted file mode 100644 index 966c8fc..0000000 --- a/app/components/settings/general/index.jsx +++ /dev/null @@ -1,81 +0,0 @@ -// import styles -import '../tab.scss'; -import './style.scss'; - -// import dependencies -import { observer } from 'mobx-react-lite'; - -// import local files -import TextInput from '../../ui/input'; -import { createPostRequest } from '../../../services/axios'; -import { - TimezoneDropdown, - DateformatDropdown, - TimeformatDropdown, - ColorsDropdown, - ThemesDropdown, -} from './dropdown'; -import AvatarSelect from '../../modal/settings/avatar'; -import useContextStore from '../../../context'; - -const SettingsGeneral = () => { - const { - userStore: { user, setUser }, - } = useContextStore(); - - const handleUpdate = async (e) => { - const value = e.target?.value?.trim(); - - if (!value) { - return; - } - - if (user.displayName !== value) { - await createPostRequest('/api/user/update/username', { - displayName: value, - }); - - setUser({ ...user, displayName: value }); - - return; - } - }; - - return ( -
-
General
- -
-
-
Profile Information
-
- Configure timezone and date format display settings -
- - - - - - - -
-
-
Date & Time
-
- Configure profile information and appearance -
- - - - -
-
-
- ); -}; - -export default observer(SettingsGeneral); diff --git a/app/components/settings/general/style.scss b/app/components/settings/general/style.scss deleted file mode 100644 index 9d73297..0000000 --- a/app/components/settings/general/style.scss +++ /dev/null @@ -1,62 +0,0 @@ -@import '../../../styles/global.scss'; - -.settings-general-container { - padding: pxToRem(4); - flex: 1; - display: flex; - flex-direction: column; -} - -.settings-general-content { - flex: 1; - display: flex; - gap: pxToRem(12); - padding: 0 pxToRem(8) pxToRem(20) pxToRem(8); - overflow-y: auto; -} - -.settings-general-profile { - flex: 1; -} - -.settings-general-date { - flex: 1; -} - -.settings-general-title { - color: var(--font-color); - font-size: var(--font-2xl); - font-weight: 700; -} - -.settings-general-subtitle { - color: var(--accent-200); - font-size: var(--font-lg); - font-weight: 500; - margin-bottom: pxToRem(12); -} - -.avatar-input { - width: 100%; - height: pxToRem(50); - background-color: var(--accent-800); - color: var(--font-color); - padding: 0 pxToRem(8); - font-size: var(--font-md); - font-weight: var(--weight-medium); - border-radius: var(--radius-md); - margin-top: pxToRem(4); - border: 2px solid #ffffff00; - display: flex; - align-items: center; - - &:hover { - cursor: pointer; - } -} - -@include tablet { - .settings-general-content { - flex-direction: column; - } -} diff --git a/app/components/settings/tab.scss b/app/components/settings/tab.scss deleted file mode 100644 index d93e6d9..0000000 --- a/app/components/settings/tab.scss +++ /dev/null @@ -1,39 +0,0 @@ -@import '../../styles/global.scss'; - -.settings-tab { - display: flex; - flex-direction: column; - width: 250px; - background-color: var(--accent-800); - padding: pxToRem(4); -} - -.settings-tab-title { - padding: pxToRem(12); - color: var(--accent-100); - font-size: var(--font-2xl); - font-weight: 700; - text-align: center; - border-bottom: pxToRem(3) solid var(--accent-600); - margin-bottom: pxToRem(12); -} - -.settings-tab-text { - color: var(--accent-100); - font-size: var(--font-2xl); - font-weight: 500; - cursor: pointer; - transition: background-color 0.2s ease-in-out; - margin: pxToRem(4); - padding: pxToRem(8) pxToRem(16); - border-radius: pxToRem(12); - - &:hover { - background-color: var(--accent-900); - } - - &.active { - background-color: var(--accent-900); - color: var(--primary-500); - } -} From ba246a46a9a4a3148a7ffaf302e6fa41bba4469e Mon Sep 17 00:00:00 2001 From: ksjaay Date: Sat, 1 Jun 2024 23:09:45 +0100 Subject: [PATCH 04/28] Updates test:server to build before starting server --- app/assets/react.svg | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 app/assets/react.svg diff --git a/app/assets/react.svg b/app/assets/react.svg deleted file mode 100644 index 7b17ad7..0000000 --- a/app/assets/react.svg +++ /dev/null @@ -1,4 +0,0 @@ - \ No newline at end of file From 292d37dfe7881aa94858ab84635396b556ee1fbe Mon Sep 17 00:00:00 2001 From: ksjaay Date: Sat, 1 Jun 2024 23:11:16 +0100 Subject: [PATCH 05/28] NEW ICONS --- app/components/icons/faCircleCheck.jsx | 30 ++++++++++++++++++++++++ app/components/icons/faUserCircle.jsx | 25 ++++++++++++++++++++ app/components/icons/faUsers.jsx | 25 ++++++++++++++++++++ app/components/icons/index.jsx | 24 +++++++++++++++++++ app/components/icons/ioArrowBack.jsx | 31 +++++++++++++++++++++++++ app/components/icons/ioColorPalette.jsx | 25 ++++++++++++++++++++ app/components/icons/liaSyncSolid.jsx | 25 ++++++++++++++++++++ app/components/icons/mdEye.jsx | 25 ++++++++++++++++++++ app/components/icons/mdEyeOff.jsx | 25 ++++++++++++++++++++ app/components/icons/mdHelpCircle.jsx | 25 ++++++++++++++++++++ 10 files changed, 260 insertions(+) create mode 100644 app/components/icons/faCircleCheck.jsx create mode 100644 app/components/icons/faUserCircle.jsx create mode 100644 app/components/icons/faUsers.jsx create mode 100644 app/components/icons/ioArrowBack.jsx create mode 100644 app/components/icons/ioColorPalette.jsx create mode 100644 app/components/icons/liaSyncSolid.jsx create mode 100644 app/components/icons/mdEye.jsx create mode 100644 app/components/icons/mdEyeOff.jsx create mode 100644 app/components/icons/mdHelpCircle.jsx diff --git a/app/components/icons/faCircleCheck.jsx b/app/components/icons/faCircleCheck.jsx new file mode 100644 index 0000000..fb546b7 --- /dev/null +++ b/app/components/icons/faCircleCheck.jsx @@ -0,0 +1,30 @@ +// import dependencies +import PropTypes from 'prop-types'; + +const FaCircleCheck = ({ height, width, checkColor = 'white' }) => ( + + + + +); + +FaCircleCheck.displayName = 'FaCircleCheck'; + +FaCircleCheck.propTypes = { + width: PropTypes.number, + height: PropTypes.number, + checkColor: PropTypes.string, +}; + +export default FaCircleCheck; diff --git a/app/components/icons/faUserCircle.jsx b/app/components/icons/faUserCircle.jsx new file mode 100644 index 0000000..da54c56 --- /dev/null +++ b/app/components/icons/faUserCircle.jsx @@ -0,0 +1,25 @@ +// import dependencies +import PropTypes from 'prop-types'; + +const FaUserCircle = ({ width = 25, height = 25 }) => ( + + + +); + +FaUserCircle.displayName = 'FaUserCircle'; + +FaUserCircle.propTypes = { + width: PropTypes.number, + height: PropTypes.number, +}; + +export default FaUserCircle; diff --git a/app/components/icons/faUsers.jsx b/app/components/icons/faUsers.jsx new file mode 100644 index 0000000..7dead35 --- /dev/null +++ b/app/components/icons/faUsers.jsx @@ -0,0 +1,25 @@ +// import dependencies +import PropTypes from 'prop-types'; + +const FaUsers = ({ height = 25, width = 25 }) => ( + + + +); + +FaUsers.displayName = 'FaUsers'; + +FaUsers.propTypes = { + width: PropTypes.number, + height: PropTypes.number, +}; + +export default FaUsers; diff --git a/app/components/icons/index.jsx b/app/components/icons/index.jsx index 5040a49..c2f6d61 100644 --- a/app/components/icons/index.jsx +++ b/app/components/icons/index.jsx @@ -1,6 +1,11 @@ import BsTable from './bsTable'; import FaCheck from './faCheck'; +import FaChevronDown from './faChevronDown'; +import FaChevronLeft from './faChevronLeft'; +import FaChevronRight from './faChevronRight'; import FaChevronUp from './faChevronUp'; +import FaCircleCheck from './faCircleCheck'; +import FaUserCircle from './faUserCircle'; import FaClose from './faClose'; import FaCog from './faCog'; import FaEllipsisVertical from './faEllipsisVertical'; @@ -12,15 +17,27 @@ import FaTrash from './faTrash'; import FiLayout from './fiLayout'; import HiStatusOffline from './hiStatusOffline'; import HiStatusOnline from './hiStatusOnline'; +import IoArrowBack from './ioArrowBack'; +import IoColorPalette from './ioColorPalette'; import IoGrid from './ioGrid'; +import LiaSyncSolid from './liaSyncSolid'; import MdEdit from './mdEdit'; +import MdErrorOutline from './mdErrorOutline'; +import MdEye from './mdEye'; +import MdEyeOff from './mdEyeOff'; +import MdHelpCircle from './mdHelpCircle'; import PiListFill from './piListFill'; import StatusLogo from './statusLogo'; export { BsTable, FaCheck, + FaChevronDown, + FaChevronLeft, + FaChevronRight, + FaCircleCheck, FaChevronUp, + FaUserCircle, FaClose, FaCog, FaEllipsisVertical, @@ -32,8 +49,15 @@ export { FiLayout, HiStatusOffline, HiStatusOnline, + IoArrowBack, + IoColorPalette, IoGrid, + LiaSyncSolid, MdEdit, + MdErrorOutline, + MdEye, + MdEyeOff, + MdHelpCircle, PiListFill, StatusLogo, }; diff --git a/app/components/icons/ioArrowBack.jsx b/app/components/icons/ioArrowBack.jsx new file mode 100644 index 0000000..f4e4196 --- /dev/null +++ b/app/components/icons/ioArrowBack.jsx @@ -0,0 +1,31 @@ +// import dependencies +import PropTypes from 'prop-types'; + +const IoArrowBack = ({ height = 25, width = 25 }) => ( + + + +); + +IoArrowBack.displayName = 'IoArrowBack'; + +IoArrowBack.propTypes = { + height: PropTypes.number, + width: PropTypes.number, +}; + +export default IoArrowBack; diff --git a/app/components/icons/ioColorPalette.jsx b/app/components/icons/ioColorPalette.jsx new file mode 100644 index 0000000..bf65395 --- /dev/null +++ b/app/components/icons/ioColorPalette.jsx @@ -0,0 +1,25 @@ +// import dependencies +import PropTypes from 'prop-types'; + +const IoColorPalette = ({ height = 25, width = 25 }) => ( + + + +); + +IoColorPalette.displayName = 'IoColorPalette'; + +IoColorPalette.propTypes = { + height: PropTypes.number, + width: PropTypes.number, +}; + +export default IoColorPalette; diff --git a/app/components/icons/liaSyncSolid.jsx b/app/components/icons/liaSyncSolid.jsx new file mode 100644 index 0000000..0703941 --- /dev/null +++ b/app/components/icons/liaSyncSolid.jsx @@ -0,0 +1,25 @@ +// import dependencies +import PropTypes from 'prop-types'; + +const LiaSyncSolid = ({ height, width }) => ( + + + +); + +LiaSyncSolid.displayName = 'LiaSyncSolid'; + +LiaSyncSolid.propTypes = { + width: PropTypes.number, + height: PropTypes.number, +}; + +export default LiaSyncSolid; diff --git a/app/components/icons/mdEye.jsx b/app/components/icons/mdEye.jsx new file mode 100644 index 0000000..d62331f --- /dev/null +++ b/app/components/icons/mdEye.jsx @@ -0,0 +1,25 @@ +// import dependencies +import PropTypes from 'prop-types'; + +const MdEye = ({ width = 25, height = 25 }) => ( + + + +); + +MdEye.displayName = 'MdEye'; + +MdEye.propTypes = { + width: PropTypes.number, + height: PropTypes.number, +}; + +export default MdEye; diff --git a/app/components/icons/mdEyeOff.jsx b/app/components/icons/mdEyeOff.jsx new file mode 100644 index 0000000..e94def6 --- /dev/null +++ b/app/components/icons/mdEyeOff.jsx @@ -0,0 +1,25 @@ +// import dependencies +import PropTypes from 'prop-types'; + +const MdEyeOff = ({ width = 25, height = 25 }) => ( + + + +); + +MdEyeOff.displayName = 'MdEyeOff'; + +MdEyeOff.propTypes = { + width: PropTypes.number, + height: PropTypes.number, +}; + +export default MdEyeOff; diff --git a/app/components/icons/mdHelpCircle.jsx b/app/components/icons/mdHelpCircle.jsx new file mode 100644 index 0000000..a3a46c4 --- /dev/null +++ b/app/components/icons/mdHelpCircle.jsx @@ -0,0 +1,25 @@ +// import dependencies +import PropTypes from 'prop-types'; + +const MdHelpCircle = ({ width = 24, height = 24 }) => ( + + + +); + +MdHelpCircle.displayName = 'MdHelpCircle'; + +MdHelpCircle.propTypes = { + width: PropTypes.number, + height: PropTypes.number, +}; + +export default MdHelpCircle; From 3b85e44171555c82327473cb8850f7e0edde2932 Mon Sep 17 00:00:00 2001 From: ksjaay Date: Sat, 1 Jun 2024 23:12:48 +0100 Subject: [PATCH 06/28] Updates/adds new modals for settings page --- .../modal/settings/account/avatar.jsx | 100 ++++++++++++ .../modal/settings/account/avatar.scss | 36 ++++ .../modal/settings/account/delete.jsx | 79 +++++++++ .../modal/settings/account/password.jsx | 135 +++++++++++++++ .../modal/settings/account/transfer.jsx | 154 ++++++++++++++++++ .../modal/settings/account/username.jsx | 77 +++++++++ .../modal/settings/manage/approve.jsx | 1 + .../modal/settings/manage/decline.jsx | 1 + .../modal/settings/manage/delete.jsx | 1 + .../modal/settings/manage/permissions.jsx | 1 + 10 files changed, 585 insertions(+) create mode 100644 app/components/modal/settings/account/avatar.jsx create mode 100644 app/components/modal/settings/account/avatar.scss create mode 100644 app/components/modal/settings/account/delete.jsx create mode 100644 app/components/modal/settings/account/password.jsx create mode 100644 app/components/modal/settings/account/transfer.jsx create mode 100644 app/components/modal/settings/account/username.jsx diff --git a/app/components/modal/settings/account/avatar.jsx b/app/components/modal/settings/account/avatar.jsx new file mode 100644 index 0000000..be02cac --- /dev/null +++ b/app/components/modal/settings/account/avatar.jsx @@ -0,0 +1,100 @@ +import './avatar.scss'; + +// import dependencies +import PropTypes from 'prop-types'; +import { useState } from 'react'; + +// import local files +import Modal from '../../../ui/modal'; +import TextInput from '../../../ui/input'; + +const avatars = [ + 'Ape', + 'Bear', + 'Cat', + 'Dog', + 'Duck', + 'Eagle', + 'Fox', + 'Gerbil', + 'Hamster', + 'Hedgehog', + 'Koala', + 'Ostrich', + 'Panda', + 'Rabbit', + 'Rocket', + 'Smart-Dog', + 'Tiger', +]; + +const isImageUrl = (url) => { + if (typeof url !== 'string') { + return false; + } + + return url.match(/^https?:\/\/.+\.(jpg|jpeg|png|gif)$/gim); +}; + +const SettingsAccountAvatarModal = ({ + value = 'Panda', + closeModal, + handleSumbit, +}) => { + const [avatar, setAvatar] = useState(value); + + const isUrl = isImageUrl(avatar); + const imageUrl = isUrl ? avatar : `/icons/${avatar}.png`; + + return ( + <> + Change Avatar + +
+ +
+ setAvatar(e.target.value)} + /> + +
Or select from below
+
+ {avatars.map((avatarName) => ( + {avatarName} setAvatar(avatarName)} + /> + ))} +
+
+ + + + Cancel + + handleSumbit(avatar)}> + Update + + + + ); +}; + +SettingsAccountAvatarModal.displayName = 'SettingsAccountAvatarModal'; + +SettingsAccountAvatarModal.propTypes = { + value: PropTypes.string.isRequired, + closeModal: PropTypes.func.isRequired, + handleSumbit: PropTypes.func.isRequired, +}; + +export default SettingsAccountAvatarModal; diff --git a/app/components/modal/settings/account/avatar.scss b/app/components/modal/settings/account/avatar.scss new file mode 100644 index 0000000..0d3dc8d --- /dev/null +++ b/app/components/modal/settings/account/avatar.scss @@ -0,0 +1,36 @@ +@import '../../../../styles/global.scss'; + +.settings-modal-avatar-container { + display: flex; + justify-content: center; + align-items: center; +} + +.settings-modal-avatar-image { + width: pxToRem(100); + height: pxToRem(100); + border-radius: var(--radius-pill); +} + +.settings-modal-avatars-container { + display: flex; + flex-wrap: wrap; + gap: 8px; +} + +.settings-modal-avatar-option { + width: pxToRem(60); + height: pxToRem(60); + border: pxToRem(2) solid #00000000; + + &:hover { + border: pxToRem(2) solid var(--primary-600); + cursor: pointer; + } +} + +.settings-modal-avatar-option-select { + width: pxToRem(60); + height: pxToRem(60); + border: pxToRem(2) solid var(--primary-600); +} diff --git a/app/components/modal/settings/account/delete.jsx b/app/components/modal/settings/account/delete.jsx new file mode 100644 index 0000000..7f12419 --- /dev/null +++ b/app/components/modal/settings/account/delete.jsx @@ -0,0 +1,79 @@ +import './avatar.scss'; + +// import dependencies +import PropTypes from 'prop-types'; +import { toast } from 'sonner'; + +// import local files +import Modal from '../../../ui/modal'; +import TextInput from '../../../ui/input'; + +import { AlertError } from '../../../ui/alert'; + +const SettingsAccountDeleteModal = ({ closeModal, handleSumbit }) => { + return ( + <> + Delete Account + + + + + To verify, type{' '} + delete account below: + + } + /> + +
+ By continuing, your account will be deleted, along with any access you + have to data. +
+
+ + + + Cancel + + { + const transferConfirm = document.getElementById( + 'settings-transfer-confirm' + ).value; + + if (transferConfirm.toLowerCase().trim() !== 'delete account') { + toast.error('Enter delete account to confirm.'); + return; + } + + handleSumbit(); + }} + > + Delete account + + + + ); +}; + +SettingsAccountDeleteModal.displayName = 'SettingsAccountDeleteModal'; + +SettingsAccountDeleteModal.propTypes = { + closeModal: PropTypes.func.isRequired, + handleSumbit: PropTypes.func.isRequired, +}; + +export default SettingsAccountDeleteModal; diff --git a/app/components/modal/settings/account/password.jsx b/app/components/modal/settings/account/password.jsx new file mode 100644 index 0000000..a037fc2 --- /dev/null +++ b/app/components/modal/settings/account/password.jsx @@ -0,0 +1,135 @@ +// import dependencies +import PropTypes from 'prop-types'; + +// import local files +import Modal from '../../../ui/modal'; +import TextInput from '../../../ui/input'; +import RegisterChecklist from '../../../register/checklist'; +import { useState } from 'react'; +import { MdEye, MdEyeOff } from '../../../icons'; +import handleChangePassword from '../../../../handlers/settings/account/password'; +import validators from '../../../../../server/utils/validators'; + +const SettingsAccountPasswordModal = ({ modalTitle, id, closeModal }) => { + const [values, setValues] = useState({ + current: '', + new: '', + repeat: '', + showPassword: false, + showNewPassword: false, + errors: {}, + }); + + const handleOnBlur = (key, value) => { + const isInvalidPassword = validators.auth.password(value); + handleErrors(key, isInvalidPassword?.password || null); + }; + + const handlePasswordChange = (key, value) => { + setValues((prev) => ({ + ...prev, + [key]: value, + })); + }; + + const handleErrors = (key, error) => { + setValues((prev) => ({ + ...prev, + errors: { + ...prev.errors, + [key]: error, + }, + })); + }; + + const submit = async () => { + const { + current: currentPassword, + new: newPassword, + repeat: repeatPassword, + } = values; + + await handleChangePassword({ + currentPassword, + newPassword, + repeatPassword, + handleErrors, + closeModal, + }); + }; + + return ( + <> + {modalTitle} + + handlePasswordChange('current', e.target.value)} + onBlur={(e) => handleOnBlur('current', e.target.value)} + type={values.showPassword ? 'text' : 'password'} + iconRight={ +
+ handlePasswordChange('showPassword', !values.showPassword) + } + > + {values.showPassword ? : } +
+ } + error={values.errors.current} + /> + handlePasswordChange('new', e.target.value)} + onBlur={(e) => handleOnBlur('new', e.target.value)} + type={values.showNewPassword ? 'text' : 'password'} + value={values.new} + iconRight={ +
+ handlePasswordChange('showNewPassword', !values.showNewPassword) + } + > + {values.showNewPassword ? : } +
+ } + error={values.errors.new} + /> + + + + handlePasswordChange('repeat', e.target.value)} + onBlur={(e) => handleOnBlur('repeat', e.target.value)} + type={'password'} + value={values.repeat} + error={values.errors.repeat} + /> +
+ + + + Cancel + + + Update + + + + ); +}; + +SettingsAccountPasswordModal.displayName = 'SettingsAccountPasswordModal'; + +SettingsAccountPasswordModal.propTypes = { + modalTitle: PropTypes.string.isRequired, + id: PropTypes.string.isRequired, + closeModal: PropTypes.func.isRequired, +}; + +export default SettingsAccountPasswordModal; diff --git a/app/components/modal/settings/account/transfer.jsx b/app/components/modal/settings/account/transfer.jsx new file mode 100644 index 0000000..79b8edd --- /dev/null +++ b/app/components/modal/settings/account/transfer.jsx @@ -0,0 +1,154 @@ +import './avatar.scss'; + +// import dependencies +import PropTypes from 'prop-types'; +import { useEffect } from 'react'; +import { observer } from 'mobx-react-lite'; +import { toast } from 'sonner'; + +// import local files +import Modal from '../../../ui/modal'; +import TextInput from '../../../ui/input'; +import useTeamContext from '../../../../context/team'; +import { createGetRequest } from '../../../../services/axios'; +import useDropdown from '../../../../hooks/useDropdown'; +import Dropdown from '../../../ui/dropdown'; +import { AlertError } from '../../../ui/alert'; + +const SettingsAccountTransferModal = ({ closeModal, handleSumbit }) => { + const { getTeam, setTeam } = useTeamContext(); + const { dropdownIsOpen, selectedId, toggleDropdown, handleDropdownSelect } = + useDropdown(); + const team = getTeam(); + + const sortedMembers = team?.sort((a, b) => a?.permission - b?.permission); + + useEffect(() => { + const fetchTeam = async () => { + try { + const query = await createGetRequest('/api/user/team'); + + setTeam(query.data); + } catch (error) { + console.log(error); + toast.error("Couldn't fetch team members"); + } + }; + + fetchTeam(); + }, []); + + const dropdownItems = sortedMembers.map((member) => ( + { + handleDropdownSelect(member.email); + toggleDropdown(); + }} + showDot + isSelected={selectedId === member.email} + dotColor="primary" + > + {member.email} + + )); + + return ( + <> + + Transfer ownership + + + + +
+ Select member to transfer ownership +
+ + + + {selectedId || 'Select member'} + + + {dropdownItems} + + + + + To verify, type{' '} + transfer ownership{' '} + below: + + } + /> + +
+ By continuing, you acknowledge that the application will be + transferred to the selected user. +
+
+ + + + Cancel + + { + const transferConfirm = document.getElementById( + 'settings-transfer-confirm' + ).value; + + if (transferConfirm.toLowerCase().trim() !== 'transfer ownership') { + toast.error('Enter transfer ownership to confirm.'); + return; + } + + handleSumbit(selectedId); + }} + > + Confirm + + + + ); +}; + +SettingsAccountTransferModal.displayName = 'SettingsAccountTransferModal'; + +SettingsAccountTransferModal.propTypes = { + closeModal: PropTypes.func.isRequired, + handleSumbit: PropTypes.func.isRequired, +}; + +export default observer(SettingsAccountTransferModal); diff --git a/app/components/modal/settings/account/username.jsx b/app/components/modal/settings/account/username.jsx new file mode 100644 index 0000000..9253b04 --- /dev/null +++ b/app/components/modal/settings/account/username.jsx @@ -0,0 +1,77 @@ +// import dependencies +import PropTypes from 'prop-types'; + +// import local files +import Modal from '../../../ui/modal'; +import TextInput from '../../../ui/input'; +import { useState } from 'react'; +import handleChangeUsername from '../../../../handlers/settings/account/username'; +import { observer } from 'mobx-react-lite'; +import useContextStore from '../../../../context'; + +const SettingsAccountUsernameModal = ({ + title, + modalTitle, + id, + value, + closeModal, +}) => { + const [error, setError] = useState(null); + + const { + userStore: { updateUsingKey }, + } = useContextStore(); + + const handleError = (error) => { + setError(error); + }; + + const submit = async () => { + const value = document.getElementById(`settings-edit-${id}`).value; + const query = await handleChangeUsername( + value, + setError, + closeModal, + handleError + ); + + if (query === true) { + updateUsingKey('displayName', value); + } + }; + + return ( + <> + {modalTitle} + + + + + + + Cancel + + + Update + + + + ); +}; + +SettingsAccountUsernameModal.displayName = 'SettingsAccountUsernameModal'; + +SettingsAccountUsernameModal.propTypes = { + title: PropTypes.string.isRequired, + modalTitle: PropTypes.string.isRequired, + id: PropTypes.string.isRequired, + value: PropTypes.string.isRequired, + closeModal: PropTypes.func.isRequired, +}; + +export default observer(SettingsAccountUsernameModal); diff --git a/app/components/modal/settings/manage/approve.jsx b/app/components/modal/settings/manage/approve.jsx index 2822178..784fc4a 100644 --- a/app/components/modal/settings/manage/approve.jsx +++ b/app/components/modal/settings/manage/approve.jsx @@ -23,6 +23,7 @@ const MemberApproveModal = ({ member, onClose }) => { toast.success('User request approved successfully.'); onClose(); } catch (error) { + console.log(error); toast.error("Error approving user's request."); } }; diff --git a/app/components/modal/settings/manage/decline.jsx b/app/components/modal/settings/manage/decline.jsx index af71dbc..2c044df 100644 --- a/app/components/modal/settings/manage/decline.jsx +++ b/app/components/modal/settings/manage/decline.jsx @@ -22,6 +22,7 @@ const MemberDeclineModal = ({ member, onClose }) => { toast.success('User request declined successfully.'); onClose(); } catch (error) { + console.log(error); toast.error("Error declining user's request."); } }; diff --git a/app/components/modal/settings/manage/delete.jsx b/app/components/modal/settings/manage/delete.jsx index fa43b68..c48d035 100644 --- a/app/components/modal/settings/manage/delete.jsx +++ b/app/components/modal/settings/manage/delete.jsx @@ -22,6 +22,7 @@ const MemberDeleteModal = ({ member, onClose }) => { toast.success('User has been removed successfully.'); onClose(); } catch (error) { + console.log(error); toast.error("Error declining user's request."); } }; diff --git a/app/components/modal/settings/manage/permissions.jsx b/app/components/modal/settings/manage/permissions.jsx index f3db149..973111a 100644 --- a/app/components/modal/settings/manage/permissions.jsx +++ b/app/components/modal/settings/manage/permissions.jsx @@ -45,6 +45,7 @@ const MemberPermissionsModal = ({ member, onClose }) => { toast.success('User permissions updated successfully.'); onClose(); } catch (error) { + console.log(error); if (error.response?.status === 400) { return toast.error( "You don't have permission to assign this permission." From 04b73506e11633d7be745e95f7225e3776b2aad9 Mon Sep 17 00:00:00 2001 From: ksjaay Date: Sat, 1 Jun 2024 23:13:59 +0100 Subject: [PATCH 07/28] Adds components for personal account settings --- app/components/settings/account/avatar.jsx | 94 +++++++++++++++ app/components/settings/account/avatar.scss | 61 ++++++++++ app/components/settings/account/index.jsx | 70 ++++++++++++ .../settings/account/item/desktop.jsx | 108 ++++++++++++++++++ .../settings/account/item/desktop.scss | 16 +++ .../settings/account/item/mobile.jsx | 93 +++++++++++++++ .../settings/account/item/mobile.scss | 49 ++++++++ .../settings/account/menu/mobile.jsx | 0 .../settings/account/menu/mobile.scss | 0 app/components/settings/account/style.scss | 64 +++++++++++ app/components/settings/tab.jsx | 42 ------- 11 files changed, 555 insertions(+), 42 deletions(-) create mode 100644 app/components/settings/account/avatar.jsx create mode 100644 app/components/settings/account/avatar.scss create mode 100644 app/components/settings/account/index.jsx create mode 100644 app/components/settings/account/item/desktop.jsx create mode 100644 app/components/settings/account/item/desktop.scss create mode 100644 app/components/settings/account/item/mobile.jsx create mode 100644 app/components/settings/account/item/mobile.scss create mode 100644 app/components/settings/account/menu/mobile.jsx create mode 100644 app/components/settings/account/menu/mobile.scss create mode 100644 app/components/settings/account/style.scss delete mode 100644 app/components/settings/tab.jsx diff --git a/app/components/settings/account/avatar.jsx b/app/components/settings/account/avatar.jsx new file mode 100644 index 0000000..8a7ca85 --- /dev/null +++ b/app/components/settings/account/avatar.jsx @@ -0,0 +1,94 @@ +import './avatar.scss'; + +// import dependencies +import { observer } from 'mobx-react-lite'; + +// import local files +import useContextStore from '../../../context'; +import Button from '../../ui/button'; +import SettingsAccountAvatarModal from '../../modal/settings/account/avatar'; +import { toast } from 'sonner'; +import { createPostRequest } from '../../../services/axios'; + +const userPermissionNames = { 1: 'Owner', 2: 'Admin', 3: 'Editor', 4: 'Guest' }; + +const isImageUrl = (url) => { + if (typeof url !== 'string') { + return false; + } + return url.match(/^https?:\/\/.+\.(jpg|jpeg|png|gif)$/gim) !== null; +}; + +const SettingsAccountAvatar = () => { + const { + userStore: { + user: { avatar, displayName, permission }, + updateUsingKey, + }, + modalStore: { openModal, closeModal }, + } = useContextStore(); + + const avatarUrl = isImageUrl(avatar) ? avatar : `/icons/${avatar}.png`; + + const userAvatar = avatar ? ( + + ) : ( +
+ {displayName?.charAt(0)} +
+ ); + + const handleAvatarChange = async (selectedAvatar) => { + try { + await createPostRequest('/api/user/update/avatar', { + avatar: selectedAvatar, + }); + + updateUsingKey('avatar', selectedAvatar); + + toast.success('Avatar successfully updated'); + closeModal(); + } catch (error) { + console.log(error); + toast.error('Something went wrong, please try again later.'); + } + }; + + return ( +
+ {userAvatar} +
+
+ {displayName} +
+
+ {userPermissionNames[permission]} +
+
+
+ + +
+
+ ); +}; + +export default observer(SettingsAccountAvatar); diff --git a/app/components/settings/account/avatar.scss b/app/components/settings/account/avatar.scss new file mode 100644 index 0000000..f41b2d5 --- /dev/null +++ b/app/components/settings/account/avatar.scss @@ -0,0 +1,61 @@ +@import '../../../styles/global.scss'; + +.settings-account-avatar-container { + display: flex; + align-items: center; + gap: pxToRem(15); + margin-bottom: pxToRem(20); +} + +.settings-account-avatar-image-default { + display: flex; + align-items: center; + justify-content: center; + width: pxToRem(150); + height: pxToRem(150); + border-radius: var(--radius-pill); + border: 3px solid var(--gray-600); + background-color: var(--primary-700); + font-size: var(--font-3xl); + color: var(--font-color); +} + +.settings-account-avatar-image { + display: flex; + width: pxToRem(150); + height: pxToRem(150); + border-radius: var(--radius-pill); + border: 3px solid var(--gray-600); +} + +.settings-account-avatar-button-container { + flex: 1; + display: flex; + justify-content: flex-end; + align-items: center; + gap: 10px; +} + +@include tablet { + .settings-account-avatar-button-container { + flex-direction: column; + align-items: flex-end; + margin-top: 20px; + } +} + +@include mobile { + .settings-account-avatar-button-container { + flex-direction: row; + margin-top: 0; + } + + .settings-account-avatar-container { + flex-direction: column; + align-items: center; + } + + .settings-account-avatar-info { + text-align: center; + } +} diff --git a/app/components/settings/account/index.jsx b/app/components/settings/account/index.jsx new file mode 100644 index 0000000..0aadcd7 --- /dev/null +++ b/app/components/settings/account/index.jsx @@ -0,0 +1,70 @@ +import './../ui/tab/tab.scss'; +import './style.scss'; + +// import local files +import Button from '../../ui/button'; +import SettingsAccountDesktopItem from './item/desktop'; +import SettingsAccountMobileItem from './item/mobile'; +import SettingsAccountAvatar from './avatar'; + +const accountItems = [ + { + title: 'Email', + id: 'email', + }, + { + title: 'Username', + modalTitle: 'Edit your username', + id: 'displayName', + canEdit: true, + }, + { + title: 'Password', + modalTitle: 'Change Password', + id: 'password', + canEdit: true, + }, + { + title: 'Transfer Ownership', + id: 'transfer', + description: 'Transfer ownership to another user', + customButton: ( +
+ +
+ ), + }, + { + title: 'Delete Account', + id: 'delete', + description: 'Your account will be removed from our database', + customButton: ( +
+ +
+ ), + fontColor: 'red', + }, +]; + +const SettingsAccount = () => { + return ( +
+ + + + {accountItems.map((item) => ( + + ))} + + + + {accountItems.map((item) => ( + + ))} + +
+ ); +}; + +export default SettingsAccount; diff --git a/app/components/settings/account/item/desktop.jsx b/app/components/settings/account/item/desktop.jsx new file mode 100644 index 0000000..309853d --- /dev/null +++ b/app/components/settings/account/item/desktop.jsx @@ -0,0 +1,108 @@ +import './desktop.scss'; + +// import dependencies +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import { observer } from 'mobx-react-lite'; + +// import local files +import Button from '../../../ui/button'; +import useContextStore from '../../../../context'; + +import SettingsAccountAvatarModal from '../../../modal/settings/account/avatar'; +import SettingsAccountDeleteModal from '../../../modal/settings/account/delete'; +import SettingsAccountPasswordModal from '../../../modal/settings/account/password'; +import SettingsAccountTransferModal from '../../../modal/settings/account/transfer'; +import SettingsAccountUsernameModal from '../../../modal/settings/account/username'; + +const selectModal = (id, props, closeModal) => { + switch (id) { + case 'displayName': + return ( + + ); + case 'password': + return ( + + ); + case 'avatar': + return ; + case 'transfer': + return ( + + ); + case 'delete': + return ; + default: + return null; + } +}; + +const SettingsAccountDesktopItem = ({ + title, + id, + canEdit, + description, + customButton, + ...props +}) => { + const classes = classNames({ + 'settings-account-item': !description, + 'settings-account-item-vertical': description, + }); + + const { + userStore: { user }, + modalStore: { openModal, closeModal }, + } = useContextStore(); + + return ( +
+
+
{title}
+ {!description && ( +
+ {id === 'password' ? '* * * * * * * *' : user[id]} +
+ )} + {description && ( +
{description}
+ )} +
+ { + const content = selectModal( + id, + { title, id, canEdit, value: user[id], ...props }, + closeModal + ); + + if (!content) { + return; + } + + openModal(content); + }} + > + {canEdit && !customButton && ( +
+ +
+ )} + {customButton ? customButton : null} +
+
+ ); +}; + +SettingsAccountDesktopItem.displayName = 'SettingsAccountDesktopItem'; + +SettingsAccountDesktopItem.propTypes = { + title: PropTypes.string.isRequired, + id: PropTypes.string.isRequired, + canEdit: PropTypes.bool, + description: PropTypes.string, + customButton: PropTypes.element, +}; + +export default observer(SettingsAccountDesktopItem); diff --git a/app/components/settings/account/item/desktop.scss b/app/components/settings/account/item/desktop.scss new file mode 100644 index 0000000..584d79f --- /dev/null +++ b/app/components/settings/account/item/desktop.scss @@ -0,0 +1,16 @@ +@import '../../../../styles/global.scss'; + +.settings-account-item-vertical { + display: flex; + flex-direction: column; + justify-content: flex-start; + margin-bottom: pxToRem(8); +} + +.settings-account-item-buttons { + display: flex; + flex-direction: column; + gap: 10px; + margin-top: 10px; + width: fit-content; +} diff --git a/app/components/settings/account/item/mobile.jsx b/app/components/settings/account/item/mobile.jsx new file mode 100644 index 0000000..d6537c5 --- /dev/null +++ b/app/components/settings/account/item/mobile.jsx @@ -0,0 +1,93 @@ +import './mobile.scss'; + +// import dependencies +import PropTypes from 'prop-types'; +import { observer } from 'mobx-react-lite'; + +// import local files +import { FaChevronRight } from '../../../icons'; +import useContextStore from '../../../../context'; +import SettingsAccountAvatarModal from '../../../modal/settings/account/avatar'; +import SettingsAccountDeleteModal from '../../../modal/settings/account/delete'; +import SettingsAccountPasswordModal from '../../../modal/settings/account/password'; +import SettingsAccountTransferModal from '../../../modal/settings/account/transfer'; +import SettingsAccountEditModal from '../../../modal/settings/account/username'; + +const selectModal = (id, props, closeModal) => { + switch (id) { + case 'displayName': + return ; + case 'password': + return ( + + ); + case 'avatar': + return ; + case 'transfer': + return ( + + ); + case 'delete': + return ; + default: + return null; + } +}; + +const SettingsAccountMobileItem = ({ + title, + id, + canEdit, + fontColor, + ...props +}) => { + const { + userStore: { user }, + modalStore: { openModal, closeModal }, + } = useContextStore(); + + const color = !fontColor ? {} : { color: `var(--${fontColor}-700)` }; + + return ( +
{ + const content = selectModal( + id, + { title, id, canEdit, fontColor, value: user[id], ...props }, + closeModal + ); + + if (!content) { + return; + } + + openModal(content); + }} + > +
+ {title} +
+
+
{user[id]}
+ + {canEdit && ( +
+ +
+ )} +
+
+ ); +}; + +SettingsAccountMobileItem.displayName = 'SettingsAccountMobileItem'; + +SettingsAccountMobileItem.propTypes = { + title: PropTypes.string.isRequired, + id: PropTypes.string.isRequired, + canEdit: PropTypes.bool, + fontColor: PropTypes.string, +}; + +export default observer(SettingsAccountMobileItem); diff --git a/app/components/settings/account/item/mobile.scss b/app/components/settings/account/item/mobile.scss new file mode 100644 index 0000000..e68428a --- /dev/null +++ b/app/components/settings/account/item/mobile.scss @@ -0,0 +1,49 @@ +@import '../../../../styles/global.scss'; + +.settings-account-mobile-item { + display: flex; + padding: 12px 8px; + justify-content: center; + align-items: center; + border-bottom: 2px solid var(--accent-700); + user-select: none; + + &:hover { + cursor: pointer; + background-color: var(--accent-700); + border-radius: var(--radius-md); + } +} + +.settings-account-mobile-item-title { + font-size: var(--font-lg); + font-weight: var(--weight-semibold); + display: flex; + justify-content: center; + align-items: center; +} + +.settings-account-mobile-item:last-child { + border-bottom: none; +} + +.settings-account-mobile-item-description { + display: flex; + flex: 1; + justify-content: flex-end; + align-items: center; + gap: 8px; +} + +.settings-account-mobile-item-icon { + display: flex; + color: var(--accent-50); +} + +@include mobile { + .settings-account-mobile-item-icon { + width: 25px; + justify-content: center; + align-items: center; + } +} diff --git a/app/components/settings/account/menu/mobile.jsx b/app/components/settings/account/menu/mobile.jsx new file mode 100644 index 0000000..e69de29 diff --git a/app/components/settings/account/menu/mobile.scss b/app/components/settings/account/menu/mobile.scss new file mode 100644 index 0000000..e69de29 diff --git a/app/components/settings/account/style.scss b/app/components/settings/account/style.scss new file mode 100644 index 0000000..0866c0d --- /dev/null +++ b/app/components/settings/account/style.scss @@ -0,0 +1,64 @@ +@import '../../../styles/global.scss'; + +.settings-account-container { + padding: 0.75rem 1.5rem 0.75rem 1rem; + flex: 1; + display: flex; + flex-direction: column; + margin: 0 auto; + max-width: pxToRem(1050); + margin-top: pxToRem(15); +} + +.settings-account-content { + display: flex; + flex: 1; + width: 100%; + max-width: pxToRem(800); + flex-direction: column; +} + +.settings-account-profile { + flex: 1; +} + +.settings-account-item { + display: flex; + flex-direction: row; + justify-content: space-between; + margin-bottom: pxToRem(8); +} + +.settings-account-item-title { + font-weight: 600; + font-size: var(--font-md); + color: var(--accent-100); +} + +.settings-account-item-description { + font-size: var(--font-xl); +} + +.settings-account-item-button { + display: flex; + justify-content: center; + align-items: center; +} + +.settings-account-item-info { + font-size: var(--font-lg); +} + +@include mobile { + .settings-account-container { + padding: 0; + margin: 0 pxToRem(8); + } + + .settings-account-mobile-container { + flex: 1; + flex-direction: column; + background-color: var(--accent-800); + border-radius: var(--radius-md); + } +} diff --git a/app/components/settings/tab.jsx b/app/components/settings/tab.jsx deleted file mode 100644 index 5527dea..0000000 --- a/app/components/settings/tab.jsx +++ /dev/null @@ -1,42 +0,0 @@ -import './tab.scss'; - -// import dependencies -import PropTypes from 'prop-types'; - -const tabs = [ - { name: 'general', text: 'General' }, - { name: 'manage', text: 'Manage Team' }, - { name: 'about', text: 'About' }, -]; - -const SettingsTab = ({ tab, handleTabUpdate }) => { - const tabsList = tabs.map(({ name, text }) => { - const active = name === tab; - return ( -
handleTabUpdate(name)} - > - {text} -
- ); - }); - - return ( -
-
Settings
- {tabsList} -
- ); -}; - -SettingsTab.displayName = 'SettingsTab'; - -SettingsTab.propTypes = { - tab: PropTypes.string.isRequired, - handleTabUpdate: PropTypes.func.isRequired, -}; - -export default SettingsTab; From f8fd4eb5ef2802ff5d39142376b5bd4d12847d06 Mon Sep 17 00:00:00 2001 From: ksjaay Date: Sat, 1 Jun 2024 23:14:56 +0100 Subject: [PATCH 08/28] Cleans up verify, about, and manage team pages for settings --- app/components/register/verify.jsx | 1 + app/components/settings/about.jsx | 2 +- app/components/settings/manage/index.jsx | 12 ++++----- app/components/settings/manage/member/row.jsx | 26 ++++++++++++++----- .../settings/manage/member/row.scss | 15 ++++++++++- 5 files changed, 40 insertions(+), 16 deletions(-) diff --git a/app/components/register/verify.jsx b/app/components/register/verify.jsx index c081f0c..8eee8a4 100644 --- a/app/components/register/verify.jsx +++ b/app/components/register/verify.jsx @@ -19,6 +19,7 @@ const RegisterVerify = () => { return navigate('/'); } catch (error) { + console.log(error); toast.error('Something went wrong while verifying your account.'); } }; diff --git a/app/components/settings/about.jsx b/app/components/settings/about.jsx index 33125b7..e3e0307 100644 --- a/app/components/settings/about.jsx +++ b/app/components/settings/about.jsx @@ -1,7 +1,7 @@ import './about.scss'; const SetttingAbout = () => { - const version = import.meta.env.VITE_REACT_APP_VERSION || '0.3.11'; + const version = import.meta.env.VITE_REACT_APP_VERSION || '0.5.0'; return (
diff --git a/app/components/settings/manage/index.jsx b/app/components/settings/manage/index.jsx index 416bb57..005dae6 100644 --- a/app/components/settings/manage/index.jsx +++ b/app/components/settings/manage/index.jsx @@ -23,6 +23,7 @@ const ManageTeam = () => { setTeam(query.data); } catch (error) { + console.log(error); toast.error("Couldn't fetch team members"); } }; @@ -33,15 +34,12 @@ const ManageTeam = () => { return (
-
- -
+
); }; diff --git a/app/components/settings/manage/member/row.jsx b/app/components/settings/manage/member/row.jsx index 96d614b..49bf2cf 100644 --- a/app/components/settings/manage/member/row.jsx +++ b/app/components/settings/manage/member/row.jsx @@ -10,11 +10,13 @@ import MemberRowActions from './actions'; import useContextStore from '../../../../context'; import { userPropType } from '../../../../utils/propTypes'; -const positions = { - 1: 'Owner', - 2: 'Admin', - 3: 'Editor', - 4: 'Guest', +const positions = { 1: 'Owner', 2: 'Admin', 3: 'Editor', 4: 'Guest' }; + +const isImageUrl = (url) => { + if (typeof url !== 'string') { + return false; + } + return url.match(/^https?:\/\/.+\.(jpg|jpeg|png|gif)$/gim) !== null; }; const MemberTableRow = ({ member = {} }) => { @@ -38,12 +40,22 @@ const MemberTableRow = ({ member = {} }) => { const date = moment(member.createdAt).format('MMM DD, YYYY'); const time = moment(member.createdAt).format('hh:mm A'); - const avatar = member.avatar ? `/icons/${member.avatar}.png` : '/logo.svg'; + const avatarUrl = isImageUrl(member.avatar) + ? member.avatar + : `/icons/${member.avatar}.png`; + + const userAvatar = member.avatar ? ( + + ) : ( +
+ {member.displayName?.charAt(0)} +
+ ); return (
- + {userAvatar}
{member.displayName}
{member.email}
diff --git a/app/components/settings/manage/member/row.scss b/app/components/settings/manage/member/row.scss index 99e50c2..e3c815f 100644 --- a/app/components/settings/manage/member/row.scss +++ b/app/components/settings/manage/member/row.scss @@ -9,7 +9,20 @@ .member-row-image { width: pxToRem(45); height: pxToRem(45); - border-radius: 50%; + border-radius: var(--radius-pill); +} + +.member-row-image-default { + width: pxToRem(45); + height: pxToRem(45); + border-radius: var(--radius-pill); + display: flex; + align-items: center; + justify-content: center; + margin-right: pxToRem(6); + background-color: var(--primary-700); + font-size: var(--font-xl); + color: var(--font-color); } .member-row-details { From 7b525684e83ea1b6cd9b2f4205b39b0518a14d0a Mon Sep 17 00:00:00 2001 From: ksjaay Date: Sat, 1 Jun 2024 23:15:43 +0100 Subject: [PATCH 09/28] Adds components for personalisation settings --- .../settings/personalisation/accent.jsx | 56 ++++++ .../settings/personalisation/appearance.jsx | 80 +++++++++ .../settings/personalisation/dateformat.jsx | 53 ++++++ .../settings/personalisation/index.jsx | 58 +++++++ .../settings/personalisation/style.scss | 163 ++++++++++++++++++ .../settings/personalisation/theme.jsx | 78 +++++++++ .../settings/personalisation/timeformat.jsx | 59 +++++++ .../settings/personalisation/timezone.jsx | 47 +++++ 8 files changed, 594 insertions(+) create mode 100644 app/components/settings/personalisation/accent.jsx create mode 100644 app/components/settings/personalisation/appearance.jsx create mode 100644 app/components/settings/personalisation/dateformat.jsx create mode 100644 app/components/settings/personalisation/index.jsx create mode 100644 app/components/settings/personalisation/style.scss create mode 100644 app/components/settings/personalisation/theme.jsx create mode 100644 app/components/settings/personalisation/timeformat.jsx create mode 100644 app/components/settings/personalisation/timezone.jsx diff --git a/app/components/settings/personalisation/accent.jsx b/app/components/settings/personalisation/accent.jsx new file mode 100644 index 0000000..fd11535 --- /dev/null +++ b/app/components/settings/personalisation/accent.jsx @@ -0,0 +1,56 @@ +// import dependencies +import PropTypes from 'prop-types'; + +// import local files +import FaCircleCheck from '../../icons/faCircleCheck'; +import classNames from 'classnames'; + +const colors = ['Blue', 'Purple', 'Green', 'Yellow', 'Red', 'Cyan', 'Pink']; + +const SettingsPersonalisationAccent = ({ color, setColor }) => { + return ( + <> +
Accent
+
+ {colors.map((colorName) => { + const classes = classNames( + 'settings-accent-container', + `settings-accent-${colorName.toLowerCase()}`, + { + 'settings-accent-blue--active': color === 'Blue', + 'settings-accent-cyan--active': color === 'Cyan', + 'settings-accent-green--active': color === 'Green', + 'settings-accent-pink--active': color === 'Pink', + 'settings-accent-purple--active': color === 'Purple', + 'settings-accent-red--active': color === 'Red', + 'settings-accent-yellow--active': color === 'Yellow', + } + ); + + return ( +
setColor(colorName)} + > + {color === colorName && ( +
+ +
+ )} +
+ ); + })} +
+ + ); +}; + +SettingsPersonalisationAccent.displayName = 'SettingsPersonalisationAccent'; + +SettingsPersonalisationAccent.propTypes = { + color: PropTypes.string.isRequired, + setColor: PropTypes.func.isRequired, +}; + +export default SettingsPersonalisationAccent; diff --git a/app/components/settings/personalisation/appearance.jsx b/app/components/settings/personalisation/appearance.jsx new file mode 100644 index 0000000..c13f89b --- /dev/null +++ b/app/components/settings/personalisation/appearance.jsx @@ -0,0 +1,80 @@ +// import dependencies +import PropTypes from 'prop-types'; +import { observer } from 'mobx-react-lite'; +import dayjs from 'dayjs'; + +// import local files +import Button from '../../ui/button'; +import TextInput from '../../ui/input'; +import useContextStore from '../../../context'; + +const SettingsPersonalisationAppearance = ({ + dateformat, + timeformat, + theme, +}) => { + const { + userStore: { + user: { displayName }, + }, + } = useContextStore(); + + const message = + theme === 'dark' + ? 'Woow this looks so nice to my eyes' + : theme === 'light' + ? 'Why is it so bright, I can barely look at this' + : 'I have no clue, might be dark, might be light'; + + return ( + <> +
Appearance
+
+
+
+
+ {displayName?.charAt(0)?.toUpperCase()} +
+ +
+
+
+ {displayName} +
+
+ {dayjs(Date.now()).format(`${dateformat} ${timeformat}`)} +
+
+
Configure the appearance using the controls below
+
{message}
+
+
+
+ +
+
+ +
+ + +
+
+ + ); +}; + +SettingsPersonalisationAppearance.displayName = + 'SettingsPersonalisationAppearance'; + +SettingsPersonalisationAppearance.propTypes = { + dateformat: PropTypes.string, + timeformat: PropTypes.string, + theme: PropTypes.string, +}; + +export default observer(SettingsPersonalisationAppearance); diff --git a/app/components/settings/personalisation/dateformat.jsx b/app/components/settings/personalisation/dateformat.jsx new file mode 100644 index 0000000..ef63138 --- /dev/null +++ b/app/components/settings/personalisation/dateformat.jsx @@ -0,0 +1,53 @@ +// import dependencies +import PropTypes from 'prop-types'; + +// import local files +import Button from '../../ui/button'; +import Dropdown from '../../ui/dropdown'; +import useDropdown from '../../../hooks/useDropdown'; +import timeformats from '../../../constant/dateformats.json'; + +const SettingsPersonalisationDateformat = ({ dateformat, setDateformat }) => { + const { dropdownIsOpen, toggleDropdown } = useDropdown(); + + return ( +
+
Date Format
+ + + + + + {timeformats.map((format) => ( + setDateformat(format)} + showDot + isSelected={dateformat === format} + > + {format} + + ))} + + +
+ ); +}; + +SettingsPersonalisationDateformat.displayName = + 'SettingsPersonalisationDateformat'; + +SettingsPersonalisationDateformat.propTypes = { + dateformat: PropTypes.string.isRequired, + setDateformat: PropTypes.func.isRequired, +}; + +export default SettingsPersonalisationDateformat; diff --git a/app/components/settings/personalisation/index.jsx b/app/components/settings/personalisation/index.jsx new file mode 100644 index 0000000..fdff36c --- /dev/null +++ b/app/components/settings/personalisation/index.jsx @@ -0,0 +1,58 @@ +import './style.scss'; + +// import local files +import useLocalStorageContext from '../../../hooks/useLocalstorage'; +import SettingsPersonalisationAppearance from './appearance'; +import SettingsPersonalisationTheme from './theme'; +import SettingsPersonalisationAccent from './accent'; +import SettingsPersonalisationTimeformat from './timeformat'; +import SettingsPersonalisationDateformat from './dateformat'; +import SettingsPersonalisationTimezone from './timezone'; + +const SettingsPersonalisation = () => { + const { + timezone, + dateformat, + timeformat, + theme, + color, + setTimezone, + setDateformat, + setTimeformat, + setTheme, + setColor, + } = useLocalStorageContext(); + + return ( +
+
+ + + + +
+ + + +
+ + +
+
+ ); +}; + +export default SettingsPersonalisation; diff --git a/app/components/settings/personalisation/style.scss b/app/components/settings/personalisation/style.scss new file mode 100644 index 0000000..efb00cd --- /dev/null +++ b/app/components/settings/personalisation/style.scss @@ -0,0 +1,163 @@ +.settings-subtitle { + margin-top: 25px; + font-size: 20px; + font-weight: 700; + margin-bottom: 10px; +} + +.settings-appearance-container { + display: flex; + flex-direction: column; + background-color: var(--accent-900); + padding: 10px; + border-radius: 16px; +} + +.settings-appearance-icon { + width: 35px; + height: 35px; + display: flex; + justify-content: center; + align-items: center; + border-radius: 50%; + background-color: var(--primary-700); + color: var(--font-color); + font-size: 18px; + font-weight: 700; +} + +.settings-appearance-info { + margin-bottom: 10px; +} + +.settings-appearance-displayname { + display: flex; + align-items: center; + gap: 5px; +} + +.settings-appearance-name { + font-weight: 700; + font-size: 18px; + margin-right: 3px; + + &:hover { + cursor: pointer; + color: var(--primary-500); + } +} + +.settings-appearance-time { + color: var(--accent-200); + font-size: 14px; +} + +.settings-appearance-content { + display: flex; + justify-content: space-between; + align-items: center; +} + +.settings-theme { + width: 4rem; + height: 4rem; + border-radius: 100%; + border: 2px solid var(--accent-300); + position: relative; + + &.settings-theme-light { + background-color: white; + } + + &.settings-theme-dark { + background-color: var(--gray-700); + } + + &.settings-theme--active { + border: 2px solid var(--primary-600); + } + + &:hover { + cursor: pointer; + } +} + +.settings-theme-icon { + position: absolute; + top: -3px; + right: -3px; + color: var(--primary-700); +} + +.settings-accent-container { + width: 3.5rem; + height: 3.5rem; + border-radius: 100%; + border: 2px solid var(--primary-700); + background: var(--primary-800); + cursor: pointer; + position: relative; + + &.settings-accent-blue { + border: 2px solid var(--blue-700); + background-color: var(--blue-800); + + &.settings-accent-blue--active { + border: 2px solid var(--blue-600); + } + } + + &.settings-accent-cyan { + border: 2px solid var(--cyan-700); + background-color: var(--cyan-800); + + &.settings-accent-cyan--active { + border: 2px solid var(--cyan-600); + } + } + + &.settings-accent-green { + border: 2px solid var(--green-700); + background-color: var(--green-800); + + &.settings-accent-green--active { + border: 2px solid var(--green-600); + } + } + + &.settings-accent-pink { + border: 2px solid var(--pink-700); + background-color: var(--pink-800); + + &.settings-accent-pink--active { + border: 2px solid var(--pink-600); + } + } + + &.settings-accent-purple { + border: 2px solid var(--purple-700); + background-color: var(--purple-800); + + &.settings-accent-purple--active { + border: 2px solid var(--purple-600); + } + } + + &.settings-accent-red { + border: 2px solid var(--red-700); + background-color: var(--red-800); + + &.settings-accent-red--active { + border: 2px solid var(--red-600); + } + } + + &.settings-accent-yellow { + border: 2px solid var(--yellow-700); + background-color: var(--yellow-800); + + &.settings-accent-yellow--active { + border: 2px solid var(--yellow-600); + } + } +} diff --git a/app/components/settings/personalisation/theme.jsx b/app/components/settings/personalisation/theme.jsx new file mode 100644 index 0000000..7863c43 --- /dev/null +++ b/app/components/settings/personalisation/theme.jsx @@ -0,0 +1,78 @@ +// import dependencies +import PropTypes from 'prop-types'; + +// import local files +import FaCircleCheck from '../../icons/faCircleCheck'; +import Tooltip from '../../ui/tooltip'; +import { LiaSyncSolid } from '../../icons'; + +const SettingsPersonalisationTheme = ({ theme, setTheme }) => { + return ( + <> +
Theme
+ +
+ +
setTheme('light')} + > + {theme === 'light' && ( +
+ +
+ )} +
+
+ +
setTheme('dark')} + > + {theme === 'dark' && ( +
+ +
+ )} +
+
+ +
setTheme('system')} + > + {theme === 'system' && ( +
+ +
+ )} +
+ +
+
+
+
+ + ); +}; + +SettingsPersonalisationTheme.displayName = 'SettingsPersonalisationTheme'; + +SettingsPersonalisationTheme.propTypes = { + theme: PropTypes.string.isRequired, + setTheme: PropTypes.func.isRequired, +}; + +export default SettingsPersonalisationTheme; diff --git a/app/components/settings/personalisation/timeformat.jsx b/app/components/settings/personalisation/timeformat.jsx new file mode 100644 index 0000000..aa15fd6 --- /dev/null +++ b/app/components/settings/personalisation/timeformat.jsx @@ -0,0 +1,59 @@ +// import dependencies +import PropTypes from 'prop-types'; + +// import local files +import Button from '../../ui/button'; +import Dropdown from '../../ui/dropdown'; +import useDropdown from '../../../hooks/useDropdown'; + +const times = { + 'HH:mm:ss': '23:59:59', + 'HH:mm': '23:59', + 'hh:mm': '11:59', + 'hh:mm A': '11:59 PM', +}; + +const SettingsPersonalisationTimeformat = ({ timeformat, setTimeformat }) => { + const { dropdownIsOpen, toggleDropdown } = useDropdown(); + + return ( +
+
Time Format
+ + + + + + {Object.keys(times).map((time) => ( + setTimeformat(time)} + showDot + isSelected={time === timeformat} + > + {times[time]} + + ))} + + +
+ ); +}; + +SettingsPersonalisationTimeformat.displayName = + 'SettingsPersonalisationTimeformat'; + +SettingsPersonalisationTimeformat.propTypes = { + timeformat: PropTypes.string.isRequired, + setTimeformat: PropTypes.func.isRequired, +}; + +export default SettingsPersonalisationTimeformat; diff --git a/app/components/settings/personalisation/timezone.jsx b/app/components/settings/personalisation/timezone.jsx new file mode 100644 index 0000000..337c1c8 --- /dev/null +++ b/app/components/settings/personalisation/timezone.jsx @@ -0,0 +1,47 @@ +// import dependencies +import PropTypes from 'prop-types'; + +// import local files +import Button from '../../ui/button'; +import Dropdown from '../../ui/dropdown'; +import timezonesList from '../../../constant/timezones.json'; +import useDropdown from '../../../hooks/useDropdown'; + +const SettingsPersonalisationTimezone = ({ timezone, setTimezone }) => { + const { dropdownIsOpen, toggleDropdown } = useDropdown(); + + return ( +
+
Timezone
+ + + + + + {Object.keys(timezonesList).map((timezone) => ( + setTimezone(timezone)}> + {timezonesList[timezone]} + + ))} + + +
+ ); +}; + +SettingsPersonalisationTimezone.displayName = 'SettingsPersonalisationTimezone'; + +SettingsPersonalisationTimezone.propTypes = { + timezone: PropTypes.string.isRequired, + setTimezone: PropTypes.func.isRequired, +}; + +export default SettingsPersonalisationTimezone; From e482e839fe4ce5bb3f1ede4513f0651b2fa65302 Mon Sep 17 00:00:00 2001 From: ksjaay Date: Sat, 1 Jun 2024 23:17:02 +0100 Subject: [PATCH 10/28] Adds ui components for desktop and mobile menus/tabs --- app/components/settings/ui/menu/desktop.jsx | 35 ++++++++++ app/components/settings/ui/menu/mobile.jsx | 60 +++++++++++++++++ app/components/settings/ui/tab/desktop.jsx | 43 ++++++++++++ app/components/settings/ui/tab/mobile.jsx | 59 +++++++++++++++++ app/components/settings/ui/tab/tab.scss | 73 +++++++++++++++++++++ 5 files changed, 270 insertions(+) create mode 100644 app/components/settings/ui/menu/desktop.jsx create mode 100644 app/components/settings/ui/menu/mobile.jsx create mode 100644 app/components/settings/ui/tab/desktop.jsx create mode 100644 app/components/settings/ui/tab/mobile.jsx create mode 100644 app/components/settings/ui/tab/tab.scss diff --git a/app/components/settings/ui/menu/desktop.jsx b/app/components/settings/ui/menu/desktop.jsx new file mode 100644 index 0000000..da1102a --- /dev/null +++ b/app/components/settings/ui/menu/desktop.jsx @@ -0,0 +1,35 @@ +// import dependencies +import PropTypes from 'prop-types'; + +// import local files +import SettingsTab from '../tab/desktop'; +import SettingsAccount from '../../account'; +import SettingsPersonalisation from '../../personalisation'; +import ManageTeam from '../../manage'; +import SettingsAbout from '../../about'; +import { FaClose } from '../../../icons'; + +const SettingsDesktop = ({ tab, handleTabUpdate, handleKeydown }) => { + return ( + <> +
handleKeydown(null, true)}> + +
+ + {tab === 'Account' && } + {tab === 'Appearance' && } + {tab === 'Manage Team' && } + {tab === 'About' && } + + ); +}; + +SettingsDesktop.displayName = 'SettingsDesktop'; + +SettingsDesktop.propTypes = { + tab: PropTypes.string.isRequired, + handleTabUpdate: PropTypes.func.isRequired, + handleKeydown: PropTypes.func.isRequired, +}; + +export default SettingsDesktop; diff --git a/app/components/settings/ui/menu/mobile.jsx b/app/components/settings/ui/menu/mobile.jsx new file mode 100644 index 0000000..732d5e8 --- /dev/null +++ b/app/components/settings/ui/menu/mobile.jsx @@ -0,0 +1,60 @@ +// import dependencies +import PropTypes from 'prop-types'; +import { useState } from 'react'; + +// import local files +import IoArrowBack from '../../../icons/ioArrowBack'; +import SettingsMobileTabs from '../tab/mobile'; +import SettingsAccount from '../../account'; +import SettingsPersonalisation from '../../personalisation'; +import ManageTeam from '../../manage'; +import SettingsAbout from '../../about'; + +const SettingsMobile = ({ handleKeydown }) => { + const [page, setPage] = useState('homepage'); + const handleTabChange = (page) => setPage(page); + + return ( +
+
+
{ + if (page === 'homepage') { + return handleKeydown(null, true); + } + + setPage('homepage'); + }} + > + +
+
+ Settings +
+
+ + {page === 'homepage' && ( + + )} + {page === 'Account' && } + {page === 'Appearance' && } + {page === 'Manage Team' && } + {page === 'About' && } +
+ ); +}; + +SettingsMobile.displayName = 'SettingsMobile'; + +SettingsMobile.propTypes = { + handleKeydown: PropTypes.func.isRequired, +}; + +export default SettingsMobile; diff --git a/app/components/settings/ui/tab/desktop.jsx b/app/components/settings/ui/tab/desktop.jsx new file mode 100644 index 0000000..e349932 --- /dev/null +++ b/app/components/settings/ui/tab/desktop.jsx @@ -0,0 +1,43 @@ +// import dependencies +import PropTypes from 'prop-types'; + +const tabs = [ + { title: 'GENERAL', items: ['Account', 'Appearance'] }, + { title: 'WORKSPACE', items: ['Manage Team', 'About'] }, +]; + +const SettingsTab = ({ tab, handleTabUpdate }, index) => { + const tabsList = tabs.map(({ title, items }) => { + const itemsList = items.map((name) => { + const active = name === tab; + return ( +
handleTabUpdate(name)} + id={name.replace(' ', '-')} + > + {name} +
+ ); + }); + + return ( +
+ {title &&
{title}
} +
{itemsList}
+
+ ); + }); + + return
{tabsList}
; +}; + +SettingsTab.displayName = 'SettingsTab'; + +SettingsTab.propTypes = { + tab: PropTypes.string.isRequired, + handleTabUpdate: PropTypes.func.isRequired, +}; + +export default SettingsTab; diff --git a/app/components/settings/ui/tab/mobile.jsx b/app/components/settings/ui/tab/mobile.jsx new file mode 100644 index 0000000..4a21215 --- /dev/null +++ b/app/components/settings/ui/tab/mobile.jsx @@ -0,0 +1,59 @@ +// import dependencies +import PropTypes from 'prop-types'; +import { + FaChevronRight, + FaUserCircle, + IoColorPalette, + MdHelpCircle, +} from '../../../icons'; +import FaUsers from '../../../icons/faUsers'; + +const tabs = [ + { + title: 'General Settings', + items: [ + { name: 'Account', icon: }, + { name: 'Appearance', icon: }, + ], + }, + { + title: 'Workspace Settings', + items: [ + { name: 'Manage Team', icon: }, + { name: 'About', icon: }, + ], + }, +]; + +const SettingsMobileTabs = ({ handleTabChange }) => { + const tabsList = tabs.map(({ title, items }) => { + const itemsList = items.map((item) => { + return ( +
handleTabChange(item.name)} + > + {item.icon} +
{item.name}
+ +
+ ); + }); + + return ( +
+ {title &&
{title}
} +
{itemsList}
+
+ ); + }); + + return
{tabsList}
; +}; + +SettingsMobileTabs.displayName = 'SettingsMobileTabs'; + +SettingsMobileTabs.propTypes = { handleTabChange: PropTypes.func.isRequired }; + +export default SettingsMobileTabs; diff --git a/app/components/settings/ui/tab/tab.scss b/app/components/settings/ui/tab/tab.scss new file mode 100644 index 0000000..72e6e21 --- /dev/null +++ b/app/components/settings/ui/tab/tab.scss @@ -0,0 +1,73 @@ +@import '../../../../styles/global.scss'; + +.settings-tab { + display: flex; + flex-direction: column; + width: 250px; + background-color: var(--accent-900); + padding: pxToRem(4); + border-right: 3px solid var(--accent-700); +} + +.settings-tab-title { + padding: pxToRem(12) 0 0 pxToRem(20); + color: var(--accent-200); + font-size: var(--font-sm); +} + +.settings-tab-text { + color: var(--accent-100); + font-size: var(--font-xl); + font-weight: 500; + cursor: pointer; + transition: background-color 0.2s ease-in-out; + margin: pxToRem(4); + padding: pxToRem(8) pxToRem(16); + border-radius: pxToRem(12); + + &:hover { + background-color: var(--accent-900); + } + + &.active { + background-color: var(--accent-900); + color: var(--primary-500); + } +} + +.settings-mobile-tab-text { + display: flex; + justify-content: space-between; + align-items: center; + cursor: pointer; + color: var(--font-color); + padding: 10px 0; + border-bottom: 2px solid var(--accent-800); + gap: 10px; + + &:last-child { + border-bottom: none; + } +} + +.settings-mobile-tab-title { + padding: 3px 8px; + color: var(--accent-200); + font-weight: var(--weight-semibold); +} + +.settings-mobile-tab-items { + display: flex; + flex-direction: column; + flex: 1; + margin: 8px; + padding: 10px; + background-color: var(--accent-900); + border-radius: var(--radius-md); +} + +.settings-mobile-tabs { + display: flex; + flex-direction: column; + flex: 1; +} From c778fe8ee224d5f2187aecc724598432b158df99 Mon Sep 17 00:00:00 2001 From: ksjaay Date: Sat, 1 Jun 2024 23:17:32 +0100 Subject: [PATCH 11/28] Adds outlines to buttons --- app/components/ui/button.jsx | 9 +++- app/components/ui/button.scss | 81 +++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/app/components/ui/button.jsx b/app/components/ui/button.jsx index d466751..5089927 100644 --- a/app/components/ui/button.jsx +++ b/app/components/ui/button.jsx @@ -12,17 +12,20 @@ const Button = ({ iconLeft, iconRight, color, + outline, fullWidth, + tabIndex = 0, as: Wrapper = 'div', ...props }) => { const classes = classNames('button', { - [`button--${color}`]: color, + [`button--${color}`]: !outline && color, + [`button--${outline}-outline`]: !color && outline, 'button-fixed-width': !fullWidth, }); return ( - + {iconLeft} {children &&
{children}
} {iconRight} @@ -37,7 +40,9 @@ Button.propTypes = { iconLeft: PropTypes.node, iconRight: PropTypes.node, color: colorPropType, + outline: colorPropType, fullWidth: PropTypes.bool, + tabIndex: PropTypes.number, as: PropTypes.elementType, }; diff --git a/app/components/ui/button.scss b/app/components/ui/button.scss index c411f56..0138247 100644 --- a/app/components/ui/button.scss +++ b/app/components/ui/button.scss @@ -11,6 +11,7 @@ border: 2px solid var(--gray-600); gap: 10px; transition: all 0.25s ease-in-out; + width: 100%; } .button-fixed-width { @@ -117,3 +118,83 @@ border-color: var(--yellow-600); } } + +.button--blue-outline { + border-color: var(--blue-700); + + &:hover { + background-color: var(--blue-600); + border-color: var(--blue-600); + } +} + +.button--cyan-outline { + border-color: var(--cyan-700); + + &:hover { + background-color: var(--cyan-600); + border-color: var(--cyan-600); + } +} + +.button--gray-outline { + border-color: var(--gray-700); + + &:hover { + background-color: var(--gray-600); + border-color: var(--gray-600); + } +} + +.button--green-outline { + border-color: var(--green-700); + + &:hover { + background-color: var(--green-600); + border-color: var(--green-600); + } +} +.button--pink-outline { + border-color: var(--pink-700); + + &:hover { + background-color: var(--pink-600); + border-color: var(--pink-600); + } +} + +.button--primary-outline { + border-color: var(--primary-700); + + &:hover { + background-color: var(--primary-600); + border-color: var(--primary-600); + } +} + +.button--purple-outline { + border-color: var(--purple-700); + + &:hover { + background-color: var(--purple-600); + border-color: var(--purple-600); + } +} + +.button--red-outline { + border-color: var(--red-700); + + &:hover { + background-color: var(--red-600); + border-color: var(--red-600); + } +} + +.button--yellow-outline { + border-color: var(--yellow-700); + + &:hover { + background-color: var(--yellow-600); + border-color: var(--yellow-600); + } +} From 21d9dbb90d0a99d6fd8eedb381ac4927275a22be Mon Sep 17 00:00:00 2001 From: ksjaay Date: Sat, 1 Jun 2024 23:18:06 +0100 Subject: [PATCH 12/28] Adds left and right icons to text input --- app/components/ui/input.jsx | 30 ++++++++++++++++++++++++++++-- app/components/ui/input.scss | 28 ++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/app/components/ui/input.jsx b/app/components/ui/input.jsx index fed35f6..4ecfac6 100644 --- a/app/components/ui/input.jsx +++ b/app/components/ui/input.jsx @@ -1,10 +1,23 @@ // import styles +import classNames from 'classnames'; import './input.scss'; // import dependencies import PropTypes from 'prop-types'; -const TextInput = ({ label, id, error, ...props }) => { +const TextInput = ({ + label, + id, + error, + iconLeft, + iconRight, + tabIndex = 0, + ...props +}) => { + const classes = classNames('text-input', { + 'text-input-icon-left': iconLeft, + 'text-input-icon-right': iconRight, + }); return ( <> {label && ( @@ -12,7 +25,17 @@ const TextInput = ({ label, id, error, ...props }) => { {label} )} - +
+ {iconLeft &&
{iconLeft}
} + + {iconRight &&
{iconRight}
} +
{error && (