fix: custom theme persisting after signing out (#1780)

* fix: custom theme persistence

* chore: remove console logs

* fix: build error

* fix: change theme from command k
This commit is contained in:
Aaryan Khandelwal 2023-08-03 15:01:31 +05:30 committed by GitHub
parent 5aad6c71da
commit 97c3fb40e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 287 additions and 307 deletions

View File

@ -5,6 +5,8 @@ import { Command } from "cmdk";
import { THEMES_OBJ } from "constants/themes";
import { useTheme } from "next-themes";
import { SettingIcon } from "components/icons";
import userService from "services/user.service";
import useUser from "hooks/use-user";
type Props = {
setIsPaletteOpen: Dispatch<SetStateAction<boolean>>;
@ -12,24 +14,50 @@ type Props = {
export const ChangeInterfaceTheme: React.FC<Props> = ({ setIsPaletteOpen }) => {
const [mounted, setMounted] = useState(false);
const { setTheme } = useTheme();
const { user, mutateUser } = useUser();
const updateUserTheme = (newTheme: string) => {
if (!user) return;
setTheme(newTheme);
mutateUser((prevData) => {
if (!prevData) return prevData;
return {
...prevData,
theme: {
...prevData.theme,
theme: newTheme,
},
};
}, false);
userService.updateUser({
theme: {
...user.theme,
theme: newTheme,
},
});
};
// useEffect only runs on the client, so now we can safely show the UI
useEffect(() => {
setMounted(true);
}, []);
if (!mounted) {
return null;
}
if (!mounted) return null;
return (
<>
{THEMES_OBJ.map((theme) => (
{THEMES_OBJ.filter((t) => t.value !== "custom").map((theme) => (
<Command.Item
key={theme.value}
onSelect={() => {
setTheme(theme.value);
updateUserTheme(theme.value);
setIsPaletteOpen(false);
}}
className="focus:outline-none"

View File

@ -28,6 +28,7 @@ const defaultValues: ICustomTheme = {
sidebarText: "#c5c5c5",
darkPalette: false,
palette: "",
theme: "custom",
};
export const CustomThemeSelector: React.FC<Props> = ({ preLoadedData }) => {
@ -56,6 +57,7 @@ export const CustomThemeSelector: React.FC<Props> = ({ preLoadedData }) => {
sidebarText: formData.sidebarText,
darkPalette: darkPalette,
palette: `${formData.background},${formData.text},${formData.primary},${formData.sidebarBackground},${formData.sidebarText}`,
theme: "custom",
};
await userService

View File

@ -1,142 +1,161 @@
import { useState, useEffect, Dispatch, SetStateAction } from "react";
import { useState, useEffect } from "react";
// next-themes
import { useTheme } from "next-themes";
// services
import userService from "services/user.service";
// hooks
import useUser from "hooks/use-user";
// constants
import { THEMES_OBJ } from "constants/themes";
// ui
import { CustomSelect } from "components/ui";
// types
import { ICustomTheme, IUser } from "types";
import { ICustomTheme } from "types";
import { unsetCustomCssVariables } from "helpers/theme.helper";
type Props = {
user: IUser | undefined;
setPreLoadedData: Dispatch<SetStateAction<ICustomTheme | null>>;
setPreLoadedData: React.Dispatch<React.SetStateAction<ICustomTheme | null>>;
customThemeSelectorOptions: boolean;
setCustomThemeSelectorOptions: Dispatch<SetStateAction<boolean>>;
setCustomThemeSelectorOptions: React.Dispatch<React.SetStateAction<boolean>>;
};
export const ThemeSwitch: React.FC<Props> = ({
user,
setPreLoadedData,
customThemeSelectorOptions,
setCustomThemeSelectorOptions,
}) => {
const [mounted, setMounted] = useState(false);
const { theme, setTheme } = useTheme();
const { user, mutateUser } = useUser();
const updateUserTheme = (newTheme: string) => {
if (!user) return;
setTheme(newTheme);
mutateUser((prevData) => {
if (!prevData) return prevData;
return {
...prevData,
theme: {
...prevData.theme,
theme: newTheme,
},
};
}, false);
userService.updateUser({
theme: {
...user.theme,
theme: newTheme,
},
});
};
// useEffect only runs on the client, so now we can safely show the UI
useEffect(() => {
setMounted(true);
}, []);
if (!mounted) {
return null;
}
if (!mounted) return null;
const currentThemeObj = THEMES_OBJ.find((t) => t.value === theme);
return (
<>
<CustomSelect
value={theme}
label={
currentThemeObj ? (
<div className="flex items-center gap-2">
<CustomSelect
value={theme}
label={
currentThemeObj ? (
<div className="flex items-center gap-2">
<div
className="border-1 relative flex h-4 w-4 rotate-45 transform items-center justify-center rounded-full border"
style={{
borderColor: currentThemeObj.icon.border,
}}
>
<div
className="border-1 relative flex h-4 w-4 rotate-45 transform items-center justify-center rounded-full border"
className="h-full w-1/2 rounded-l-full"
style={{
borderColor: currentThemeObj.icon.border,
background: currentThemeObj.icon.color1,
}}
>
<div
className="h-full w-1/2 rounded-l-full"
style={{
background: currentThemeObj.icon.color1,
}}
/>
<div
className="h-full w-1/2 rounded-r-full border-l"
style={{
borderLeftColor: currentThemeObj.icon.border,
background: currentThemeObj.icon.color2,
}}
/>
</div>
{currentThemeObj.label}
/>
<div
className="h-full w-1/2 rounded-r-full border-l"
style={{
borderLeftColor: currentThemeObj.icon.border,
background: currentThemeObj.icon.color2,
}}
/>
</div>
) : (
"Select your theme"
)
}
onChange={({ value, type }: { value: string; type: string }) => {
if (value === "custom") {
if (user?.theme.palette) {
setPreLoadedData({
background: user.theme.background !== "" ? user.theme.background : "#0d101b",
text: user.theme.text !== "" ? user.theme.text : "#c5c5c5",
primary: user.theme.primary !== "" ? user.theme.primary : "#3f76ff",
sidebarBackground:
user.theme.sidebarBackground !== "" ? user.theme.sidebarBackground : "#0d101b",
sidebarText: user.theme.sidebarText !== "" ? user.theme.sidebarText : "#c5c5c5",
darkPalette: false,
palette:
user.theme.palette !== ",,,,"
? user.theme.palette
: "#0d101b,#c5c5c5,#3f76ff,#0d101b,#c5c5c5",
});
}
if (!customThemeSelectorOptions) setCustomThemeSelectorOptions(true);
} else {
if (customThemeSelectorOptions) setCustomThemeSelectorOptions(false);
for (let i = 10; i <= 900; i >= 100 ? (i += 100) : (i += 10)) {
document.documentElement.style.removeProperty(`--color-background-${i}`);
document.documentElement.style.removeProperty(`--color-text-${i}`);
document.documentElement.style.removeProperty(`--color-border-${i}`);
document.documentElement.style.removeProperty(`--color-primary-${i}`);
document.documentElement.style.removeProperty(`--color-sidebar-background-${i}`);
document.documentElement.style.removeProperty(`--color-sidebar-text-${i}`);
document.documentElement.style.removeProperty(`--color-sidebar-border-${i}`);
}
{currentThemeObj.label}
</div>
) : (
"Select your theme"
)
}
onChange={({ value, type }: { value: string; type: string }) => {
if (value === "custom") {
if (user?.theme.palette) {
setPreLoadedData({
background: user.theme.background !== "" ? user.theme.background : "#0d101b",
text: user.theme.text !== "" ? user.theme.text : "#c5c5c5",
primary: user.theme.primary !== "" ? user.theme.primary : "#3f76ff",
sidebarBackground:
user.theme.sidebarBackground !== "" ? user.theme.sidebarBackground : "#0d101b",
sidebarText: user.theme.sidebarText !== "" ? user.theme.sidebarText : "#c5c5c5",
darkPalette: false,
palette:
user.theme.palette !== ",,,,"
? user.theme.palette
: "#0d101b,#c5c5c5,#3f76ff,#0d101b,#c5c5c5",
theme: "custom",
});
}
setTheme(value);
document.documentElement.style.setProperty("color-scheme", type);
}}
input
width="w-full"
position="right"
>
{THEMES_OBJ.map(({ value, label, type, icon }) => (
<CustomSelect.Option key={value} value={{ value, type }}>
<div className="flex items-center gap-2">
if (!customThemeSelectorOptions) setCustomThemeSelectorOptions(true);
} else {
if (customThemeSelectorOptions) setCustomThemeSelectorOptions(false);
unsetCustomCssVariables();
}
updateUserTheme(value);
document.documentElement.style.setProperty("--color-scheme", type);
}}
input
width="w-full"
position="right"
>
{THEMES_OBJ.map(({ value, label, type, icon }) => (
<CustomSelect.Option key={value} value={{ value, type }}>
<div className="flex items-center gap-2">
<div
className="border-1 relative flex h-4 w-4 rotate-45 transform items-center justify-center rounded-full border"
style={{
borderColor: icon.border,
}}
>
<div
className="border-1 relative flex h-4 w-4 rotate-45 transform items-center justify-center rounded-full border"
className="h-full w-1/2 rounded-l-full"
style={{
borderColor: icon.border,
background: icon.color1,
}}
>
<div
className="h-full w-1/2 rounded-l-full"
style={{
background: icon.color1,
}}
/>
<div
className="h-full w-1/2 rounded-r-full border-l"
style={{
borderLeftColor: icon.border,
background: icon.color2,
}}
/>
</div>
{label}
/>
<div
className="h-full w-1/2 rounded-r-full border-l"
style={{
borderLeftColor: icon.border,
background: icon.color2,
}}
/>
</div>
</CustomSelect.Option>
))}
</CustomSelect>
</>
{label}
</div>
</CustomSelect.Option>
))}
</CustomSelect>
);
};

View File

@ -3,10 +3,10 @@ import { Fragment } from "react";
import { useRouter } from "next/router";
import Link from "next/link";
// next-themes
import { useTheme } from "next-themes";
// headless ui
import { Menu, Transition } from "@headlessui/react";
// next-themes
import { useTheme } from "next-themes";
// hooks
import useUser from "hooks/use-user";
import useThemeHook from "hooks/use-theme";
@ -91,7 +91,7 @@ export const WorkspaceSidebarDropdown = () => {
.then(() => {
mutateUser(undefined);
router.push("/");
setTheme("dark");
setTheme("system");
})
.catch(() =>
setToastAlert({

View File

@ -1,6 +1,16 @@
export const THEMES = ["light", "dark", "light-contrast", "dark-contrast", "custom"];
export const THEMES_OBJ = [
{
value: "system",
label: "System Preference",
type: "light",
icon: {
border: "#DEE2E6",
color1: "#FAFAFA",
color2: "#3F76FF",
},
},
{
value: "light",
label: "Light",

View File

@ -11,7 +11,7 @@ import projectService from "services/project.service";
// fetch-keys
import { USER_PROJECT_VIEW } from "constants/fetch-keys";
// helper
import { applyTheme } from "helpers/theme.helper";
import { applyTheme, unsetCustomCssVariables } from "helpers/theme.helper";
// constants
export const themeContext = createContext<ContextType>({} as ContextType);
@ -92,15 +92,18 @@ export const ThemeContextProvider: React.FC<{ children: React.ReactNode }> = ({
useEffect(() => {
const theme = localStorage.getItem("theme");
if (theme && theme === "custom") {
if (user && user.theme.palette) {
applyTheme(
user.theme.palette !== ",,,,"
? user.theme.palette
: "#0d101b,#c5c5c5,#3f76ff,#0d101b,#c5c5c5",
user.theme.darkPalette
);
}
if (theme) {
if (theme === "custom") {
if (user && user.theme.palette) {
applyTheme(
user.theme.palette !== ",,,,"
? user.theme.palette
: "#0d101b,#c5c5c5,#3f76ff,#0d101b,#c5c5c5",
user.theme.darkPalette
);
}
} else unsetCustomCssVariables();
}
}, [user]);

View File

@ -60,6 +60,7 @@ const calculateShades = (hexValue: string): TShades => {
};
export const applyTheme = (palette: string, isDarkPalette: boolean) => {
const dom = document?.querySelector<HTMLElement>("[data-theme='custom']");
// palette: [bg, text, primary, sidebarBg, sidebarText]
const values: string[] = palette.split(",");
values.push(isDarkPalette ? "dark" : "light");
@ -79,41 +80,40 @@ export const applyTheme = (palette: string, isDarkPalette: boolean) => {
const sidebarBackgroundRgbValues = `${sidebarBackgroundShades[shade].r}, ${sidebarBackgroundShades[shade].g}, ${sidebarBackgroundShades[shade].b}`;
const sidebarTextRgbValues = `${sidebarTextShades[shade].r}, ${sidebarTextShades[shade].g}, ${sidebarTextShades[shade].b}`;
document
.querySelector<HTMLElement>("[data-theme='custom']")
?.style.setProperty(`--color-background-${shade}`, bgRgbValues);
document
.querySelector<HTMLElement>("[data-theme='custom']")
?.style.setProperty(`--color-text-${shade}`, textRgbValues);
document
.querySelector<HTMLElement>("[data-theme='custom']")
?.style.setProperty(`--color-primary-${shade}`, primaryRgbValues);
document
.querySelector<HTMLElement>("[data-theme='custom']")
?.style.setProperty(`--color-sidebar-background-${shade}`, sidebarBackgroundRgbValues);
document
.querySelector<HTMLElement>("[data-theme='custom']")
?.style.setProperty(`--color-sidebar-text-${shade}`, sidebarTextRgbValues);
dom?.style.setProperty(`--color-background-${shade}`, bgRgbValues);
dom?.style.setProperty(`--color-text-${shade}`, textRgbValues);
dom?.style.setProperty(`--color-primary-${shade}`, primaryRgbValues);
dom?.style.setProperty(`--color-sidebar-background-${shade}`, sidebarBackgroundRgbValues);
dom?.style.setProperty(`--color-sidebar-text-${shade}`, sidebarTextRgbValues);
if (i >= 100 && i <= 400) {
const borderShade = i === 100 ? 70 : i === 200 ? 80 : i === 300 ? 90 : 100;
document
.querySelector<HTMLElement>("[data-theme='custom']")
?.style.setProperty(
`--color-border-${shade}`,
`${bgShades[borderShade].r}, ${bgShades[borderShade].g}, ${bgShades[borderShade].b}`
);
document
.querySelector<HTMLElement>("[data-theme='custom']")
?.style.setProperty(
`--color-sidebar-border-${shade}`,
`${sidebarBackgroundShades[borderShade].r}, ${sidebarBackgroundShades[borderShade].g}, ${sidebarBackgroundShades[borderShade].b}`
);
dom?.style.setProperty(
`--color-border-${shade}`,
`${bgShades[borderShade].r}, ${bgShades[borderShade].g}, ${bgShades[borderShade].b}`
);
dom?.style.setProperty(
`--color-sidebar-border-${shade}`,
`${sidebarBackgroundShades[borderShade].r}, ${sidebarBackgroundShades[borderShade].g}, ${sidebarBackgroundShades[borderShade].b}`
);
}
}
document
.querySelector<HTMLElement>("[data-theme='custom']")
?.style.setProperty("--color-scheme", values[5]);
dom?.style.setProperty("--color-scheme", values[5]);
};
export const unsetCustomCssVariables = () => {
for (let i = 10; i <= 900; i >= 100 ? (i += 100) : (i += 10)) {
const dom = document.querySelector<HTMLElement>("[data-theme='custom']");
dom?.style.removeProperty(`--color-background-${i}`);
dom?.style.removeProperty(`--color-text-${i}`);
dom?.style.removeProperty(`--color-border-${i}`);
dom?.style.removeProperty(`--color-primary-${i}`);
dom?.style.removeProperty(`--color-sidebar-background-${i}`);
dom?.style.removeProperty(`--color-sidebar-text-${i}`);
dom?.style.removeProperty(`--color-sidebar-border-${i}`);
dom?.style.removeProperty("--color-scheme");
}
};

View File

@ -1,6 +1,7 @@
import { useEffect, useState } from "react";
import { useTheme } from "next-themes";
// next-themes
import { useTheme } from "next-themes";
// hooks
import useUserAuth from "hooks/use-user-auth";
// layouts
@ -15,11 +16,13 @@ import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs";
import { ICustomTheme } from "types";
const ProfilePreferences = () => {
const { user: myProfile } = useUserAuth();
const { theme } = useTheme();
const [customThemeSelectorOptions, setCustomThemeSelectorOptions] = useState(false);
const [preLoadedData, setPreLoadedData] = useState<ICustomTheme | null>(null);
const { theme } = useTheme();
const { user: myProfile } = useUserAuth();
useEffect(() => {
if (theme === "custom") {
if (myProfile?.theme.palette)
@ -37,6 +40,7 @@ const ProfilePreferences = () => {
myProfile.theme.palette !== ",,,,"
? myProfile.theme.palette
: "#0d101b,#c5c5c5,#3f76ff,#0d101b,#c5c5c5",
theme: "custom",
});
if (!customThemeSelectorOptions) setCustomThemeSelectorOptions(true);
}
@ -71,7 +75,6 @@ const ProfilePreferences = () => {
</div>
<div className="col-span-12 sm:col-span-6">
<ThemeSwitch
user={myProfile}
setPreLoadedData={setPreLoadedData}
customThemeSelectorOptions={customThemeSelectorOptions}
setCustomThemeSelectorOptions={setCustomThemeSelectorOptions}

View File

@ -45,7 +45,7 @@ Router.events.on("routeChangeComplete", NProgress.done);
function MyApp({ Component, pageProps }: AppProps) {
return (
// <UserProvider>
<ThemeProvider themes={THEMES} defaultTheme="dark">
<ThemeProvider themes={THEMES} defaultTheme="system">
<ToastContextProvider>
<ThemeContextProvider>
<CrispWithNoSSR />

View File

@ -1,143 +0,0 @@
import React from "react";
// layouts
import DefaultLayout from "layouts/default-layout";
import { UserAuthorizationLayout } from "layouts/auth-layout/user-authorization-wrapper";
// types
import type { NextPage } from "next";
const Colors: NextPage = () => (
<UserAuthorizationLayout>
<DefaultLayout>
<div className="space-y-8 p-8">
<div>
Primary:
<div className="flex flex-wrap">
<div className="h-12 w-12 bg-custom-primary-0" />
<div className="h-12 w-12 bg-custom-primary-10" />
<div className="h-12 w-12 bg-custom-primary-20" />
<div className="h-12 w-12 bg-custom-primary-30" />
<div className="h-12 w-12 bg-custom-primary-40" />
<div className="h-12 w-12 bg-custom-primary-50" />
<div className="h-12 w-12 bg-custom-primary-60" />
<div className="h-12 w-12 bg-custom-primary-70" />
<div className="h-12 w-12 bg-custom-primary-80" />
<div className="h-12 w-12 bg-custom-primary-90" />
<div className="h-12 w-12 bg-custom-primary-100" />
<div className="h-12 w-12 bg-custom-primary-200" />
<div className="h-12 w-12 bg-custom-primary-300" />
<div className="h-12 w-12 bg-custom-primary-400" />
<div className="h-12 w-12 bg-custom-primary-500" />
<div className="h-12 w-12 bg-custom-primary-600" />
<div className="h-12 w-12 bg-custom-primary-700" />
<div className="h-12 w-12 bg-custom-primary-800" />
<div className="h-12 w-12 bg-custom-primary-900" />
<div className="h-12 w-12 bg-custom-primary-1000" />
</div>
</div>
<div>
Background:
<div className="flex flex-wrap">
<div className="h-12 w-12 bg-custom-background-0" />
<div className="h-12 w-12 bg-custom-background-10" />
<div className="h-12 w-12 bg-custom-background-20" />
<div className="h-12 w-12 bg-custom-background-30" />
<div className="h-12 w-12 bg-custom-background-40" />
<div className="h-12 w-12 bg-custom-background-50" />
<div className="h-12 w-12 bg-custom-background-60" />
<div className="h-12 w-12 bg-custom-background-70" />
<div className="h-12 w-12 bg-custom-background-80" />
<div className="h-12 w-12 bg-custom-background-90" />
<div className="h-12 w-12 bg-custom-background-100" />
<div className="h-12 w-12 bg-custom-background-200" />
<div className="h-12 w-12 bg-custom-background-300" />
<div className="h-12 w-12 bg-custom-background-400" />
<div className="h-12 w-12 bg-custom-background-500" />
<div className="h-12 w-12 bg-custom-background-600" />
<div className="h-12 w-12 bg-custom-background-700" />
<div className="h-12 w-12 bg-custom-background-800" />
<div className="h-12 w-12 bg-custom-background-900" />
<div className="h-12 w-12 bg-custom-background-1000" />
</div>
</div>
<div>
Text:
<div className="flex flex-wrap">
<div className="h-12 w-12 bg-custom-text-0" />
<div className="h-12 w-12 bg-custom-text-10" />
<div className="h-12 w-12 bg-custom-text-20" />
<div className="h-12 w-12 bg-custom-text-30" />
<div className="h-12 w-12 bg-custom-text-40" />
<div className="h-12 w-12 bg-custom-text-50" />
<div className="h-12 w-12 bg-custom-text-60" />
<div className="h-12 w-12 bg-custom-text-70" />
<div className="h-12 w-12 bg-custom-text-80" />
<div className="h-12 w-12 bg-custom-text-90" />
<div className="h-12 w-12 bg-custom-text-100" />
<div className="h-12 w-12 bg-custom-text-200" />
<div className="h-12 w-12 bg-custom-text-300" />
<div className="h-12 w-12 bg-custom-text-400" />
<div className="h-12 w-12 bg-custom-text-500" />
<div className="h-12 w-12 bg-custom-text-600" />
<div className="h-12 w-12 bg-custom-text-700" />
<div className="h-12 w-12 bg-custom-text-800" />
<div className="h-12 w-12 bg-custom-text-900" />
<div className="h-12 w-12 bg-custom-text-1000" />
</div>
</div>
<div>
Sidebar Background:
<div className="flex flex-wrap">
<div className="h-12 w-12 bg-custom-sidebar-background-0" />
<div className="h-12 w-12 bg-custom-sidebar-background-10" />
<div className="h-12 w-12 bg-custom-sidebar-background-20" />
<div className="h-12 w-12 bg-custom-sidebar-background-30" />
<div className="h-12 w-12 bg-custom-sidebar-background-40" />
<div className="h-12 w-12 bg-custom-sidebar-background-50" />
<div className="h-12 w-12 bg-custom-sidebar-background-60" />
<div className="h-12 w-12 bg-custom-sidebar-background-70" />
<div className="h-12 w-12 bg-custom-sidebar-background-80" />
<div className="h-12 w-12 bg-custom-sidebar-background-90" />
<div className="h-12 w-12 bg-custom-sidebar-background-100" />
<div className="h-12 w-12 bg-custom-sidebar-background-200" />
<div className="h-12 w-12 bg-custom-sidebar-background-300" />
<div className="h-12 w-12 bg-custom-sidebar-background-400" />
<div className="h-12 w-12 bg-custom-sidebar-background-500" />
<div className="h-12 w-12 bg-custom-sidebar-background-600" />
<div className="h-12 w-12 bg-custom-sidebar-background-700" />
<div className="h-12 w-12 bg-custom-sidebar-background-800" />
<div className="h-12 w-12 bg-custom-sidebar-background-900" />
<div className="h-12 w-12 bg-custom-sidebar-background-1000" />
</div>
</div>
<div>
Sidebar Text:
<div className="flex flex-wrap">
<div className="h-12 w-12 bg-custom-sidebar-text-0" />
<div className="h-12 w-12 bg-custom-sidebar-text-10" />
<div className="h-12 w-12 bg-custom-sidebar-text-20" />
<div className="h-12 w-12 bg-custom-sidebar-text-30" />
<div className="h-12 w-12 bg-custom-sidebar-text-40" />
<div className="h-12 w-12 bg-custom-sidebar-text-50" />
<div className="h-12 w-12 bg-custom-sidebar-text-60" />
<div className="h-12 w-12 bg-custom-sidebar-text-70" />
<div className="h-12 w-12 bg-custom-sidebar-text-80" />
<div className="h-12 w-12 bg-custom-sidebar-text-90" />
<div className="h-12 w-12 bg-custom-sidebar-text-100" />
<div className="h-12 w-12 bg-custom-sidebar-text-200" />
<div className="h-12 w-12 bg-custom-sidebar-text-300" />
<div className="h-12 w-12 bg-custom-sidebar-text-400" />
<div className="h-12 w-12 bg-custom-sidebar-text-500" />
<div className="h-12 w-12 bg-custom-sidebar-text-600" />
<div className="h-12 w-12 bg-custom-sidebar-text-700" />
<div className="h-12 w-12 bg-custom-sidebar-text-800" />
<div className="h-12 w-12 bg-custom-sidebar-text-900" />
<div className="h-12 w-12 bg-custom-sidebar-text-1000" />
</div>
</div>
</div>
</DefaultLayout>
</UserAuthorizationLayout>
);
export default Colors;

View File

@ -1,4 +1,4 @@
import React from "react";
import React, { useEffect } from "react";
import Image from "next/image";
@ -22,6 +22,8 @@ import {
import { Spinner } from "components/ui";
// images
import BluePlaneLogoWithoutText from "public/plane-logos/blue-without-text.png";
import { useTheme } from "next-themes";
import { ICurrentUserResponse, IUser } from "types";
// types
type EmailPasswordFormValues = {
email: string;
@ -34,6 +36,12 @@ const HomePage: NextPage = () => {
const { setToastAlert } = useToast();
const { setTheme } = useTheme();
const changeTheme = (user: IUser) => {
setTheme(user.theme.theme ?? "system");
};
const handleGoogleSignIn = async ({ clientId, credential }: any) => {
try {
if (clientId && credential) {
@ -43,7 +51,10 @@ const HomePage: NextPage = () => {
clientId,
};
const response = await authenticationService.socialAuth(socialAuthPayload);
if (response && response?.user) mutateUser();
if (response && response?.user) {
mutateUser();
changeTheme(response.user);
}
} else {
throw Error("Cant find credentials");
}
@ -66,7 +77,10 @@ const HomePage: NextPage = () => {
clientId: process.env.NEXT_PUBLIC_GITHUB_ID,
};
const response = await authenticationService.socialAuth(socialAuthPayload);
if (response && response?.user) mutateUser();
if (response && response?.user) {
mutateUser();
changeTheme(response.user);
}
} else {
throw Error("Cant find credentials");
}
@ -85,7 +99,10 @@ const HomePage: NextPage = () => {
.emailLogin(formData)
.then((response) => {
try {
if (response) mutateUser();
if (response) {
mutateUser();
changeTheme(response.user);
}
} catch (err: any) {
setToastAlert({
type: "error",
@ -109,7 +126,10 @@ const HomePage: NextPage = () => {
const handleEmailCodeSignIn = async (response: any) => {
try {
if (response) mutateUser();
if (response) {
mutateUser();
changeTheme(response.user);
}
} catch (err: any) {
setToastAlert({
type: "error",
@ -120,6 +140,10 @@ const HomePage: NextPage = () => {
}
};
useEffect(() => {
setTheme("system");
}, [setTheme]);
return (
<DefaultLayout>
{isLoading ? (

View File

@ -1,6 +1,9 @@
import React, { useState, useEffect } from "react";
// next imports
import { useRouter } from "next/router";
// next-themes
import { useTheme } from "next-themes";
// layouts
import DefaultLayout from "layouts/default-layout";
// services
@ -17,11 +20,17 @@ const MagicSignIn: NextPage = () => {
const { setToastAlert } = useToast();
const { user, isLoading, mutateUser } = useUserAuth("sign-in");
const { setTheme } = useTheme();
const { mutateUser } = useUserAuth("sign-in");
const [isSigningIn, setIsSigningIn] = useState(false);
const [errorSigningIn, setErrorSignIn] = useState<string | undefined>();
useEffect(() => {
setTheme("system");
}, [setTheme]);
useEffect(() => {
setIsSigningIn(() => false);
setErrorSignIn(() => undefined);

View File

@ -1,6 +1,5 @@
import { useEffect, useState } from "react";
import Router from "next/router";
import Image from "next/image";
import useSWR, { mutate } from "swr";
@ -32,7 +31,7 @@ import { CURRENT_USER, USER_WORKSPACE_INVITATIONS } from "constants/fetch-keys";
const Onboarding: NextPage = () => {
const [step, setStep] = useState<number | null>(null);
const { theme } = useTheme();
const { theme, setTheme } = useTheme();
const { user, isLoading: userLoading } = useUserAuth("onboarding");
@ -117,6 +116,10 @@ const Onboarding: NextPage = () => {
await userService.updateUserOnBoard({ userRole: user.role }, user);
};
useEffect(() => {
setTheme("system");
}, [setTheme]);
useEffect(() => {
const handleStepChange = async () => {
if (!user || !invitations) return;

View File

@ -3,6 +3,8 @@ import React, { useEffect, useState } from "react";
import { useRouter } from "next/router";
import Image from "next/image";
// next-themes
import { useTheme } from "next-themes";
// react-hook-form
import { useForm } from "react-hook-form";
// hooks
@ -31,6 +33,8 @@ const ResetPasswordPage: NextPage = () => {
const { setToastAlert } = useToast();
const { setTheme } = useTheme();
const {
register,
handleSubmit,
@ -76,6 +80,10 @@ const ResetPasswordPage: NextPage = () => {
);
};
useEffect(() => {
setTheme("system");
}, [setTheme]);
useEffect(() => {
if (parseInt(process.env.NEXT_PUBLIC_ENABLE_OAUTH || "0")) router.push("/");
else setIsLoading(false);

View File

@ -3,6 +3,8 @@ import React, { useEffect, useState } from "react";
import Image from "next/image";
import { useRouter } from "next/router";
// next-themes
import { useTheme } from "next-themes";
// services
import authenticationService from "services/authentication.service";
// hooks
@ -31,6 +33,8 @@ const SignUp: NextPage = () => {
const { setToastAlert } = useToast();
const { setTheme } = useTheme();
const { mutateUser } = useUserAuth("sign-in");
const handleSignUp = async (formData: EmailPasswordFormValues) => {
@ -62,6 +66,10 @@ const SignUp: NextPage = () => {
);
};
useEffect(() => {
setTheme("system");
}, [setTheme]);
useEffect(() => {
if (parseInt(process.env.NEXT_PUBLIC_ENABLE_OAUTH || "0")) router.push("/");
else setIsLoading(false);

View File

@ -1,5 +1,6 @@
// services
import APIService from "services/api.service";
import { ICurrentUserResponse } from "types";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
@ -32,7 +33,11 @@ class AuthService extends APIService {
});
}
async socialAuth(data: any) {
async socialAuth(data: any): Promise<{
access_token: string;
refresh_toke: string;
user: ICurrentUserResponse;
}> {
return this.post("/api/social-auth/", data, { headers: {} })
.then((response) => {
this.setAccessToken(response?.data?.access_token);

View File

@ -46,6 +46,7 @@ export interface ICustomTheme {
sidebarText: string;
darkPalette: boolean;
palette: string;
theme: string;
}
export interface ICurrentUserResponse extends IUser {