diff --git a/dist-electron/main.js b/dist-electron/main.js index c9c7726..728ec0d 100644 --- a/dist-electron/main.js +++ b/dist-electron/main.js @@ -38,7 +38,11 @@ function createWindow() { icon: path.join(__dirname, "path-to-your-icon", "electron-vite.svg"), webPreferences: { preload: path.join(__dirname, "preload.mjs") - } + }, + width: 900, + height: 700, + minWidth: 900, + minHeight: 700 }); win.webContents.on("did-finish-load", () => { win == null ? void 0 : win.webContents.send("main-process-message", (/* @__PURE__ */ new Date()).toLocaleString()); diff --git a/electron/main.ts b/electron/main.ts index c81eb41..47785f1 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -51,6 +51,10 @@ function createWindow() { webPreferences: { preload: path.join(__dirname, "preload.mjs"), }, + width: 900, + height: 700, + minWidth: 900, + minHeight: 700, }); // Send a message to the Renderer process when the window has finished loading diff --git a/package.json b/package.json index b07cf14..697e577 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "dependencies": { "@floating-ui/react-dom": "^2.1.1", "@headlessui/react": "^2.1.3", + "@tanstack/react-query": "^5.53.3", "axios": "^1.7.5", "class-variance-authority": "^0.7.0", "framer-motion": "^11.3.30", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0c6b9ef..ee7914c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ importers: '@headlessui/react': specifier: ^2.1.3 version: 2.1.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@tanstack/react-query': + specifier: ^5.53.3 + version: 5.53.3(react@18.3.1) axios: specifier: ^1.7.5 version: 1.7.5 @@ -602,6 +605,14 @@ packages: resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} engines: {node: '>=10'} + '@tanstack/query-core@5.53.3': + resolution: {integrity: sha512-ZfjAgd7NpqDx0e4aYBt7EmS2enbulPrJwowTy+mayRE93WUUH+sIYHun1TdRjpGwDPMNNZ5D6goh7n3CwoO+HA==} + + '@tanstack/react-query@5.53.3': + resolution: {integrity: sha512-286mN/91CeM7vC6CZFLKYDHSw+WyMX6ekIvzoTbpM4xyPb99VSyCKPLyPgaOatKqYm6ooMBquSq9NGRdKgsJfg==} + peerDependencies: + react: ^18 || ^19 + '@tanstack/react-virtual@3.10.4': resolution: {integrity: sha512-Y2y1QJN3e5gNTG4wlZcoW2IAFrVCuho80oyeODKKFVSbAhJAXmkDNH3ZztM6EQij5ueqpqgz5FlsgKP9TGjImA==} peerDependencies: @@ -2871,6 +2882,13 @@ snapshots: dependencies: defer-to-connect: 2.0.1 + '@tanstack/query-core@5.53.3': {} + + '@tanstack/react-query@5.53.3(react@18.3.1)': + dependencies: + '@tanstack/query-core': 5.53.3 + react: 18.3.1 + '@tanstack/react-virtual@3.10.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@tanstack/virtual-core': 3.10.4 diff --git a/src/App.tsx b/src/App.tsx index a5f1e94..9fd9bec 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,6 +4,7 @@ import router from "./router/MainRouter"; import "./i18n"; import { useEffect } from "react"; import { useTranslation } from "react-i18next"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; const App = () => { const { i18n } = useTranslation(); @@ -11,9 +12,13 @@ const App = () => { const lng = navigator.language; i18n.changeLanguage(lng); }, []); + + const queryClient = new QueryClient(); return ( - + + + ); }; diff --git a/src/assets/Icons/CheckIcon.tsx b/src/assets/Icons/CheckIcon.tsx new file mode 100644 index 0000000..af646aa --- /dev/null +++ b/src/assets/Icons/CheckIcon.tsx @@ -0,0 +1,24 @@ +const CheckIcon = ({ + stroke, + className, +}: { + stroke?: number; + className?: string; +}) => ( + + + +); + +export default CheckIcon; diff --git a/src/assets/Icons/DownIcon.tsx b/src/assets/Icons/DownIcon.tsx new file mode 100644 index 0000000..dc780f9 --- /dev/null +++ b/src/assets/Icons/DownIcon.tsx @@ -0,0 +1,24 @@ +const DownIcon = ({ + stroke, + className, +}: { + stroke?: number; + className?: string; +}) => ( + + + +); + +export default DownIcon; diff --git a/src/assets/Icons/FolderAddIcon.tsx b/src/assets/Icons/FolderAddIcon.tsx new file mode 100644 index 0000000..f4001e3 --- /dev/null +++ b/src/assets/Icons/FolderAddIcon.tsx @@ -0,0 +1,40 @@ +const FolderAddIcon = ({ + stroke, + className, + solid, +}: { + stroke?: number; + className?: string; + solid?: boolean; +}) => + solid ? ( + + + + ) : ( + + + + ); + +export default FolderAddIcon; diff --git a/src/assets/Icons/LeftIcon.tsx b/src/assets/Icons/LeftIcon.tsx new file mode 100644 index 0000000..892886b --- /dev/null +++ b/src/assets/Icons/LeftIcon.tsx @@ -0,0 +1,24 @@ +const LeftIcon = ({ + stroke, + className, +}: { + stroke?: number; + className?: string; +}) => ( + + + +); + +export default LeftIcon; diff --git a/src/assets/Icons/RightIcon.tsx b/src/assets/Icons/RightIcon.tsx new file mode 100644 index 0000000..2cbd98b --- /dev/null +++ b/src/assets/Icons/RightIcon.tsx @@ -0,0 +1,24 @@ +const RightIcon = ({ + stroke, + className, +}: { + stroke?: number; + className?: string; +}) => ( + + + +); + +export default RightIcon; diff --git a/src/assets/Icons/UpIcon.tsx b/src/assets/Icons/UpIcon.tsx new file mode 100644 index 0000000..104bf43 --- /dev/null +++ b/src/assets/Icons/UpIcon.tsx @@ -0,0 +1,24 @@ +const UpIcon = ({ + stroke, + className, +}: { + stroke?: number; + className?: string; +}) => ( + + + +); + +export default UpIcon; diff --git a/src/components/Crax.tsx b/src/components/Crax.tsx index 4378d9a..ae09183 100644 --- a/src/components/Crax.tsx +++ b/src/components/Crax.tsx @@ -21,7 +21,7 @@ const Crax = () => { }, []); return ( -
+
{eyeOpen ? "0_0" : ">_<"}
); diff --git a/src/components/Icon.tsx b/src/components/Icon.tsx index 2a1a60d..4de8467 100644 --- a/src/components/Icon.tsx +++ b/src/components/Icon.tsx @@ -1,12 +1,18 @@ import BookmarkIcon from "../assets/Icons/BookmarkIcon"; +import CheckIcon from "../assets/Icons/CheckIcon"; import CloseIcon from "../assets/Icons/CloseIcon"; +import DownIcon from "../assets/Icons/DownIcon"; import FilmIcon from "../assets/Icons/FilmIcon"; +import FolderAddIcon from "../assets/Icons/FolderAddIcon"; import FolderOpenIcon from "../assets/Icons/FolderOpenIcon"; import GearIcon from "../assets/Icons/GearIcon"; +import LeftIcon from "../assets/Icons/LeftIcon"; import MoreHorizontalIcon from "../assets/Icons/MoreHorizontalIcon"; import PlayIcon from "../assets/Icons/PlayIcon"; +import RightIcon from "../assets/Icons/RightIcon"; import SearchIcon from "../assets/Icons/SearchIcon"; import TvIcon from "../assets/Icons/TvIcon"; +import UpIcon from "../assets/Icons/UpIcon"; import UploadIcon from "../assets/Icons/UploadIcon"; const iconMap = { @@ -18,8 +24,14 @@ const iconMap = { moreHorizontal: MoreHorizontalIcon, upload: UploadIcon, folderOpen: FolderOpenIcon, + folderAdd: FolderAddIcon, gear: GearIcon, - tv: TvIcon + tv: TvIcon, + left: LeftIcon, + right: RightIcon, + up: UpIcon, + down: DownIcon, + check: CheckIcon, }; export type IconName = keyof typeof iconMap; diff --git a/src/components/inputs/Button.tsx b/src/components/inputs/Button.tsx index f210691..59625a6 100644 --- a/src/components/inputs/Button.tsx +++ b/src/components/inputs/Button.tsx @@ -2,25 +2,30 @@ import { VariantProps } from "class-variance-authority"; import buttonStyles from "../../styles/buttonStyles"; import Icon, { IconName } from "../Icon"; import { useNavigate } from "react-router-dom"; +import { ReactNode } from "react"; -export interface ButtonProps - extends React.ButtonHTMLAttributes, - VariantProps { +export type ButtonProps = VariantProps & { icon?: IconName; iconType?: "solid" | "outline"; to?: string; rounded?: boolean; -} + isIconLeft?: boolean; + fullWidth?: boolean; + className?: string; + children?: ReactNode; + onClick?: () => void; +}; const Button: React.FC = ({ className, variant, - title, size = "small", icon, iconType, to = "", rounded = false, + isIconLeft = false, + fullWidth, children, ...props }) => { @@ -28,23 +33,35 @@ const Button: React.FC = ({ return ( ); }; diff --git a/src/components/inputs/Switch.tsx b/src/components/inputs/Switch.tsx new file mode 100644 index 0000000..dc33dfa --- /dev/null +++ b/src/components/inputs/Switch.tsx @@ -0,0 +1,29 @@ +import { Switch as HUISwitch } from "@headlessui/react"; + +interface SwitchProps { + checked: boolean; + onChange: (checked: boolean) => void; + className?: string; + label?: string; +} + +const Switch = ({ checked, onChange, className, label }: SwitchProps) => { + return ( +
+ {label &&
{label}
} + + +
+ ); +}; + +export default Switch; diff --git a/src/components/setup/CollectionsTab.tsx b/src/components/setup/CollectionsTab.tsx deleted file mode 100644 index 4bf93de..0000000 --- a/src/components/setup/CollectionsTab.tsx +++ /dev/null @@ -1,226 +0,0 @@ -import { useState } from "react"; -import { motion } from "framer-motion"; -import { - Description, - Dialog, - DialogPanel, - DialogTitle, - Tab, - TabGroup, - TabList, - TabPanel, - TabPanels, -} from "@headlessui/react"; -import Crax from "../Crax"; -import Icon from "../Icon"; -import Button from "../inputs/Button"; -import TextInput from "../inputs/TextInput"; -import IconButton from "../inputs/IconButton"; - -const MediaTypeTabPanel = () => { - const [isOpen, setIsOpen] = useState(false); - const [folderPath, setFolderPath] = useState(""); - - const mediaTypes = [ - { id: "movie", label: "Movie", icon: "film" }, - { id: "tv", label: "TV Show", icon: "tv" }, - ]; - - const [selectedMediaType, setSelectedMediaType] = useState(mediaTypes[0]); - - const handleSelectFolderButton = async () => { - const result = await window.ipcRenderer.selectFolder(); - if (!result.canceled && result.filePaths.length > 0) { - setFolderPath(result.filePaths[0]); // Set the selected folder path - } - }; - - const handleSelectFolderInput = (e: any) => { - setFolderPath(e.target.value); - }; - - return ( - - {mediaTypes.map((mediaType) => ( - - ))} - - setIsOpen(false)} - className="relative z-50" - > -
- -
- - Add a new{" "} - - {selectedMediaType.label} - {" "} - collection - - - Enter the path to your media collection here. - -
- -
- -
- -
-
-
- - -
-
-
-
-
- ); -}; - -const FoldersTabPanel = () => { - return ( - -
-
-
My Awesome Collection
-
Path: /Users/Hello/Welcome/TO
-
-
- -
-
-
-
-
My Awesome Collection
-
Path: /Users/Hello/Welcome/TO
-
-
- -
-
-
-
-
My Awesome Collection
-
Path: /Users/Hello/Welcome/TO
-
-
- -
-
-
- ); -}; - -const AdvancedTabPanel = () => { - return Hello 2; -}; - -const CollectionsTab = () => { - return ( -
- - - - - {({ selected }) => ( - - -
Media Type
-
- )} -
- - {({ selected }) => ( - - -
Folders
-
- )} -
- - {({ selected }) => ( - - -
Advanced
-
- )} -
-
- - - - - -
-
- ); -}; - -export default CollectionsTab; diff --git a/src/components/setup/ExtrasTab.tsx b/src/components/setup/ExtrasTab.tsx deleted file mode 100644 index 0ec7439..0000000 --- a/src/components/setup/ExtrasTab.tsx +++ /dev/null @@ -1,5 +0,0 @@ -const ExtrasTab = () => { - return
Hello 3
; -}; - -export default ExtrasTab; diff --git a/src/components/setup/ServerTab.tsx b/src/components/setup/ServerTab.tsx deleted file mode 100644 index 83a87a3..0000000 --- a/src/components/setup/ServerTab.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import Crax from "../Crax"; -import Icon from "../Icon"; -import TextInput from "../inputs/TextInput"; - -const ServerTab = () => { - return ( -
- - -
OR
- -
- ); -}; - -export default ServerTab; diff --git a/src/contexts/ConfigContext.tsx b/src/contexts/ConfigContext.tsx index 57353cc..056f94b 100644 --- a/src/contexts/ConfigContext.tsx +++ b/src/contexts/ConfigContext.tsx @@ -1,7 +1,6 @@ import React, { createContext, useContext } from "react"; import { useTranslation } from "react-i18next"; -import config from "../config"; -import { Config } from "electron"; +import config, { Config } from "../config"; const ConfigContext = createContext(undefined); diff --git a/src/index.css b/src/index.css index 81ca5b5..f11b040 100644 --- a/src/index.css +++ b/src/index.css @@ -7,10 +7,10 @@ -webkit-app-region: drag; } -/* :root { +:root { --swiper-theme-color: #ffffff !important; --swiper-navigation-color: #ffffff !important; -} */ +} @layer base { body { @@ -47,155 +47,3 @@ @apply opacity-50 pointer-events-none; } } - -:root { - --color-bg1: rgb(0, 115, 255); - --color-bg2: rgb(0, 255, 170); - --color1: 18, 113, 255; - --color2: 221, 74, 255; - --color3: 100, 220, 255; - --color4: 200, 50, 50; - --color5: 180, 180, 50; - --color-interactive: 140, 100, 255; - --circle-size: 80%; - --blending: hard-light; -} - -@keyframes moveInCircle { - 0% { - transform: rotate(0deg); - } - 50% { - transform: rotate(180deg); - } - 100% { - transform: rotate(360deg); - } -} - -@keyframes moveVertical { - 0% { - transform: translateY(-50%); - } - 50% { - transform: translateY(50%); - } - 100% { - transform: translateY(-50%); - } -} - -@keyframes moveHorizontal { - 0% { - transform: translateX(-50%) translateY(-10%); - } - 50% { - transform: translateX(50%) translateY(10%); - } - 100% { - transform: translateX(-50%) translateY(-10%); - } -} - -.gradient-bg { - width: 100vw; - height: 100vh; - position: relative; - overflow: hidden; - background: linear-gradient(40deg, var(--color-bg1), var(--color-bg2)); - top: 0; - left: 0; -} -.gradient-bg svg { - display: none; -} -.gradient-bg .gradients-container { - filter: url(#goo) blur(40px); - width: 100%; - height: 100%; -} -.gradient-bg .g1 { - position: absolute; - background: radial-gradient( - circle at center, - rgba(var(--color1)) 0, - rgba(var(--color1)) 50% - ) - no-repeat; - mix-blend-mode: var(--blending); - width: var(--circle-size); - height: var(--circle-size); - top: calc(50% - var(--circle-size) / 2); - left: calc(50% - var(--circle-size) / 2); - transform-origin: center center; - animation: moveVertical 30s ease infinite; - opacity: 1; -} -.gradient-bg .g2 { - position: absolute; - background: radial-gradient( - circle at center, - rgba(var(--color2)) 0, - rgba(var(--color2)) 50% - ) - no-repeat; - mix-blend-mode: var(--blending); - width: var(--circle-size); - height: var(--circle-size); - top: calc(50% - var(--circle-size) / 2); - left: calc(50% - var(--circle-size) / 2); - transform-origin: calc(50% - 400px); - animation: moveInCircle 20s reverse infinite; - opacity: 1; -} -.gradient-bg .g3 { - position: absolute; - background: radial-gradient( - circle at center, - rgba(var(--color3)) 0, - rgba(var(--color3)) 50% - ) - no-repeat; - mix-blend-mode: var(--blending); - width: var(--circle-size); - height: var(--circle-size); - top: calc(50% - var(--circle-size) / 2 + 200px); - left: calc(50% - var(--circle-size) / 2 - 500px); - transform-origin: calc(50% + 400px); - animation: moveInCircle 40s linear infinite; - opacity: 1; -} -.gradient-bg .g4 { - position: absolute; - background: radial-gradient( - circle at center, - rgba(var(--color4)) 0, - rgba(var(--color4)) 50% - ) - no-repeat; - mix-blend-mode: var(--blending); - width: var(--circle-size); - height: var(--circle-size); - top: calc(50% - var(--circle-size) / 2); - left: calc(50% - var(--circle-size) / 2); - transform-origin: calc(50% - 200px); - animation: moveHorizontal 40s ease infinite; - opacity: 0.7; -} -.gradient-bg .g5 { - position: absolute; - background: radial-gradient( - circle at center, - rgba(var(--color5)) 0, - rgba(var(--color5)) 50% - ) - no-repeat; - mix-blend-mode: var(--blending); - width: calc(var(--circle-size) * 2); - height: calc(var(--circle-size) * 2); - top: calc(50% - var(--circle-size)); - left: calc(50% - var(--circle-size)); - transform-origin: calc(50% - 800px) calc(50% + 200px); - animation: moveInCircle 20s ease infinite; - opacity: 1; -} diff --git a/src/pages/setup/SetupTabs/CollectionsTab.tsx b/src/pages/setup/SetupTabs/CollectionsTab.tsx new file mode 100644 index 0000000..449ea79 --- /dev/null +++ b/src/pages/setup/SetupTabs/CollectionsTab.tsx @@ -0,0 +1,160 @@ +import { motion } from "framer-motion"; +import { + Listbox, + ListboxButton, + ListboxOption, + ListboxOptions, + Tab, + TabGroup, + TabList, + TabPanel, + TabPanels, +} from "@headlessui/react"; +import { useState } from "react"; +import Icon from "../../../components/Icon"; +import TextInput from "../../../components/inputs/TextInput"; +import Button from "../../../components/inputs/Button"; +import axios from "axios"; + +const NewCollectionSubTab = () => { + const mediaTypes = [ + { mediaType: "movie", label: "Movie", icon: "film" }, + { mediaType: "tv", label: "TV Show", icon: "tv" }, + ]; + + const [selected, setSelected] = useState(mediaTypes[0]); + + const postNewCollectionConfig = async (collectionsConfig: { + name: string; + path: string; + mediaType: "movie" | "tv"; + isAdult: boolean; + }) => { + const { data } = await axios.patch( + "http://localhost:8803/api/v1/config/collections", + collectionsConfig + ); + return data; + }; + + const [currentCollectionName, setCurrentCollectionName] = useState(""); + const [currentCollectionImage, setCurrentCollectionImage] = useState(""); + const [currentMediaType, setCurrentMediaType] = useState(""); + + return ( +
+
+ +
+ +
+
+ +
+
Media Type
+ + +
+ +
{selected.label}
+
+ +
+ + {mediaTypes.map((mediaType) => ( + +
{mediaType.label}
+
+ ))} +
+
+
+ +
+ ); +}; + +const CollectionsSubTab = () => { + return
Hello 2
; +}; + +const collectionTabsContent = [ + { + id: "newcollection", + title: "New Collection", + icon: "folderAdd", + tab: , + }, + { + id: "collections", + title: "Collections", + icon: "folderOpen", + tab: , + }, +]; + +const CollectionsTab = ({ config, handleBack, handleNext }: any) => { + const [selectedIndex, setSelectedIndex] = useState(0); + return ( +
+ + + {collectionTabsContent.map(({ id, title, icon }, index) => ( + + +
{title}
+
+ ))} +
+ + {collectionTabsContent.map(({ id, tab }) => ( + + {tab} + + ))} + +
+
+ + +
+
+ ); +}; + +export default CollectionsTab; diff --git a/src/pages/setup/SetupTabs/ExtrasTab.tsx b/src/pages/setup/SetupTabs/ExtrasTab.tsx new file mode 100644 index 0000000..b35ce3f --- /dev/null +++ b/src/pages/setup/SetupTabs/ExtrasTab.tsx @@ -0,0 +1,35 @@ +import Icon from "../../../components/Icon"; +import Switch from "../../../components/inputs/Switch"; + +const ExtrasTab = ({ config, handleBack, handleNext }: any) => { + return ( +
+
+ Homepage + +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ ); +}; + +export default ExtrasTab; diff --git a/src/pages/setup/SetupTabs/ServerTab.tsx b/src/pages/setup/SetupTabs/ServerTab.tsx new file mode 100644 index 0000000..85bb803 --- /dev/null +++ b/src/pages/setup/SetupTabs/ServerTab.tsx @@ -0,0 +1,75 @@ +import { useEffect, useState } from "react"; +import Icon from "../../../components/Icon"; +import TextInput from "../../../components/inputs/TextInput"; +import Button from "../../../components/inputs/Button"; +import axios from "axios"; +import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; + +const ServerTab = ({ handleBack, handleNext }: any) => { + const getServerConfig = async () => { + const { data } = await axios.get( + "http://localhost:8803/api/v1/config/server" + ); + return data; + }; + + const patchServerConfig = async (serverConfig: { name: string }) => { + const { data } = await axios.patch( + "http://localhost:8803/api/v1/config/server", + serverConfig + ); + return data; + }; + + const queryClient = useQueryClient(); + + const { data: server } = useQuery({ + queryKey: ["server"], + queryFn: getServerConfig, + }); + + const mutation = useMutation({ + mutationFn: patchServerConfig, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ["server"] }); + }, + }); + + const [serverName, setServerName] = useState(server?.name || ""); + + useEffect(() => { + if (server) { + setServerName(server.name); + } + }, [server]); + + const handleNextWithFn = async () => { + mutation.mutate({ name: serverName }); + handleNext(); + }; + + return ( +
+
+ setServerName(e.target.value)} + /> +
OR
+ +
+
+ +
+
+ ); +}; + +export default ServerTab; diff --git a/src/pages/setup/SetupTabs/UsersTab.tsx b/src/pages/setup/SetupTabs/UsersTab.tsx new file mode 100644 index 0000000..7e0d8c9 --- /dev/null +++ b/src/pages/setup/SetupTabs/UsersTab.tsx @@ -0,0 +1,73 @@ +import { useState } from "react"; +import Switch from "../../../components/inputs/Switch"; +import TextInput from "../../../components/inputs/TextInput"; +import Button from "../../../components/inputs/Button"; +import Icon from "../../../components/Icon"; + +const UsersTab = ({ config, handleBack, handleNext }: any) => { + const [profileImage, setProfileImage] = useState(""); + const [childAccount, setChildAccount] = useState(false); + const [passwordProtected, setPasswordProtected] = useState(false); + return ( +
+
+
+ {[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((item) => ( + + + ))} +
+
+ +
+ +
+
+ setPasswordProtected(checked)} + /> + {passwordProtected && ( +
+ + +
+ )} + setChildAccount(checked)} + /> + +
+
+ ); +}; + +export default UsersTab; diff --git a/src/components/setup/SetupTabs.tsx b/src/pages/setup/SetupTabs/index.tsx similarity index 50% rename from src/components/setup/SetupTabs.tsx rename to src/pages/setup/SetupTabs/index.tsx index 2dbef48..b4515c0 100644 --- a/src/components/setup/SetupTabs.tsx +++ b/src/pages/setup/SetupTabs/index.tsx @@ -1,31 +1,63 @@ -import { useState } from "react"; +import { ReactNode, useState } from "react"; import { motion } from "framer-motion"; import { Tab, TabGroup, TabList, TabPanel, TabPanels } from "@headlessui/react"; import CollectionsTab from "./CollectionsTab"; -import ExtrasTab from "./ExtrasTab"; import ServerTab from "./ServerTab"; -import Icon from "../Icon"; +import SetupTab from "./ExtrasTab"; +import Icon from "../../../components/Icon"; +import UsersTab from "./UsersTab"; -const setupTabsContent = [ + +interface SetupTabContent { + id: string; + title: string; + tab: (handleBack?: () => void, handleNext?: () => void) => ReactNode; +} + +const setupTabsContent: SetupTabContent[] = [ { id: "server", title: "Server", - tab: , + tab: (handleBack, handleNext) => ( + + ), }, { id: "collections", title: "Collections", - tab: , + tab: (handleBack, handleNext) => ( + + ), + }, + { + id: "users", + title: "Users", + tab: (handleBack, handleNext) => ( + + ), }, { id: "extras", title: "Extras", - tab: , + tab: (handleBack, handleNext) => , }, ]; const SetupTabs = ({ setIsOpen }: any) => { const [selectedIndex, setSelectedIndex] = useState(0); + + const handleNext = () => { + if (selectedIndex < setupTabsContent.length - 1) { + setSelectedIndex(selectedIndex + 1); + } + }; + + const handleBack = () => { + if (selectedIndex > 0) { + setSelectedIndex(selectedIndex - 1); + } + }; + return ( { onChange={setSelectedIndex} >
- + {setupTabsContent.map(({ id, title }, index) => ( {selectedIndex === index && ( )} @@ -52,20 +86,22 @@ const SetupTabs = ({ setIsOpen }: any) => { ))}
- + {setupTabsContent.map(({ id, tab }) => ( - {tab} + + {tab(handleBack, handleNext)} + ))}
diff --git a/src/pages/setup/WelcomePage.tsx b/src/pages/setup/WelcomePage.tsx index 0d58061..bc99dc1 100644 --- a/src/pages/setup/WelcomePage.tsx +++ b/src/pages/setup/WelcomePage.tsx @@ -1,7 +1,8 @@ import { AnimatePresence, motion } from "framer-motion"; import { useState } from "react"; import Logo from "../../components/Logo"; -import SetupTabs from "../../components/setup/SetupTabs"; +import SetupTabs from "./SetupTabs"; +import Icon from "../../components/Icon"; const WelcomePage = () => { const [isOpen, setIsOpen] = useState(false); @@ -79,7 +80,7 @@ const WelcomePage = () => { }, }, close: { - width: "130px", + width: "160px", height: "40px", transition: { type: "spring", @@ -95,10 +96,10 @@ const WelcomePage = () => { } : undefined } - className={`relative transition-colors text-black flex items-center justify-center ${ + className={`relative transition-colors group/wrapper text-black flex items-center justify-center bg-white ${ !isOpen - ? "mt-10 rounded-xl cursor-pointer bg-white" - : "cursor-default rounded-[20px] border bg-white/60" + ? "mt-10 rounded-xl cursor-pointer" + : "cursor-default rounded-3xl border" }`} onClick={!isOpen ? toggleOpen : undefined} > @@ -120,8 +121,11 @@ const WelcomePage = () => { ) : ( -
- Setup Dester +
+
Setup Dester
+
+ +
)} diff --git a/src/styles/buttonStyles.ts b/src/styles/buttonStyles.ts index b6d11dd..a50c8a9 100644 --- a/src/styles/buttonStyles.ts +++ b/src/styles/buttonStyles.ts @@ -5,29 +5,23 @@ const buttonStyles = cva( "font-semibold", "flex", "items-center", + "justify-center", "transition-colors", - "w-fit", "whitespace-nowrap", ], { variants: { variant: { - primary: [ - "bg-white", - "hover:bg-zinc-200", - "active:bg-zinc-400", - "text-black", - ], + primary: ["bg-white", "hover:bg-zinc-200", "text-black"], secondary: [ "bg-neutral-600/20", "hover:bg-neutral-600/40", - "active:bg-neutral-600/60", "text-white", "backdrop-blur-lg", "shadow-[inset_0_1px_0_0_#ffffff1a]", ], black: ["bg-black", "text-white"], - accent: ["bg-emerald-400", "text-white", "hover:bg-emerald-500"], + accent: ["bg-emerald-400", "hover:bg-emerald-500"], }, size: { small: ["text-sm", "px-1", "h-10"], @@ -36,6 +30,10 @@ const buttonStyles = cva( rounded: { true: "rounded-full", }, + fullWidth: { + true: "w-full", + flase: "w-fit", + }, }, compoundVariants: [ { @@ -52,6 +50,7 @@ const buttonStyles = cva( defaultVariants: { variant: "primary", size: "small", + fullWidth: false, }, } ); diff --git a/src/wrappers/SetupWrapper.tsx b/src/wrappers/SetupWrapper.tsx index 0752c96..6c26f75 100644 --- a/src/wrappers/SetupWrapper.tsx +++ b/src/wrappers/SetupWrapper.tsx @@ -5,33 +5,6 @@ const SetupWrapper = () => { return (
- {/*
- - - - - - - - - -
-
-
-
-
-
-
-
*/}