prettier format

This commit is contained in:
mbaharip
2024-05-18 15:19:11 +07:00
parent 356c8fc3e9
commit e5367e9a1a
8 changed files with 89 additions and 135 deletions
+12 -18
View File
@@ -1,35 +1,29 @@
"use client" "use client";
import { import { Toast, ToastClose, ToastDescription, ToastProvider, ToastTitle, ToastViewport } from "~/components/ui/toast";
Toast, import { useToast } from "~/components/ui/use-toast";
ToastClose,
ToastDescription,
ToastProvider,
ToastTitle,
ToastViewport,
} from "~/components/ui/toast"
import { useToast } from "~/components/ui/use-toast"
export function Toaster() { export function Toaster() {
const { toasts } = useToast() const { toasts } = useToast();
return ( return (
<ToastProvider> <ToastProvider>
{toasts.map(function ({ id, title, description, action, ...props }) { {toasts.map(function ({ id, title, description, action, ...props }) {
return ( return (
<Toast key={id} {...props}> <Toast
<div className="grid gap-1"> key={id}
{...props}
>
<div className='grid gap-1'>
{title && <ToastTitle>{title}</ToastTitle>} {title && <ToastTitle>{title}</ToastTitle>}
{description && ( {description && <ToastDescription>{description}</ToastDescription>}
<ToastDescription>{description}</ToastDescription>
)}
</div> </div>
{action} {action}
<ToastClose /> <ToastClose />
</Toast> </Toast>
) );
})} })}
<ToastViewport /> <ToastViewport />
</ToastProvider> </ToastProvider>
) );
} }
+64 -69
View File
@@ -1,78 +1,75 @@
"use client" "use client";
// Inspired by react-hot-toast library // Inspired by react-hot-toast library
import * as React from "react" import * as React from "react";
import type { import type { ToastActionElement, ToastProps } from "~/components/ui/toast";
ToastActionElement,
ToastProps,
} from "~/components/ui/toast"
const TOAST_LIMIT = 1 const TOAST_LIMIT = 1;
const TOAST_REMOVE_DELAY = 1000000 const TOAST_REMOVE_DELAY = 1000000;
type ToasterToast = ToastProps & { type ToasterToast = ToastProps & {
id: string id: string;
title?: React.ReactNode title?: React.ReactNode;
description?: React.ReactNode description?: React.ReactNode;
action?: ToastActionElement action?: ToastActionElement;
} };
const actionTypes = { const actionTypes = {
ADD_TOAST: "ADD_TOAST", ADD_TOAST: "ADD_TOAST",
UPDATE_TOAST: "UPDATE_TOAST", UPDATE_TOAST: "UPDATE_TOAST",
DISMISS_TOAST: "DISMISS_TOAST", DISMISS_TOAST: "DISMISS_TOAST",
REMOVE_TOAST: "REMOVE_TOAST", REMOVE_TOAST: "REMOVE_TOAST",
} as const } as const;
let count = 0 let count = 0;
function genId() { function genId() {
count = (count + 1) % Number.MAX_SAFE_INTEGER count = (count + 1) % Number.MAX_SAFE_INTEGER;
return count.toString() return count.toString();
} }
type ActionType = typeof actionTypes type ActionType = typeof actionTypes;
type Action = type Action =
| { | {
type: ActionType["ADD_TOAST"] type: ActionType["ADD_TOAST"];
toast: ToasterToast toast: ToasterToast;
} }
| { | {
type: ActionType["UPDATE_TOAST"] type: ActionType["UPDATE_TOAST"];
toast: Partial<ToasterToast> toast: Partial<ToasterToast>;
} }
| { | {
type: ActionType["DISMISS_TOAST"] type: ActionType["DISMISS_TOAST"];
toastId?: ToasterToast["id"] toastId?: ToasterToast["id"];
} }
| { | {
type: ActionType["REMOVE_TOAST"] type: ActionType["REMOVE_TOAST"];
toastId?: ToasterToast["id"] toastId?: ToasterToast["id"];
} };
interface State { interface State {
toasts: ToasterToast[] toasts: ToasterToast[];
} }
const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>() const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();
const addToRemoveQueue = (toastId: string) => { const addToRemoveQueue = (toastId: string) => {
if (toastTimeouts.has(toastId)) { if (toastTimeouts.has(toastId)) {
return return;
} }
const timeout = setTimeout(() => { const timeout = setTimeout(() => {
toastTimeouts.delete(toastId) toastTimeouts.delete(toastId);
dispatch({ dispatch({
type: "REMOVE_TOAST", type: "REMOVE_TOAST",
toastId: toastId, toastId: toastId,
}) });
}, TOAST_REMOVE_DELAY) }, TOAST_REMOVE_DELAY);
toastTimeouts.set(toastId, timeout) toastTimeouts.set(toastId, timeout);
} };
export const reducer = (state: State, action: Action): State => { export const reducer = (state: State, action: Action): State => {
switch (action.type) { switch (action.type) {
@@ -80,27 +77,25 @@ export const reducer = (state: State, action: Action): State => {
return { return {
...state, ...state,
toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT), toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
} };
case "UPDATE_TOAST": case "UPDATE_TOAST":
return { return {
...state, ...state,
toasts: state.toasts.map((t) => toasts: state.toasts.map((t) => (t.id === action.toast.id ? { ...t, ...action.toast } : t)),
t.id === action.toast.id ? { ...t, ...action.toast } : t };
),
}
case "DISMISS_TOAST": { case "DISMISS_TOAST": {
const { toastId } = action const { toastId } = action;
// ! Side effects ! - This could be extracted into a dismissToast() action, // ! Side effects ! - This could be extracted into a dismissToast() action,
// but I'll keep it here for simplicity // but I'll keep it here for simplicity
if (toastId) { if (toastId) {
addToRemoveQueue(toastId) addToRemoveQueue(toastId);
} else { } else {
state.toasts.forEach((toast) => { state.toasts.forEach((toast) => {
addToRemoveQueue(toast.id) addToRemoveQueue(toast.id);
}) });
} }
return { return {
@@ -111,46 +106,46 @@ export const reducer = (state: State, action: Action): State => {
...t, ...t,
open: false, open: false,
} }
: t : t,
), ),
} };
} }
case "REMOVE_TOAST": case "REMOVE_TOAST":
if (action.toastId === undefined) { if (action.toastId === undefined) {
return { return {
...state, ...state,
toasts: [], toasts: [],
} };
} }
return { return {
...state, ...state,
toasts: state.toasts.filter((t) => t.id !== action.toastId), toasts: state.toasts.filter((t) => t.id !== action.toastId),
} };
} }
} };
const listeners: Array<(state: State) => void> = [] const listeners: Array<(state: State) => void> = [];
let memoryState: State = { toasts: [] } let memoryState: State = { toasts: [] };
function dispatch(action: Action) { function dispatch(action: Action) {
memoryState = reducer(memoryState, action) memoryState = reducer(memoryState, action);
listeners.forEach((listener) => { listeners.forEach((listener) => {
listener(memoryState) listener(memoryState);
}) });
} }
type Toast = Omit<ToasterToast, "id"> type Toast = Omit<ToasterToast, "id">;
function toast({ ...props }: Toast) { function toast({ ...props }: Toast) {
const id = genId() const id = genId();
const update = (props: ToasterToast) => const update = (props: ToasterToast) =>
dispatch({ dispatch({
type: "UPDATE_TOAST", type: "UPDATE_TOAST",
toast: { ...props, id }, toast: { ...props, id },
}) });
const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id }) const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id });
dispatch({ dispatch({
type: "ADD_TOAST", type: "ADD_TOAST",
@@ -159,36 +154,36 @@ function toast({ ...props }: Toast) {
id, id,
open: true, open: true,
onOpenChange: (open) => { onOpenChange: (open) => {
if (!open) dismiss() if (!open) dismiss();
}, },
}, },
}) });
return { return {
id: id, id: id,
dismiss, dismiss,
update, update,
} };
} }
function useToast() { function useToast() {
const [state, setState] = React.useState<State>(memoryState) const [state, setState] = React.useState<State>(memoryState);
React.useEffect(() => { React.useEffect(() => {
listeners.push(setState) listeners.push(setState);
return () => { return () => {
const index = listeners.indexOf(setState) const index = listeners.indexOf(setState);
if (index > -1) { if (index > -1) {
listeners.splice(index, 1) listeners.splice(index, 1);
} }
} };
}, [state]) }, [state]);
return { return {
...state, ...state,
toast, toast,
dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }), dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
} };
} }
export { useToast, toast } export { useToast, toast };
+1 -5
View File
@@ -37,10 +37,6 @@ const LayoutProvider = ({ children }: TLayoutProvider) => {
localStorage.setItem("layout", layout); localStorage.setItem("layout", layout);
}; };
return ( return <LayoutContext.Provider value={{ layout, setLayout: onChangeLayout }}>{children}</LayoutContext.Provider>;
<LayoutContext.Provider value={{ layout, setLayout: onChangeLayout }}>
{children}
</LayoutContext.Provider>
);
}; };
export default LayoutProvider; export default LayoutProvider;
+1 -5
View File
@@ -35,9 +35,5 @@ const ThemeProvider = ({ children }: TThemeProvider) => {
setTheme(getThemeFromLocalStorage()); setTheme(getThemeFromLocalStorage());
}, []); }, []);
return ( return <ThemeContext.Provider value={{ theme, setTheme }}>{children}</ThemeContext.Provider>;
<ThemeContext.Provider value={{ theme, setTheme }}>
{children}
</ThemeContext.Provider>
);
}; };
+1 -2
View File
@@ -23,8 +23,7 @@ export default function useLocalStorage<T>(key: string, initialValue: T) {
// Create dispatch function to set or remove localStorage // Create dispatch function to set or remove localStorage
const setValue: SetValue<T> = (value) => { const setValue: SetValue<T> = (value) => {
try { try {
const valueToStore = const valueToStore = value instanceof Function ? value(storedValue) : value;
value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore); setStoredValue(valueToStore);
window.localStorage.setItem(key, JSON.stringify(valueToStore)); window.localStorage.setItem(key, JSON.stringify(valueToStore));
} catch (error) { } catch (error) {
+4 -11
View File
@@ -133,12 +133,7 @@ export const Schema_Config_Site = z.object({
toaster: z toaster: z
.object({ .object({
position: z.enum([ position: z.enum(["top-left", "top-right", "bottom-left", "bottom-right"]),
"top-left",
"top-right",
"bottom-left",
"bottom-right",
]),
duration: z.number().positive(), duration: z.number().positive(),
}) })
.optional() .optional()
@@ -201,12 +196,10 @@ export const Schema_App_Configuration = z.object({
site: Schema_Config_Site, site: Schema_Config_Site,
}); });
export type ConfigurationCategory = keyof z.infer< export type ConfigurationCategory = keyof z.infer<typeof Schema_App_Configuration>;
export type ConfigurationKeys<T extends keyof z.infer<typeof Schema_App_Configuration>> = keyof z.infer<
typeof Schema_App_Configuration typeof Schema_App_Configuration
>; >[T];
export type ConfigurationKeys<
T extends keyof z.infer<typeof Schema_App_Configuration>,
> = keyof z.infer<typeof Schema_App_Configuration>[T];
export type ConfigurationValue< export type ConfigurationValue<
T extends keyof z.infer<typeof Schema_App_Configuration>, T extends keyof z.infer<typeof Schema_App_Configuration>,
K extends keyof z.infer<typeof Schema_App_Configuration>[T], K extends keyof z.infer<typeof Schema_App_Configuration>[T],
+5 -19
View File
@@ -15,17 +15,11 @@ const generateKey = () => {
}; };
const key = generateKey(); const key = generateKey();
export async function encryptData( export async function encryptData(data: string, encryptKey: string = key): Promise<string> {
data: string,
encryptKey: string = key,
): Promise<string> {
try { try {
const ivKey = Buffer.from(key); const ivKey = Buffer.from(key);
const cipher = crypto.createCipheriv("aes-128-cbc", encryptKey, ivKey); const cipher = crypto.createCipheriv("aes-128-cbc", encryptKey, ivKey);
return Buffer.concat([ return Buffer.concat([cipher.update(data, "utf-8"), cipher.final()]).toString("hex");
cipher.update(data, "utf-8"),
cipher.final(),
]).toString("hex");
} catch (error) { } catch (error) {
const e = error as Error; const e = error as Error;
console.error(e.message); console.error(e.message);
@@ -33,23 +27,15 @@ export async function encryptData(
} }
} }
export async function decryptData( export async function decryptData(hash: string, encryptKey: string = key): Promise<string> {
hash: string,
encryptKey: string = key,
): Promise<string> {
try { try {
const ivKey = Buffer.from(key); const ivKey = Buffer.from(key);
const decipher = crypto.createDecipheriv("aes-128-cbc", encryptKey, ivKey); const decipher = crypto.createDecipheriv("aes-128-cbc", encryptKey, ivKey);
return Buffer.concat([ return Buffer.concat([decipher.update(hash, "hex"), decipher.final()]).toString("utf-8");
decipher.update(hash, "hex"),
decipher.final(),
]).toString("utf-8");
} catch (error) { } catch (error) {
const e = error as Error; const e = error as Error;
console.error(e.message); console.error(e.message);
throw new Error( throw new Error("Failed to decrypt data, either invalid hash or encryption key.");
"Failed to decrypt data, either invalid hash or encryption key.",
);
} }
} }
+1 -6
View File
@@ -3,12 +3,7 @@ import tw from "tailwindcss/defaultTheme";
const config: Config = { const config: Config = {
darkMode: ["class"], darkMode: ["class"],
content: [ content: ["./pages/**/*.{ts,tsx}", "./components/**/*.{ts,tsx}", "./app/**/*.{ts,tsx}", "./src/**/*.{ts,tsx}"],
"./pages/**/*.{ts,tsx}",
"./components/**/*.{ts,tsx}",
"./app/**/*.{ts,tsx}",
"./src/**/*.{ts,tsx}",
],
prefix: "", prefix: "",
theme: { theme: {
container: { container: {