diff --git a/package-lock.json b/package-lock.json index 122d218..be7d4ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@lexical/rich-text": "^0.34.0", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dropdown-menu": "^2.1.16", + "@radix-ui/react-label": "^2.1.7", "@radix-ui/react-separator": "^1.1.7", "@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-tooltip": "^1.2.8", @@ -1253,6 +1254,29 @@ } } }, + "node_modules/@radix-ui/react-label": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.7.tgz", + "integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-menu": { "version": "2.1.16", "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz", diff --git a/package.json b/package.json index c8216fb..dfa5ce7 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@lexical/rich-text": "^0.34.0", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dropdown-menu": "^2.1.16", + "@radix-ui/react-label": "^2.1.7", "@radix-ui/react-separator": "^1.1.7", "@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-tooltip": "^1.2.8", diff --git a/src/app/page.tsx b/src/app/page.tsx index eb96bae..2aa95be 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,15 +1,22 @@ -'use client'; +"use client"; import AppSidebar from "@/components/Sidebar"; -import { Button } from "@/components/ui/button"; -import Image from "next/image"; export default function Home() { return ( - - + + ok ); } diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index a55d105..cf05d5b 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -1,14 +1,15 @@ +"use client"; + import { Sidebar, SidebarContent, - SidebarFooter, SidebarHeader, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarProvider, } from "./ui/sidebar"; -import { ChevronDown, HashIcon, MicIcon, SpeakerIcon } from "lucide-react"; +import { ChevronDown, HashIcon, MicIcon } from "lucide-react"; import { DropdownMenuItem, DropdownMenu, @@ -16,6 +17,22 @@ import { DropdownMenuTrigger, } from "./ui/dropdown-menu"; import Server from "@/types/server"; +import { useEffect, useState } from "react"; +import Cookies from "js-cookie"; +import { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "./ui/dialog"; +import { Input } from "./ui/input"; +import { Label } from "./ui/label"; +import { Button } from "./ui/button"; +import Link from "next/link"; export default function AppSidebar({ server, @@ -24,43 +41,118 @@ export default function AppSidebar({ server?: Server; children: React.ReactNode; }>) { - return server ? ( - - - - - - - - - Select Server - - - + const [servers, setServers] = useState<[string, string][]>([]); + const [newServer, setNewServer] = useState({ name: "", ip: "" }); - - - Acme Inc - - - Acme Corp. - - - - - - - - {server.channels.map((channel) => ( - - {channel.kind === "voice" ? : } - {channel.name} - - ))} - - - {children} - + useEffect(() => { + const s = Cookies.get("servers")?.split(","); + if (s) setServers(s.map((x) => x.trim().split("@") as [string, string])); + }, []); + + const handleAddServer = () => { + if (!newServer.ip) return; + const updatedServers = [ + ...servers, + [newServer.ip, newServer.name] as [string, string], + ]; + + setServers(updatedServers); + Cookies.set("servers", updatedServers.map((x) => x.join("@")).join(","), { + expires: 7, + }); + setNewServer({ name: "", ip: "" }); + }; + + return server ? ( + + + + Add server + + Add a new server to your server list. + + + +
+
+ + + setNewServer((prev) => ({ ...prev, name: e.target.value })) + } + placeholder="Voxa Server" + /> +
+
+ + + setNewServer((prev) => ({ ...prev, ip: e.target.value })) + } + placeholder="192.168.1.5" + /> +
+
+ + + + + + + + + +
+ + + + + + + + + + Select Server + + + + + + {servers.map((s, i) => ( + + {s[1] || s[0]} + + ))} + + + Add Server + + + + + + + + + {server.channels.map((channel) => ( + + {channel.kind === "voice" ? : } + {channel.name} + + ))} + + + {children} + +
) : ( children ); diff --git a/src/components/ui/dialog.tsx b/src/components/ui/dialog.tsx new file mode 100644 index 0000000..d9ccec9 --- /dev/null +++ b/src/components/ui/dialog.tsx @@ -0,0 +1,143 @@ +"use client" + +import * as React from "react" +import * as DialogPrimitive from "@radix-ui/react-dialog" +import { XIcon } from "lucide-react" + +import { cn } from "@/lib/utils" + +function Dialog({ + ...props +}: React.ComponentProps) { + return +} + +function DialogTrigger({ + ...props +}: React.ComponentProps) { + return +} + +function DialogPortal({ + ...props +}: React.ComponentProps) { + return +} + +function DialogClose({ + ...props +}: React.ComponentProps) { + return +} + +function DialogOverlay({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DialogContent({ + className, + children, + showCloseButton = true, + ...props +}: React.ComponentProps & { + showCloseButton?: boolean +}) { + return ( + + + + {children} + {showCloseButton && ( + + + Close + + )} + + + ) +} + +function DialogHeader({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function DialogFooter({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function DialogTitle({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DialogDescription({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +export { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogOverlay, + DialogPortal, + DialogTitle, + DialogTrigger, +} diff --git a/src/components/ui/label.tsx b/src/components/ui/label.tsx new file mode 100644 index 0000000..fb5fbc3 --- /dev/null +++ b/src/components/ui/label.tsx @@ -0,0 +1,24 @@ +"use client" + +import * as React from "react" +import * as LabelPrimitive from "@radix-ui/react-label" + +import { cn } from "@/lib/utils" + +function Label({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +export { Label }