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 { useState } from "react"
|
||||||
import Link from "next/link"
|
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 Navbar = () => {
|
||||||
const [isOpen, setIsOpen] = useState(false)
|
const [isOpen, setIsOpen] = useState(false)
|
||||||
@ -19,17 +19,23 @@ const Navbar = () => {
|
|||||||
<div className="hidden md:block">
|
<div className="hidden md:block">
|
||||||
<div className="ml-10 flex items-center space-x-4">
|
<div className="ml-10 flex items-center space-x-4">
|
||||||
<Link
|
<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"
|
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
|
<Home className="mr-2 h-5 w-5" /> Home
|
||||||
</Link>
|
</Link>
|
||||||
<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"
|
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
|
<Server className="mr-2 h-5 w-5" /> Services
|
||||||
</Link>
|
</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>
|
</div>
|
||||||
<div className="md:hidden">
|
<div className="md:hidden">
|
||||||
@ -64,6 +70,12 @@ const Navbar = () => {
|
|||||||
>
|
>
|
||||||
<Server className="mr-2 h-5 w-5" /> Services
|
<Server className="mr-2 h-5 w-5" /> Services
|
||||||
</Link>
|
</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>
|
||||||
</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 Head from "next/head"
|
||||||
import { Inter } from "next/font/google"
|
import { Inter } from "next/font/google"
|
||||||
import Navbar from "../app/components/Navbar"
|
import Navbar from "../app/components/Navbar"
|
||||||
|
import "@radix-ui/themes/styles.css";
|
||||||
|
|
||||||
const inter = Inter({ subsets: ["latin"] })
|
const inter = Inter({ subsets: ["latin"] })
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/react-slot": "^1.1.1",
|
"@radix-ui/react-slot": "^1.1.1",
|
||||||
|
"@radix-ui/themes": "^3.2.0",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"lucide-react": "^0.474.0",
|
"lucide-react": "^0.474.0",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user