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