diff --git a/react-frontend/bun.lockb b/react-frontend/bun.lockb index 6147480..4dcb424 100755 Binary files a/react-frontend/bun.lockb and b/react-frontend/bun.lockb differ diff --git a/react-frontend/package.json b/react-frontend/package.json index 881e77d..ff97f0c 100644 --- a/react-frontend/package.json +++ b/react-frontend/package.json @@ -11,7 +11,9 @@ }, "dependencies": { "@radix-ui/react-alert-dialog": "^1.0.4", + "@radix-ui/react-dialog": "^1.0.4", "@radix-ui/react-dropdown-menu": "^2.0.5", + "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-slot": "^1.0.2", "class-variance-authority": "^0.7.0", "clsx": "^2.0.0", diff --git a/react-frontend/src/App.tsx b/react-frontend/src/App.tsx index d8b3748..0b862c1 100644 --- a/react-frontend/src/App.tsx +++ b/react-frontend/src/App.tsx @@ -1,56 +1,153 @@ -import './App.css' -import { ModeToggle } from './components/mode-toggle' -import { Button } from './components/ui/button' +import { ModeToggle } from '@/components/mode-toggle' import { ThemeProvider } from '@/components/theme-provider' +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogFooter, + DialogTitle, + DialogTrigger, +} from '@/components/ui/dialog' +import { Button } from '@/components/ui/button' +import { Input } from '@/components/ui/input' +import { Label } from '@/components/ui/label' +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from '@/components/ui/table' +import { useEffect, useState } from 'react' + +const backend_url = 'http://192.168.100.40:1234' + +type Shortener = { + id: number + link: string + code: string +} + +export default function App() { + const [shorteners, setShorteners] = useState([]) + + const getShorteners = async () => { + const response = await fetch(backend_url + '/link', { + method: 'GET', + }) + + const data = (await response.json()).shorteners as Shortener[] + + setShorteners(data) + } + + useEffect(() => { + if (!shorteners.length) { + getShorteners() + } + }, []) -function App() { return ( - - - + +
+ +
) } -import { - AlertDialog, - AlertDialogAction, - AlertDialogCancel, - AlertDialogContent, - AlertDialogDescription, - AlertDialogFooter, - AlertDialogHeader, - AlertDialogTitle, - AlertDialogTrigger, -} from '@/components/ui/alert-dialog' - -export function AlertDialogDemo() { +const Navbar = ({ getShorteners }: { getShorteners: () => Promise }) => { + return ( +
+
+
Shortener
+
+ + +
+
+
+ ) +} +const CreateShortener = ({ + getShorteners, +}: { + getShorteners: () => Promise +}) => { + const [link, setLink] = useState('') + const addShortener = async () => { + await fetch(backend_url + '/link', { + headers: { + 'Content-Type': 'application/json', + }, + method: 'POST', + body: JSON.stringify({ + link: link, + }), + }).then(() => { + getShorteners() + setLink('') + }) + } return ( - - - - - - - - Are you absolutely sure? - - - This action cannot be undone. This will permanently - delete your account and remove your data from our - servers. - - - - Cancel - Continue - - - + + + + + + + Add Shortener + + Create a new shortener for your link. + + +
+
+ + setLink(e.target.value)} + /> +
+
+ + + +
+
) } -export default App +const ShortenerTable = ({ shorteners }: { shorteners: Shortener[] }) => { + return ( + + + + Link + Shortener + + + + {shorteners.map((shortener) => ( + + {shortener.link} + {shortener.code} + + ))} + +
+ ) +} diff --git a/react-frontend/src/components/ui/dialog.tsx b/react-frontend/src/components/ui/dialog.tsx new file mode 100644 index 0000000..f50d5d0 --- /dev/null +++ b/react-frontend/src/components/ui/dialog.tsx @@ -0,0 +1,121 @@ +import * as React from "react" +import * as DialogPrimitive from "@radix-ui/react-dialog" +import { X } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Dialog = DialogPrimitive.Root + +const DialogTrigger = DialogPrimitive.Trigger + +const DialogPortal = ({ + className, + ...props +}: DialogPrimitive.DialogPortalProps) => ( + +) +DialogPortal.displayName = DialogPrimitive.Portal.displayName + +const DialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName + +const DialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)) +DialogContent.displayName = DialogPrimitive.Content.displayName + +const DialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogHeader.displayName = "DialogHeader" + +const DialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogFooter.displayName = "DialogFooter" + +const DialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogTitle.displayName = DialogPrimitive.Title.displayName + +const DialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogDescription.displayName = DialogPrimitive.Description.displayName + +export { + Dialog, + DialogTrigger, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, +} diff --git a/react-frontend/src/components/ui/input.tsx b/react-frontend/src/components/ui/input.tsx new file mode 100644 index 0000000..677d05f --- /dev/null +++ b/react-frontend/src/components/ui/input.tsx @@ -0,0 +1,25 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +export interface InputProps + extends React.InputHTMLAttributes {} + +const Input = React.forwardRef( + ({ className, type, ...props }, ref) => { + return ( + + ) + } +) +Input.displayName = "Input" + +export { Input } diff --git a/react-frontend/src/components/ui/label.tsx b/react-frontend/src/components/ui/label.tsx new file mode 100644 index 0000000..683faa7 --- /dev/null +++ b/react-frontend/src/components/ui/label.tsx @@ -0,0 +1,24 @@ +import * as React from "react" +import * as LabelPrimitive from "@radix-ui/react-label" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const labelVariants = cva( + "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" +) + +const Label = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, ...props }, ref) => ( + +)) +Label.displayName = LabelPrimitive.Root.displayName + +export { Label } diff --git a/react-frontend/src/components/ui/table.tsx b/react-frontend/src/components/ui/table.tsx new file mode 100644 index 0000000..bb3a87f --- /dev/null +++ b/react-frontend/src/components/ui/table.tsx @@ -0,0 +1,114 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Table = React.forwardRef< + HTMLTableElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+ + +)) +Table.displayName = "Table" + +const TableHeader = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableHeader.displayName = "TableHeader" + +const TableBody = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableBody.displayName = "TableBody" + +const TableFooter = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableFooter.displayName = "TableFooter" + +const TableRow = React.forwardRef< + HTMLTableRowElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableRow.displayName = "TableRow" + +const TableHead = React.forwardRef< + HTMLTableCellElement, + React.ThHTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +TableHead.displayName = "TableHead" + +const TableCell = React.forwardRef< + HTMLTableCellElement, + React.TdHTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableCell.displayName = "TableCell" + +const TableCaption = React.forwardRef< + HTMLTableCaptionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +TableCaption.displayName = "TableCaption" + +export { + Table, + TableHeader, + TableBody, + TableFooter, + TableHead, + TableRow, + TableCell, + TableCaption, +}