self-service read only ui
This commit is contained in:
parent
685c928d2c
commit
fc6a2523f0
|
@ -1,5 +1,4 @@
|
||||||
import type { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
import { Inter } from 'next/font/google';
|
|
||||||
import ThemeWrapper from '@/lib/components/ThemeWrapper';
|
import ThemeWrapper from '@/lib/components/ThemeWrapper';
|
||||||
import './globals.css';
|
import './globals.css';
|
||||||
import AuthWrapper from '@/lib/components/AuthWrapper';
|
import AuthWrapper from '@/lib/components/AuthWrapper';
|
||||||
|
@ -7,8 +6,6 @@ import { getServerSession } from 'next-auth';
|
||||||
import NavigationPanel from '@/lib/components/ui/NavigationPanel';
|
import NavigationPanel from '@/lib/components/ui/NavigationPanel';
|
||||||
import { Flex } from '@radix-ui/themes';
|
import { Flex } from '@radix-ui/themes';
|
||||||
|
|
||||||
const inter = Inter({ subsets: ['latin'] });
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: 'Create Next App',
|
title: 'Create Next App',
|
||||||
description: 'Generated by create next app',
|
description: 'Generated by create next app',
|
||||||
|
@ -21,7 +18,7 @@ export default async function RootLayout({
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<body className={`${inter.className} p-4`}>
|
<body className={`p-4`}>
|
||||||
<ThemeWrapper>
|
<ThemeWrapper>
|
||||||
<AuthWrapper session={await getServerSession()}>
|
<AuthWrapper session={await getServerSession()}>
|
||||||
<Flex direction='row' gap='4'>
|
<Flex direction='row' gap='4'>
|
||||||
|
|
122
src/app/self-service/page.tsx
Normal file
122
src/app/self-service/page.tsx
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Card, Text, Heading, Flex, TextField, Button, IconButton, Popover, Link, Tabs, Box, Grid } from "@radix-ui/themes";
|
||||||
|
import { CheckIcon, CopyIcon, InfoIcon, LockIcon, UserIcon } from "lucide-react";
|
||||||
|
import { useSession } from "next-auth/react";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
// TODO read these from environment
|
||||||
|
const EMAIL_HOST = "mx1.amogus.cloud";
|
||||||
|
const SMTP_PORT = "465";
|
||||||
|
const IMAP_PORT = "993";
|
||||||
|
const SMTP_SECURITY = "SSL/TLS";
|
||||||
|
const IMAP_SECURITY = "SSL/TLS";
|
||||||
|
|
||||||
|
export default function SelfService() {
|
||||||
|
const session = useSession().data;
|
||||||
|
|
||||||
|
function StaticValueField({ label, value }: { label: string, value: string }) {
|
||||||
|
const [checked, setChecked] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Text weight="light" size="2">{label}</Text>
|
||||||
|
<TextField.Root>
|
||||||
|
<TextField.Input disabled value={value} />
|
||||||
|
<TextField.Slot>
|
||||||
|
<IconButton
|
||||||
|
size="1"
|
||||||
|
variant="ghost"
|
||||||
|
onClick={() => {
|
||||||
|
navigator.clipboard.writeText(value);
|
||||||
|
setChecked(true);
|
||||||
|
setTimeout(() => setChecked(false), 1000);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{checked
|
||||||
|
? <CheckIcon width={16} height={16} />
|
||||||
|
: <CopyIcon width={16} height={16} />
|
||||||
|
}
|
||||||
|
</IconButton>
|
||||||
|
</TextField.Slot>
|
||||||
|
</TextField.Root>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Heading className="pb-4">Account settings</Heading>
|
||||||
|
|
||||||
|
<Grid display="inline-grid" rows="1" columns="2" gap="4">
|
||||||
|
<Card className="h-fit">
|
||||||
|
<Heading size="3">Credentials</Heading>
|
||||||
|
<Text weight="light" size="2">These are the details you can use to authenticate via SMTP and IMAP.</Text>
|
||||||
|
|
||||||
|
<Flex direction="column" gap="3" className="pt-2">
|
||||||
|
<TextField.Root>
|
||||||
|
<TextField.Slot>
|
||||||
|
<UserIcon height="16" width="16" />
|
||||||
|
</TextField.Slot>
|
||||||
|
<TextField.Input disabled value={session?.user?.email ?? 'n/a'} />
|
||||||
|
<TextField.Slot>
|
||||||
|
<Popover.Root>
|
||||||
|
<Popover.Trigger>
|
||||||
|
<IconButton asChild size="1" variant="ghost">
|
||||||
|
<InfoIcon height="16" width="16" />
|
||||||
|
</IconButton>
|
||||||
|
</Popover.Trigger>
|
||||||
|
<Popover.Content className="w-96">
|
||||||
|
<Text>
|
||||||
|
Your username uniquely identifies your account and therefore cannot be changed. If you need a different email address, you can <Link onClick={() => alert("todo")}>request an alias</Link> instead.
|
||||||
|
</Text>
|
||||||
|
</Popover.Content>
|
||||||
|
</Popover.Root>
|
||||||
|
</TextField.Slot>
|
||||||
|
</TextField.Root>
|
||||||
|
|
||||||
|
<Flex direction="row" gap="3">
|
||||||
|
<TextField.Root className="flex-1">
|
||||||
|
<TextField.Slot>
|
||||||
|
<LockIcon height="16" width="16" />
|
||||||
|
</TextField.Slot>
|
||||||
|
<TextField.Input disabled value={"\u25CF".repeat(10)} />
|
||||||
|
</TextField.Root>
|
||||||
|
|
||||||
|
<Button variant="outline">
|
||||||
|
Change
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card className="h-fit">
|
||||||
|
<Heading size="3">Server configuration</Heading>
|
||||||
|
<Text weight="light" size="2">You can use these details to log in using any mail client.</Text>
|
||||||
|
|
||||||
|
<Box pt="2">
|
||||||
|
<Tabs.Root defaultValue="smtp">
|
||||||
|
<Tabs.List size="2">
|
||||||
|
<Tabs.Trigger value="smtp">Outgoing</Tabs.Trigger>
|
||||||
|
<Tabs.Trigger value="imap">Incoming</Tabs.Trigger>
|
||||||
|
</Tabs.List>
|
||||||
|
|
||||||
|
<Box pt="3" pb="2">
|
||||||
|
<Tabs.Content value="smtp">
|
||||||
|
<StaticValueField label="SMTP Server" value={EMAIL_HOST} />
|
||||||
|
<StaticValueField label="SMTP Port" value={SMTP_PORT} />
|
||||||
|
<StaticValueField label="Connection security" value={SMTP_SECURITY} />
|
||||||
|
</Tabs.Content>
|
||||||
|
<Tabs.Content value="imap">
|
||||||
|
<StaticValueField label="IMAP Server" value={EMAIL_HOST} />
|
||||||
|
<StaticValueField label="IMAP Port" value={IMAP_PORT} />
|
||||||
|
<StaticValueField label="Connection security" value={IMAP_SECURITY} />
|
||||||
|
</Tabs.Content>
|
||||||
|
</Box>
|
||||||
|
</Tabs.Root>
|
||||||
|
</Box>
|
||||||
|
</Card>
|
||||||
|
</Grid>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
|
@ -40,7 +40,9 @@ export default function NavigationPanel() {
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Flex gap='2' direction='row' justify='end'>
|
<Flex gap='2' direction='row' justify='end'>
|
||||||
<Button variant="soft">Account</Button>
|
<Link href="/self-service">
|
||||||
|
<Button variant="soft">Account</Button>
|
||||||
|
</Link>
|
||||||
<Button variant="surface" onClick={() => signOut()}>Log out</Button>
|
<Button variant="surface" onClick={() => signOut()}>Log out</Button>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
Loading…
Reference in a new issue