2 Commits
v0.0.6 ... main

Author SHA1 Message Date
typist
28a86dcbff 0.0.7
All checks were successful
Build and Push Docker Image / build (push) Successful in 1m24s
2025-10-28 04:40:54 +08:00
7cd826b052 feat: add-tool base64 (#7)
Co-authored-by: typist <git@mail.typist.cc>
Reviewed-on: #7
2025-10-28 04:39:39 +08:00
4 changed files with 82 additions and 4 deletions

View File

@@ -1,7 +1,7 @@
{ {
"name": "litek", "name": "litek",
"private": true, "private": true,
"version": "0.0.6", "version": "0.0.7",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",

View File

@@ -0,0 +1,70 @@
import { useState, type FC } from "react";
import { Textarea } from "@/components/ui/textarea";
import { Button } from "@/components/ui/button";
import { toast } from "sonner";
import { ArrowLeftIcon, ArrowRightIcon } from "lucide-react";
const Tool: FC = () => {
const [decoded, setDecoded] = useState<string>("");
const [encoded, setEncoded] = useState<string>("");
const encode = () => {
try {
const encoded64 = btoa(decoded);
setEncoded(encoded64);
setDecoded("");
toast.success("encoded successfully");
} catch (error: unknown) {
if (error instanceof Error) {
toast.error(error.message);
} else {
toast.error("encoding failed");
}
}
};
const decode = () => {
try {
const decoded64 = atob(encoded);
setDecoded(decoded64);
setEncoded("");
toast.success("decoded successfully");
} catch (error: unknown) {
if (error instanceof Error) {
toast.error(error.message);
} else {
toast.error("decoding failed");
}
}
};
return (
<div className="h-[50vh] flex flex-row gap-4 pt-[20vh]">
<Textarea
className="flex-1 resize-none"
placeholder="Enter the original text"
value={decoded}
onChange={(e) => setDecoded(e.target.value)}
/>
<div className="flex flex-col gap-2 justify-center">
<Button onClick={encode}>
<ArrowRightIcon className="size-4" />
Encode
</Button>
<Button onClick={decode}>
<ArrowLeftIcon className="size-4" />
Decode
</Button>
</div>
<Textarea
className="flex-1 resize-none"
placeholder="Enter the Base64 encoded text"
value={encoded}
onChange={(e) => setEncoded(e.target.value)}
/>
</div>
);
};
export default Tool;

View File

@@ -1,8 +1,9 @@
import type { ReactNode } from 'react'; import type { ReactNode } from 'react';
import { FileJson, Hash } from 'lucide-react' import { FileJson, Hash, Binary } from 'lucide-react'
import UUID from './uuid' import UUID from './uuid'
import JSON from './json' import JSON from './json'
import Base64 from './base64'
export interface Tool { export interface Tool {
path: string; path: string;
@@ -26,5 +27,12 @@ export const tools: Tool[] = [
description: "Format and validate JSON", description: "Format and validate JSON",
icon: <FileJson />, icon: <FileJson />,
component: <JSON />, component: <JSON />,
},
{
path: "base64",
name: "Base64 Encoder/Decoder",
description: "Encode and decode Base64",
icon: <Binary />,
component: <Base64 />,
} }
]; ];

View File

@@ -7,12 +7,12 @@ import { AppSidebar } from "@/components/sidebar";
export const Layout: FC = () => ( export const Layout: FC = () => (
<SidebarProvider> <SidebarProvider>
<AppSidebar /> <AppSidebar />
<div className="p-4 flex flex-col w-full h-[100vh]"> <div className="p-4 flex flex-col w-full h-[100vh] overflow-hidden">
<nav className="flex items-center justify-between"> <nav className="flex items-center justify-between">
<SidebarTrigger className="size-10" /> <SidebarTrigger className="size-10" />
<div role="actions" /> <div role="actions" />
</nav> </nav>
<main className="flex-1 overflow-auto p-4"> <main className="flex-1 overflow-auto p-4 overflow-hidden">
<Outlet /> <Outlet />
</main> </main>
</div> </div>