mirror of
https://github.com/khairul169/db-backup-tool.git
synced 2026-10-30 23:00:49 +07:00
feat: add frontend
This commit is contained in:
@@ -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;
|
||||
@@ -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>
|
||||
>;
|
||||
@@ -0,0 +1,3 @@
|
||||
import { QueryClient } from "react-query";
|
||||
|
||||
export const queryClient = new QueryClient();
|
||||
@@ -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!");
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user