add account frontend elements w/ sample
All checks were successful
Build and Push Docker Image / build_and_push (push) Successful in 6m11s
All checks were successful
Build and Push Docker Image / build_and_push (push) Successful in 6m11s
This commit is contained in:
parent
1ac3dd8e28
commit
a8f4de04b4
106
app/account/dashboard/page.tsx
Normal file
106
app/account/dashboard/page.tsx
Normal file
@ -0,0 +1,106 @@
|
||||
"use client"
|
||||
|
||||
import { useState } from "react"
|
||||
import { Flex, Text, Card, Progress, Grid, Box } from "@radix-ui/themes"
|
||||
import { Mail, GitBranch, Music, Key, CheckCircle, XCircle } from "lucide-react"
|
||||
import Sidebar from "../../components/account/Sidebar"
|
||||
|
||||
export default function Dashboard() {
|
||||
const [diskUsage, setDiskUsage] = useState(75)
|
||||
|
||||
return (
|
||||
<Flex>
|
||||
<Sidebar />
|
||||
<Flex direction="column" className="flex-1 p-8">
|
||||
<Text size="8" weight="bold" className="mb-6">
|
||||
Dashboard
|
||||
</Text>
|
||||
<Grid columns="2" gap="4">
|
||||
<Card className="p-6">
|
||||
<Text size="6" weight="bold" className="mb-4">
|
||||
Disk Usage
|
||||
</Text>
|
||||
<Flex direction="column" gap="2" className="mt-8">
|
||||
<Progress value={diskUsage} />
|
||||
<Text>{diskUsage}% of 100GB used</Text>
|
||||
</Flex>
|
||||
</Card>
|
||||
|
||||
<Card className="p-6">
|
||||
<Text size="6" weight="bold" className="mb-4">
|
||||
Account Security
|
||||
</Text>
|
||||
<Flex direction="column" gap="2" className="mt-3">
|
||||
<Flex align="center" gap="2">
|
||||
<CheckCircle className="text-green-500" />
|
||||
<Text>Spam Protection</Text>
|
||||
</Flex>
|
||||
<Flex align="center" gap="2">
|
||||
<XCircle className="text-red-500" />
|
||||
<Text>Two-Factor Authentication</Text>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Card>
|
||||
|
||||
<Card className="p-6">
|
||||
<Text size="6" weight="bold" className="mb-4">
|
||||
Services
|
||||
</Text>
|
||||
<Grid columns="2" gap="4" className="mt-4">
|
||||
<Flex align="center" gap="2">
|
||||
<Mail className="text-blue-500" />
|
||||
<Text>Mail</Text>
|
||||
</Flex>
|
||||
<Flex align="center" gap="2">
|
||||
<GitBranch className="text-purple-500" />
|
||||
<Text>Git</Text>
|
||||
</Flex>
|
||||
<Flex align="center" gap="2">
|
||||
<Music className="text-green-500" />
|
||||
<Text>Music</Text>
|
||||
</Flex>
|
||||
<Flex align="center" gap="2">
|
||||
<Key className="text-yellow-500" />
|
||||
<Text>Password Manager</Text>
|
||||
</Flex>
|
||||
</Grid>
|
||||
</Card>
|
||||
|
||||
<Card className="p-6">
|
||||
<Text size="6" weight="bold" className="mb-4">
|
||||
Linked Accounts
|
||||
</Text>
|
||||
<Flex direction="column" gap="2" className="mt-6">
|
||||
<Flex align="center" gap="2">
|
||||
<Box className="w-4 h-4 rounded-full bg-green-500" />
|
||||
<Text>p0ntus mail</Text>
|
||||
</Flex>
|
||||
<Flex align="center" gap="2">
|
||||
<Box className="w-4 h-4 rounded-full bg-green-500" />
|
||||
<Text>LibreCloud Git</Text>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Card>
|
||||
|
||||
<Card className="p-6">
|
||||
<Text size="6" weight="bold" className="mb-4">
|
||||
LibreCloud Git
|
||||
</Text>
|
||||
<Flex align="center" gap="4" className="mt-4">
|
||||
<Box className="w-16 h-16 rounded-full bg-gray-700 flex items-center justify-center">
|
||||
|
||||
</Box>
|
||||
<Flex direction="column" gap="1">
|
||||
<Text size="5" weight="bold">
|
||||
username
|
||||
</Text>
|
||||
<Text>12 repositories</Text>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Card>
|
||||
</Grid>
|
||||
</Flex>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
15
app/account/layout.tsx
Normal file
15
app/account/layout.tsx
Normal file
@ -0,0 +1,15 @@
|
||||
import { Theme } from "@radix-ui/themes"
|
||||
import "@radix-ui/themes/styles.css"
|
||||
|
||||
export default function AccountLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<Theme appearance="dark" accentColor="blue" grayColor="slate">
|
||||
<div className="min-h-screen bg-gray-900">{children}</div>
|
||||
</Theme>
|
||||
)
|
||||
}
|
||||
|
60
app/account/login/page.tsx
Normal file
60
app/account/login/page.tsx
Normal file
@ -0,0 +1,60 @@
|
||||
"use client"
|
||||
|
||||
import Link from "next/link"
|
||||
import { useState } from "react"
|
||||
import { TextField, Button, Flex, Text, Card } from "@radix-ui/themes"
|
||||
import { Mail, Lock } from "lucide-react"
|
||||
|
||||
export default function Login() {
|
||||
const [email, setEmail] = useState("")
|
||||
const [password, setPassword] = useState("")
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
}
|
||||
|
||||
return (
|
||||
<Flex className="h-screen" align="center" justify="center">
|
||||
<Card className="w-full max-w-md p-6">
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Text size="5" weight="bold">
|
||||
Log in to your account
|
||||
</Text>
|
||||
<Flex direction="column" gap="4" className="mt-6">
|
||||
<TextField.Root
|
||||
placeholder="Email"
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setEmail(e.target.value)}
|
||||
required
|
||||
>
|
||||
<TextField.Slot>
|
||||
<Mail height="16" width="16" />
|
||||
</TextField.Slot>
|
||||
</TextField.Root>
|
||||
<TextField.Root
|
||||
placeholder="Password"
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setPassword(e.target.value)}
|
||||
className="mb-3"
|
||||
required
|
||||
>
|
||||
<TextField.Slot>
|
||||
<Lock height="16" width="16" />
|
||||
</TextField.Slot>
|
||||
</TextField.Root>
|
||||
<Button color="gray" variant="outline" type="submit" highContrast>Log in</Button>
|
||||
<Link
|
||||
href="https://user.pontusmail.org/admin/user/signup"
|
||||
className="text-sm underline text-center"
|
||||
>
|
||||
I don't have an account
|
||||
</Link>
|
||||
</Flex>
|
||||
</form>
|
||||
</Card>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
25
app/account/logout/page.tsx
Normal file
25
app/account/logout/page.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
"use client"
|
||||
|
||||
import { useEffect } from "react"
|
||||
import { Flex, Text, Spinner } from "@radix-ui/themes"
|
||||
import { useRouter } from "next/navigation"
|
||||
|
||||
export default function Logout() {
|
||||
const router = useRouter()
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
router.push("/account/login")
|
||||
}, 5000)
|
||||
|
||||
return () => clearTimeout(timer)
|
||||
}, [router])
|
||||
|
||||
return (
|
||||
<Flex direction="column" justify="center" align="center" className="h-screen" gap="4">
|
||||
<Spinner size="3" />
|
||||
<Text size="5">Logging out...</Text>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
38
app/account/settings/page.tsx
Normal file
38
app/account/settings/page.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
"use client"
|
||||
|
||||
import { useState } from "react"
|
||||
import { Flex, Text, Switch, Button } from "@radix-ui/themes"
|
||||
import Sidebar from "../../components/account/Sidebar"
|
||||
|
||||
export default function Settings() {
|
||||
const [darkMode, setDarkMode] = useState(true)
|
||||
const [notifications, setNotifications] = useState(true)
|
||||
|
||||
return (
|
||||
<Flex>
|
||||
<Sidebar />
|
||||
<Flex direction="column" className="flex-1 p-8">
|
||||
<Text size="8" weight="bold" className="mb-6">
|
||||
Settings
|
||||
</Text>
|
||||
<Flex direction="column" gap="4" className="mt-4" style={{ maxWidth: "500px" }}>
|
||||
<Flex justify="between" align="center">
|
||||
<Text size="4">Dark Mode</Text>
|
||||
<Switch checked={darkMode} onCheckedChange={setDarkMode} />
|
||||
</Flex>
|
||||
<Flex justify="between" align="center" className="mb-4">
|
||||
<Text size="4">Enable Notifications</Text>
|
||||
<Switch checked={notifications} onCheckedChange={setNotifications} />
|
||||
</Flex>
|
||||
<Flex justify="center" gap="4" align="center">
|
||||
<Button>Save Changes</Button>
|
||||
<Button color="gray" variant="outline" highContrast>
|
||||
Go Back
|
||||
</Button>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
import { useState } from "react"
|
||||
import Link from "next/link"
|
||||
import { Menu, X, Server, Home } from "lucide-react"
|
||||
import { Menu, X, Server, Home, User } from "lucide-react"
|
||||
|
||||
const Navbar = () => {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
@ -19,17 +19,23 @@ const Navbar = () => {
|
||||
<div className="hidden md:block">
|
||||
<div className="ml-10 flex items-center space-x-4">
|
||||
<Link
|
||||
href="#"
|
||||
href="/"
|
||||
className="flex items-center text-gray-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium"
|
||||
>
|
||||
<Home className="mr-2 h-5 w-5" /> Home
|
||||
</Link>
|
||||
<Link
|
||||
href="#services"
|
||||
href="/#services"
|
||||
className="flex items-center text-gray-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium"
|
||||
>
|
||||
<Server className="mr-2 h-5 w-5" /> Services
|
||||
</Link>
|
||||
<Link
|
||||
href="/account"
|
||||
className="flex items-center text-gray-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium"
|
||||
>
|
||||
<User className="mr-2 h-5 w-5" /> My Account
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<div className="md:hidden">
|
||||
@ -64,6 +70,12 @@ const Navbar = () => {
|
||||
>
|
||||
<Server className="mr-2 h-5 w-5" /> Services
|
||||
</Link>
|
||||
<Link
|
||||
href="/account"
|
||||
className="flex items-center text-gray-300 hover:bg-gray-700 hover:text-white block px-3 py-2 rounded-md text-base font-medium"
|
||||
>
|
||||
<User className="mr-2 h-5 w-5" /> My Account
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
38
app/components/account/Sidebar.tsx
Normal file
38
app/components/account/Sidebar.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
import Link from "next/link"
|
||||
import { Cog, LogOut, Gauge } from "lucide-react"
|
||||
import { Flex, Card } from "@radix-ui/themes"
|
||||
import { usePathname } from "next/navigation"
|
||||
|
||||
const Sidebar = () => {
|
||||
const pathname = usePathname()
|
||||
|
||||
const navItems = [
|
||||
{ href: "/account/dashboard", icon: Gauge, label: "Dashboard" },
|
||||
{ href: "/account/settings", icon: Cog, label: "Settings" },
|
||||
{ href: "/account/logout", icon: LogOut, label: "Logout" },
|
||||
]
|
||||
|
||||
return (
|
||||
<Card className="w-64 h-screen bg-gray-800 p-4">
|
||||
<Flex direction="column" gap="2">
|
||||
{navItems.map((item) => (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
className={`
|
||||
flex items-center px-4 py-2 rounded-md text-white
|
||||
transition-colors duration-200
|
||||
${pathname === item.href ? "bg-blue-600 hover:bg-blue-700" : "hover:bg-gray-700"}
|
||||
`}
|
||||
>
|
||||
<item.icon className="w-5 h-5 mr-3" />
|
||||
<span className="text-sm font-medium">{item.label}</span>
|
||||
</Link>
|
||||
))}
|
||||
</Flex>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default Sidebar
|
||||
|
@ -3,6 +3,7 @@ import type { Metadata } from "next"
|
||||
import Head from "next/head"
|
||||
import { Inter } from "next/font/google"
|
||||
import Navbar from "../app/components/Navbar"
|
||||
import "@radix-ui/themes/styles.css";
|
||||
|
||||
const inter = Inter({ subsets: ["latin"] })
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@radix-ui/react-slot": "^1.1.1",
|
||||
"@radix-ui/themes": "^3.2.0",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"lucide-react": "^0.474.0",
|
||||
|
Loading…
x
Reference in New Issue
Block a user