minimal dashboard
This commit is contained in:
@@ -10,9 +10,13 @@ import { generateUrlSafeString } from '@/utils';
|
||||
// Email doesn't exist
|
||||
// Password is between 6-20 characters
|
||||
export async function POST(req: NextRequest) {
|
||||
const { email, password } = await req.json();
|
||||
const { email, password, name } = await req.json();
|
||||
|
||||
if (typeof email !== 'string' || typeof password !== 'string')
|
||||
if (
|
||||
typeof email !== 'string' ||
|
||||
typeof password !== 'string' ||
|
||||
typeof name !== 'string'
|
||||
)
|
||||
return NextResponse.json(
|
||||
{
|
||||
message:
|
||||
@@ -29,18 +33,17 @@ export async function POST(req: NextRequest) {
|
||||
{ status: 409 }
|
||||
);
|
||||
|
||||
await database.users.insertOne({ email, password });
|
||||
await database.users.insertOne({ email, password, name });
|
||||
|
||||
const response = NextResponse.json(
|
||||
const sessionId = (await database.sessions.insertOne({ email })).insertedId;
|
||||
|
||||
return NextResponse.json(
|
||||
{
|
||||
message: 'ok',
|
||||
sessionId,
|
||||
},
|
||||
{ status: 200 }
|
||||
);
|
||||
|
||||
response.cookies.set('session_id', generateUrlSafeString(16));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Account login
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import Engagement from '@/components/engagement';
|
||||
import { Calendar } from '@/components/ui/calendar';
|
||||
|
||||
import {
|
||||
SidebarProvider,
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
} from '@/components/ui/sidebar';
|
||||
import { DayPicker } from 'react-day-picker';
|
||||
|
||||
export default function Dashboard() {
|
||||
return (
|
||||
<div className="flex w-full">
|
||||
<div>
|
||||
<SidebarProvider>
|
||||
<Sidebar className="w-64 h-full">
|
||||
<SidebarContent className="p-6">Hello</SidebarContent>
|
||||
</Sidebar>
|
||||
</SidebarProvider>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-1 flex-col p-6 px-10 h-max">
|
||||
<div className="w-full">
|
||||
<h1 className="text-3xl font-bold">Dashboard</h1>
|
||||
</div>
|
||||
|
||||
<div className="w-full mt-5 flex flex-col xl:flex-row gap-5 items-stretch">
|
||||
<Engagement />
|
||||
<div className="w-full pb-7 border rounded-2xl">
|
||||
<Calendar
|
||||
className="h-full w-full flex"
|
||||
classNames={{
|
||||
months: 'flex w-full flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0 flex-1',
|
||||
month: 'space-y-4 w-full flex flex-col',
|
||||
table: 'w-full h-full border-collapse space-y-1',
|
||||
head_row: '',
|
||||
row: 'w-full mt-2',
|
||||
day: 'px-1 py-2 rounded-xl text-xl',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
+61
-60
@@ -3,70 +3,71 @@
|
||||
@tailwind utilities;
|
||||
|
||||
body {
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 0 0% 3.9%;
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 0 0% 3.9%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 0 0% 3.9%;
|
||||
--primary: 0 0% 9%;
|
||||
--primary-foreground: 0 0% 98%;
|
||||
--secondary: 0 0% 96.1%;
|
||||
--secondary-foreground: 0 0% 9%;
|
||||
--muted: 0 0% 96.1%;
|
||||
--muted-foreground: 0 0% 45.1%;
|
||||
--accent: 0 0% 96.1%;
|
||||
--accent-foreground: 0 0% 9%;
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 0 0% 89.8%;
|
||||
--input: 0 0% 89.8%;
|
||||
--ring: 0 0% 3.9%;
|
||||
--chart-1: 12 76% 61%;
|
||||
--chart-2: 173 58% 39%;
|
||||
--chart-3: 197 37% 24%;
|
||||
--chart-4: 43 74% 66%;
|
||||
--chart-5: 27 87% 67%;
|
||||
--radius: 0.5rem;
|
||||
}
|
||||
.dark {
|
||||
--background: 0 0% 3.9%;
|
||||
--foreground: 0 0% 98%;
|
||||
--card: 0 0% 3.9%;
|
||||
--card-foreground: 0 0% 98%;
|
||||
--popover: 0 0% 3.9%;
|
||||
--popover-foreground: 0 0% 98%;
|
||||
--primary: 0 0% 98%;
|
||||
--primary-foreground: 0 0% 9%;
|
||||
--secondary: 0 0% 14.9%;
|
||||
--secondary-foreground: 0 0% 98%;
|
||||
--muted: 0 0% 14.9%;
|
||||
--muted-foreground: 0 0% 63.9%;
|
||||
--accent: 0 0% 14.9%;
|
||||
--accent-foreground: 0 0% 98%;
|
||||
--destructive: 0 62.8% 30.6%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 0 0% 14.9%;
|
||||
--input: 0 0% 14.9%;
|
||||
--ring: 0 0% 83.1%;
|
||||
--chart-1: 220 70% 50%;
|
||||
--chart-2: 160 60% 45%;
|
||||
--chart-3: 30 80% 55%;
|
||||
--chart-4: 280 65% 60%;
|
||||
--chart-5: 340 75% 55%;
|
||||
}
|
||||
:root {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 0 0% 3.9%;
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 0 0% 3.9%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 0 0% 3.9%;
|
||||
--primary: 0 72.2% 50.6%;
|
||||
--primary-foreground: 0 85.7% 97.3%;
|
||||
--secondary: 0 0% 96.1%;
|
||||
--secondary-foreground: 0 0% 9%;
|
||||
--muted: 0 0% 96.1%;
|
||||
--muted-foreground: 0 0% 45.1%;
|
||||
--accent: 0 0% 96.1%;
|
||||
--accent-foreground: 0 0% 9%;
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 0 0% 89.8%;
|
||||
--input: 0 0% 89.8%;
|
||||
--ring: 0 72.2% 50.6%;
|
||||
--radius: 0.5rem;
|
||||
--chart-1: 12 76% 61%;
|
||||
--chart-2: 173 58% 39%;
|
||||
--chart-3: 197 37% 24%;
|
||||
--chart-4: 43 74% 66%;
|
||||
--chart-5: 27 87% 67%;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: 0 0% 3.9%;
|
||||
--foreground: 0 0% 98%;
|
||||
--card: 0 0% 3.9%;
|
||||
--card-foreground: 0 0% 98%;
|
||||
--popover: 0 0% 3.9%;
|
||||
--popover-foreground: 0 0% 98%;
|
||||
--primary: 0 72.2% 50.6%;
|
||||
--primary-foreground: 0 85.7% 97.3%;
|
||||
--secondary: 0 0% 14.9%;
|
||||
--secondary-foreground: 0 0% 98%;
|
||||
--muted: 0 0% 14.9%;
|
||||
--muted-foreground: 0 0% 63.9%;
|
||||
--accent: 0 0% 14.9%;
|
||||
--accent-foreground: 0 0% 98%;
|
||||
--destructive: 0 62.8% 30.6%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 0 0% 14.9%;
|
||||
--input: 0 0% 14.9%;
|
||||
--ring: 0 72.2% 50.6%;
|
||||
--chart-1: 220 70% 50%;
|
||||
--chart-2: 160 60% 45%;
|
||||
--chart-3: 30 80% 55%;
|
||||
--chart-4: 280 65% 60%;
|
||||
--chart-5: 340 75% 55%;
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
* {
|
||||
@apply border-border;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
}
|
||||
|
||||
+45
-1
@@ -1,5 +1,49 @@
|
||||
'use client';
|
||||
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import Link from 'next/link';
|
||||
|
||||
export default function Login() {
|
||||
return <div className="bg-[#ccc] w-1/2 h-screen ml-auto"></div>;
|
||||
return (
|
||||
// <div className="bg-white dark:bg-black w-[46%] h-screen ml-auto">
|
||||
<div className="bg-white dark:bg-black w-full h-screen flex justify-center items-center">
|
||||
<div className="text-center">
|
||||
<div className="pb-5">
|
||||
<h1 className="text-xl pb-2">Log in to your account</h1>
|
||||
<Label className="text-sm text-muted-foreground">
|
||||
Enter your credentials below to access your account
|
||||
</Label>
|
||||
<Input
|
||||
className="w-80 mt-5 mx-auto"
|
||||
type="email"
|
||||
placeholder="[email protected]"
|
||||
/>
|
||||
|
||||
<Input
|
||||
className="w-80 mt-5 mx-auto"
|
||||
type="password"
|
||||
placeholder="Your password"
|
||||
/>
|
||||
|
||||
<Button className="mt-5 w-80 mx-auto">Log in</Button>
|
||||
</div>
|
||||
<div className="w-72 mx-auto">
|
||||
<Label className="mt-3 text-sm text-muted-foreground break-words">
|
||||
By clicking continue, you agree to our{' '}
|
||||
<Link href="/terms" className="underline">
|
||||
Terms of Service
|
||||
</Link>{' '}
|
||||
{'and '}
|
||||
<Link href="/privacy" className="underline">
|
||||
Privacy Policy
|
||||
</Link>
|
||||
.
|
||||
</Label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
// </div>
|
||||
);
|
||||
}
|
||||
|
||||
+12
-7
@@ -1,9 +1,14 @@
|
||||
'use client';
|
||||
import { cookies } from 'next/headers';
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div>
|
||||
<h1 className="text-2xl">The ultimate social media manager</h1>
|
||||
</div>
|
||||
);
|
||||
import { redirect } from 'next/navigation';
|
||||
|
||||
export default async function Home() {
|
||||
const cookieStore = await cookies();
|
||||
const sessionId = cookieStore.get('session_id');
|
||||
if (sessionId) {
|
||||
redirect('/dashboard');
|
||||
} else {
|
||||
redirect('/login');
|
||||
}
|
||||
return 'redirecting...';
|
||||
}
|
||||
|
||||
+38
-2
@@ -4,8 +4,16 @@ import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import Link from 'next/link';
|
||||
import { useState } from 'react';
|
||||
import axios from 'axios';
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
export default function SignUp() {
|
||||
const [name, setName] = useState('');
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
// <div className="bg-white dark:bg-black w-[46%] h-screen ml-auto">
|
||||
<div className="bg-white dark:bg-black w-full h-screen flex justify-center items-center">
|
||||
@@ -18,22 +26,50 @@ export default function SignUp() {
|
||||
<Input
|
||||
className="w-80 mt-6 mx-auto"
|
||||
placeholder="Full name"
|
||||
onChange={(event) => setName(event.target.value)}
|
||||
/>
|
||||
|
||||
<Input
|
||||
className="w-80 mt-5 mx-auto"
|
||||
type="email"
|
||||
placeholder="[email protected]"
|
||||
onChange={(event) => setEmail(event.target.value)}
|
||||
/>
|
||||
|
||||
<Input
|
||||
className="w-80 mt-5 mx-auto"
|
||||
type="password"
|
||||
placeholder="Enter a password"
|
||||
onChange={(event) => setPassword(event.target.value)}
|
||||
/>
|
||||
|
||||
<Button className="mt-5 w-80 mx-auto">
|
||||
Sign in with Email
|
||||
<Button
|
||||
className="mt-5 w-80 mx-auto"
|
||||
onClick={() => {
|
||||
console.log('Name:', name);
|
||||
console.log('Email:', email);
|
||||
console.log('Password:', password);
|
||||
|
||||
axios
|
||||
.post('/api/account/', {
|
||||
name,
|
||||
email,
|
||||
password,
|
||||
})
|
||||
.then(async (response) => {
|
||||
document.cookie = `session_id=${response.data.sessionId}`;
|
||||
console.log(
|
||||
'Account created with session',
|
||||
response.data
|
||||
);
|
||||
router.push('/dashboard');
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}}
|
||||
>
|
||||
Create account
|
||||
</Button>
|
||||
</div>
|
||||
<div className="w-72 mx-auto">
|
||||
|
||||
Reference in New Issue
Block a user