import React, { useEffect, useState } from "react"; import { useTheme } from "next-themes"; import { useForm } from "react-hook-form"; // hooks import useUser from "hooks/use-user"; // ui import { PrimaryButton } from "components/ui"; import { ColorPickerInput } from "components/core"; // services import userService from "services/user.service"; // helper import { applyTheme } from "helpers/theme.helper"; import { hexToRgb, rgbToHex } from "helpers/color.helper"; // types import { ICustomTheme } from "types"; type Props = { preLoadedData?: Partial | null; }; const defaultValues = { "accent-500": "#FE5050", bgBase: "#FFF7F7", bgSurface1: "#FFE0E0", bgSurface2: "#FFF7F7", border: "#FFC9C9", darkPalette: false, palette: "", sidebar: "#FFFFFF", textBase: "#430000", textSecondary: "#323232", }; export const CustomThemeSelector: React.FC = ({ preLoadedData }) => { const [darkPalette, setDarkPalette] = useState(false); const { register, formState: { errors, isSubmitting }, handleSubmit, watch, setValue, reset, } = useForm({ defaultValues, }); const { setTheme } = useTheme(); const { mutateUser } = useUser(); const calculateShade = (hexValue: string, shade: number): string => { const { r, g, b } = hexToRgb(hexValue); if (shade > 500) { let decimalValue = 0.1; if (shade === 600) decimalValue = 0.1; else if (shade === 700) decimalValue = 0.2; else if (shade === 800) decimalValue = 0.3; else if (shade === 900) decimalValue = 0.4; const newR = Math.ceil(r * decimalValue); const newG = Math.ceil(g * decimalValue); const newB = Math.ceil(b * decimalValue); return rgbToHex({ r: newR, g: newG, b: newB }); } else { const decimalValue = 1 - (shade * 2) / 1000; const newR = Math.floor(r + (255 - r) * decimalValue); const newG = Math.floor(g + (255 - g) * decimalValue); const newB = Math.floor(b + (255 - b) * decimalValue); return rgbToHex({ r: newR, g: newG, b: newB }); } }; const handleFormSubmit = async (formData: any) => { const accent = { "accent-50": calculateShade(formData["accent-500"], 50), "accent-100": calculateShade(formData["accent-500"], 100), "accent-200": calculateShade(formData["accent-500"], 200), "accent-300": calculateShade(formData["accent-500"], 300), "accent-400": calculateShade(formData["accent-500"], 400), "accent-500": formData["accent-500"], "accent-600": calculateShade(formData["accent-500"], 600), "accent-700": calculateShade(formData["accent-500"], 700), "accent-800": calculateShade(formData["accent-500"], 800), "accent-900": calculateShade(formData["accent-500"], 900), }; const payload: ICustomTheme = { ...accent, bgBase: formData.bgBase, bgSurface1: formData.bgSurface1, bgSurface2: formData.bgSurface2, border: formData.border, darkPalette: darkPalette, palette: `${formData.bgBase},${formData.bgSurface1},${formData.bgSurface2},${formData.border},${formData.sidebar},${accent["accent-50"]},${accent["accent-100"]},${accent["accent-200"]},${accent["accent-300"]},${accent["accent-400"]},${accent["accent-500"]},${accent["accent-600"]},${accent["accent-700"]},${accent["accent-800"]},${accent["accent-900"]},${formData.textBase},${formData.textSecondary}`, sidebar: formData.sidebar, textBase: formData.textBase, textSecondary: formData.textSecondary, }; await userService .updateUser({ theme: payload, }) .then((res) => { mutateUser((prevData) => { if (!prevData) return prevData; return { ...prevData, ...res }; }, false); applyTheme(payload.palette, darkPalette); setTheme("custom"); }) .catch((err) => console.log(err)); }; const handleUpdateTheme = async (formData: any) => { await handleFormSubmit({ ...formData, darkPalette }); }; useEffect(() => { reset({ ...defaultValues, ...preLoadedData, }); }, [preLoadedData, reset]); return (

Customize your theme

Background

Background surface 1

Background surface 2

Border

Sidebar

Accent

Text primary

Text secondary

{isSubmitting ? "Creating Theme..." : "Set Theme"}
); };