feat: add frontend

This commit is contained in:
2024-05-12 06:00:04 +07:00
parent 093b0056fb
commit 3d7508816f
72 changed files with 2558 additions and 212 deletions
+15
View File
@@ -0,0 +1,15 @@
import { ClientResponse, hc } from "hono/client";
import type { AppRouter } from "../../../backend/src/routers";
const api = hc<AppRouter>("http://localhost:3000/");
export const parseJson = async <T>(res: ClientResponse<T>) => {
const json = await res.json();
if (!res.ok) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
throw new Error((json as any)?.message || "An error occured.");
}
return json as T;
};
export default api;
+38
View File
@@ -0,0 +1,38 @@
import { createStore, useStore } from "zustand";
type DisclosureStoreType<T> = {
isOpen: boolean;
data?: T;
};
export const createDisclosureStore = <T>(initialData?: T) => {
const store = createStore<DisclosureStoreType<T>>(() => ({
isOpen: false,
data: initialData,
}));
const onOpen = (data?: T) => {
store.setState({
isOpen: true,
data,
});
};
const onClose = () => {
store.setState({ isOpen: false });
};
const setOpen = (isOpen: boolean, data?: T) => {
store.setState({ isOpen, data });
};
const useState = () => {
return useStore(store);
};
return { store, useState, onOpen, onClose, setOpen };
};
export type DisclosureType<T = unknown> = ReturnType<
typeof createDisclosureStore<T>
>;
+3
View File
@@ -0,0 +1,3 @@
import { QueryClient } from "react-query";
export const queryClient = new QueryClient();
+30
View File
@@ -0,0 +1,30 @@
import { type ClassValue, clsx } from "clsx";
import { toast } from "sonner";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
export const getFilename = (path: string) => {
return path.split("/").pop();
};
export const formatBytes = (bytes: number, decimals = 0) => {
if (bytes == 0) return "0 Bytes";
const k = 1024;
const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return (
parseFloat((bytes / Math.pow(k, i)).toFixed(decimals)) + " " + sizes[i]
);
};
export const copyToClipboard = async (data: string) => {
try {
await navigator.clipboard.writeText(data);
toast.success("Copied to clipboard!");
} catch (err) {
toast.error("Failed to copy!");
}
};