Clean up the UI. Boring easy stuff honestly
This commit is contained in:
parent
329ee9dc0a
commit
f5e3cb6234
@ -21,6 +21,7 @@
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.6",
|
||||
"@radix-ui/react-label": "^2.1.2",
|
||||
"@radix-ui/react-scroll-area": "^1.2.3",
|
||||
"@radix-ui/react-separator": "^1.1.2",
|
||||
"@radix-ui/react-slot": "^1.1.2",
|
||||
"@sentry/nextjs": "^9",
|
||||
"@supabase/ssr": "^0.6.1",
|
||||
|
25
pnpm-lock.yaml
generated
25
pnpm-lock.yaml
generated
@ -23,6 +23,9 @@ importers:
|
||||
'@radix-ui/react-scroll-area':
|
||||
specifier: ^1.2.3
|
||||
version: 1.2.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@radix-ui/react-separator':
|
||||
specifier: ^1.1.2
|
||||
version: 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@radix-ui/react-slot':
|
||||
specifier: ^1.1.2
|
||||
version: 1.1.2(@types/react@18.3.18)(react@18.3.1)
|
||||
@ -890,6 +893,19 @@ packages:
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-separator@1.1.2':
|
||||
resolution: {integrity: sha512-oZfHcaAp2Y6KFBX6I5P1u7CQoy4lheCGiYj+pGFrHy8E/VNRb5E39TkTr3JrV520csPBTZjkuKFdEsjS5EUNKQ==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-slot@1.1.2':
|
||||
resolution: {integrity: sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==}
|
||||
peerDependencies:
|
||||
@ -4144,6 +4160,15 @@ snapshots:
|
||||
'@types/react': 18.3.18
|
||||
'@types/react-dom': 18.3.5(@types/react@18.3.18)
|
||||
|
||||
'@radix-ui/react-separator@1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.18
|
||||
'@types/react-dom': 18.3.5(@types/react@18.3.18)
|
||||
|
||||
'@radix-ui/react-slot@1.1.2(@types/react@18.3.18)(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.18)(react@18.3.1)
|
||||
|
3
public/images/apple_black.svg
Normal file
3
public/images/apple_black.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="814" height="1000">
|
||||
<path d="M788.1 340.9c-5.8 4.5-108.2 62.2-108.2 190.5 0 148.4 130.3 200.9 134.2 202.2-.6 3.2-20.7 71.9-68.7 141.9-42.8 61.6-87.5 123.1-155.5 123.1s-85.5-39.5-164-39.5c-76.5 0-103.7 40.8-165.9 40.8s-105.6-57-155.5-127C46.7 790.7 0 663 0 541.8c0-194.4 126.4-297.5 250.8-297.5 66.1 0 121.2 43.4 162.7 43.4 39.5 0 101.1-46 176.3-46 28.5 0 130.9 2.6 198.3 99.2zm-234-181.5c31.1-36.9 53.1-88.1 53.1-139.3 0-7.1-.6-14.3-1.9-20.1-50.6 1.9-110.8 33.7-147.1 75.8-28.5 32.4-55.1 83.6-55.1 135.5 0 7.8 1.3 15.6 1.9 18.1 3.2.6 8.4 1.3 13.6 1.3 45.4 0 102.5-30.4 135.5-71.3z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 660 B |
@ -8,9 +8,11 @@ const HomePage = async () => {
|
||||
const { data: { session } } = await supabase.auth.getSession();
|
||||
if (!session) {
|
||||
return (
|
||||
<main>
|
||||
<main className="min-h-screen">
|
||||
<Header />
|
||||
<LoginForm />
|
||||
<div className="flex flex-col items-center justify-center md:min-h-[80vh]">
|
||||
<LoginForm />
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
@ -15,6 +15,17 @@ import {
|
||||
FormItem,
|
||||
} from '@/components/ui/form';
|
||||
import { useRef } from 'react';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card"
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
import MicrosoftSignIn from '@/components/auth/microsoft/SignIn';
|
||||
import AppleSignIn from './apple/SignIn';
|
||||
|
||||
const formSchema = z.object({
|
||||
fullName: z.string().optional(),
|
||||
@ -50,68 +61,107 @@ const LoginForm = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
<Form {...form}>
|
||||
<form ref={formRef} className="space-y-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="fullName"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel htmlFor='fullName'>
|
||||
Full Name
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input id='fullName' type='text' {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
Full name is only required when signing up.
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="email"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel htmlFor='email'>
|
||||
Email
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input id='email' type='email' {...field} required />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="password"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
Password
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input id='password' type='password' {...field} required />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<div className="flex gap-4 pt-2">
|
||||
<Button type="button" onClick={handleLogin}>
|
||||
Log in
|
||||
</Button>
|
||||
<Button type="button" onClick={handleSignup}>
|
||||
Sign up
|
||||
</Button>
|
||||
<Card
|
||||
className='flex flex-col items-center justify-center
|
||||
bg-gradient-to-br from-background via-zinc-50 to-gray-50
|
||||
dark:via-gray-950 dark:to-slate-950'
|
||||
>
|
||||
<CardHeader className='flex items-center justify-center'>
|
||||
<CardTitle>Sign In</CardTitle>
|
||||
<CardDescription>
|
||||
Log in or create an account.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Form {...form}>
|
||||
<form ref={formRef} className="space-y-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="fullName"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel htmlFor='fullName'>
|
||||
Full Name
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input id='fullName' type='text' {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
Full name is only required when signing up.
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="email"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel htmlFor='email'>
|
||||
Email
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input id='email' type='email' {...field} required />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="password"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
Password
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input id='password' type='password' {...field} required />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<div className="flex gap-4 justify-center items-center">
|
||||
<Button
|
||||
type='button'
|
||||
className='w-5/12 font-semibold bg-gradient-to-r
|
||||
from-primary via-primary to-primarydark
|
||||
hover:from-primary hover:via-primarydark hover:to-primarydark'
|
||||
onClick={handleLogin}
|
||||
>
|
||||
Log in
|
||||
</Button>
|
||||
<Button
|
||||
type='button'
|
||||
className='w-5/12 font-semibold bg-gradient-to-l
|
||||
from-primary via-primary to-primarydark
|
||||
hover:from-primary hover:via-primarydark hover:to-primarydark'
|
||||
onClick={handleSignup}
|
||||
>
|
||||
Sign up
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</CardContent>
|
||||
<CardFooter className='flex flex-col items-center justify-center w-full'>
|
||||
<div className='flex flex-row items-center justify-between w-5/6'>
|
||||
<Separator className='w-5/12 h-0.5 rounded-3xl' />
|
||||
<p className='text-center text-muted-foreground font-semibold'>
|
||||
or
|
||||
</p>
|
||||
<Separator className='w-5/12 h-0.5 rounded-3xl' />
|
||||
</div>
|
||||
<div className='m-1'>
|
||||
< MicrosoftSignIn />
|
||||
<div className='my-2'>
|
||||
<AppleSignIn />
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
|
23
src/components/auth/apple/SignIn.tsx
Normal file
23
src/components/auth/apple/SignIn.tsx
Normal file
@ -0,0 +1,23 @@
|
||||
import { Button } from '@/components/ui/button';
|
||||
import Image from 'next/image';
|
||||
|
||||
const AppleSignIn = () => {
|
||||
return (
|
||||
<Button
|
||||
className='flex flex-row items-center justify-center
|
||||
dark:bg-white bg-slate-950 m-1 dark:hover:bg-slate-200
|
||||
hover:bg-slate-700 w-full my-auto'
|
||||
>
|
||||
<Image
|
||||
src='/images/apple_black.svg'
|
||||
alt='Apple Logo'
|
||||
width={16} height={16}
|
||||
className='invert dark:invert-0'
|
||||
/>
|
||||
<p className='font-semibold dark:text-slate-950'>
|
||||
Sign in with Apple
|
||||
</p>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
export default AppleSignIn;
|
22
src/components/auth/microsoft/SignIn.tsx
Normal file
22
src/components/auth/microsoft/SignIn.tsx
Normal file
@ -0,0 +1,22 @@
|
||||
import { Button } from '@/components/ui/button';
|
||||
import Image from 'next/image';
|
||||
|
||||
const MicrosoftSignIn = () => {
|
||||
return (
|
||||
<Button
|
||||
className='flex flex-row items-center justify-center
|
||||
dark:bg-white bg-slate-950 m-1 dark:hover:bg-slate-200
|
||||
hover:bg-slate-700 w-full'
|
||||
>
|
||||
<Image
|
||||
src='/images/microsoft_logo.png'
|
||||
alt='Microsoft Logo'
|
||||
width={20} height={20}
|
||||
/>
|
||||
<p className='font-semibold dark:text-slate-950'>
|
||||
Sign in with Microsoft
|
||||
</p>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
export default MicrosoftSignIn;
|
@ -8,25 +8,34 @@ const Header = () => {
|
||||
const { tvMode } = useTVMode();
|
||||
if (tvMode) {
|
||||
return (
|
||||
<div className='absolute top-4 right-2'>
|
||||
<div className='flex flex-row my-auto items-center pt-2 pr-0 md:pt-4'>
|
||||
<TVToggle />
|
||||
<div className='w-full flex flex-row items-end justify-end'>
|
||||
<div className='flex flex-row my-auto items-center pt-2 pr-0 sm:pr-8 sm:pt-4'>
|
||||
<AvatarDropdown />
|
||||
<div className='mb-0.5'>
|
||||
<TVToggle />
|
||||
</div>
|
||||
<ThemeToggle />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<header className='w-full py-2 pt-6 md:py-5'>
|
||||
<div className='absolute top-4 right-6'>
|
||||
<div className='flex flex-row my-auto items-center pt-2 pr-0 md:pt-4 md:pr-8'>
|
||||
<TVToggle />
|
||||
<ThemeToggle />
|
||||
<header className='w-full min-h-[10vh]'>
|
||||
<div className='w-full flex flex-row items-end justify-end'>
|
||||
<div
|
||||
className='flex flex-row my-auto items-center
|
||||
pt-2 pr-0 sm:pt-4 sm:pr-8'
|
||||
>
|
||||
<AvatarDropdown />
|
||||
<div className='mb-0.5'>
|
||||
<TVToggle />
|
||||
</div>
|
||||
<ThemeToggle />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className='flex flex-row items-center text-center
|
||||
justify-center sm:ml-0 p-4 mt-10 sm:mt-0'
|
||||
justify-center'
|
||||
>
|
||||
<Image
|
||||
src='/images/tech_tracker_logo.png'
|
||||
@ -36,8 +45,9 @@ const Header = () => {
|
||||
className='max-w-[40px] md:max-w-[120px]'
|
||||
/>
|
||||
<h1
|
||||
className='title-text text-sm md:text-4xl lg:text-8xl
|
||||
bg-gradient-to-r from-[#bec8e6] via-[#F0EEE4] to-[#FFF8E7]
|
||||
className='title-text text-xl sm:text-4xl md:text-6xl lg:text-8xl
|
||||
bg-gradient-to-r dark:from-[#bec8e6] dark:via-[#F0EEE4]
|
||||
dark:to-[#FFF8E7] from-[#2e3266] via-slate-600 to-zinc-700
|
||||
font-bold pl-2 md:pl-12 text-transparent bg-clip-text'
|
||||
>
|
||||
Tech Tracker
|
||||
|
76
src/components/ui/card.tsx
Normal file
76
src/components/ui/card.tsx
Normal file
@ -0,0 +1,76 @@
|
||||
import * as React from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const Card = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"rounded-xl border bg-card text-card-foreground shadow",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
Card.displayName = "Card"
|
||||
|
||||
const CardHeader = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn("flex flex-col space-y-1.5 p-6", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardHeader.displayName = "CardHeader"
|
||||
|
||||
const CardTitle = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn("font-semibold leading-none tracking-tight", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardTitle.displayName = "CardTitle"
|
||||
|
||||
const CardDescription = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn("text-sm text-muted-foreground", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardDescription.displayName = "CardDescription"
|
||||
|
||||
const CardContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
|
||||
))
|
||||
CardContent.displayName = "CardContent"
|
||||
|
||||
const CardFooter = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn("flex items-center p-6 pt-0", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardFooter.displayName = "CardFooter"
|
||||
|
||||
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
|
31
src/components/ui/separator.tsx
Normal file
31
src/components/ui/separator.tsx
Normal file
@ -0,0 +1,31 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import * as SeparatorPrimitive from "@radix-ui/react-separator"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const Separator = React.forwardRef<
|
||||
React.ElementRef<typeof SeparatorPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
|
||||
>(
|
||||
(
|
||||
{ className, orientation = "horizontal", decorative = true, ...props },
|
||||
ref
|
||||
) => (
|
||||
<SeparatorPrimitive.Root
|
||||
ref={ref}
|
||||
decorative={decorative}
|
||||
orientation={orientation}
|
||||
className={cn(
|
||||
"shrink-0 bg-border",
|
||||
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
)
|
||||
Separator.displayName = SeparatorPrimitive.Root.displayName
|
||||
|
||||
export { Separator }
|
@ -10,7 +10,10 @@
|
||||
--card-foreground: 224 71.4% 4.1%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 224 71.4% 4.1%;
|
||||
--primary: 262.1 83.3% 57.8%;
|
||||
/*--primary: 262.1 83.3% 57.8%;*/
|
||||
--primary: 231 39% 48%;
|
||||
--primary-dark: 231 39% 38%;
|
||||
--primary-light: 231 45% 58%;
|
||||
--primary-foreground: 210 20% 98%;
|
||||
--secondary: 220 14.3% 95.9%;
|
||||
--secondary-foreground: 220.9 39.3% 11%;
|
||||
@ -37,7 +40,10 @@
|
||||
--card-foreground: 210 20% 98%;
|
||||
--popover: 224 71.4% 4.1%;
|
||||
--popover-foreground: 210 20% 98%;
|
||||
--primary: 263.4 70% 50.4%;
|
||||
/*--primary: 263.4 70% 50.4%;*/
|
||||
--primary: 231 39% 48%;
|
||||
--primary-dark: 231 39% 38%;
|
||||
--primary-light: 231 45% 58%;
|
||||
--primary-foreground: 210 20% 98%;
|
||||
--secondary: 215 27.9% 16.9%;
|
||||
--secondary-foreground: 210 20% 98%;
|
||||
|
@ -32,6 +32,14 @@ export default {
|
||||
DEFAULT: 'hsl(var(--primary))',
|
||||
foreground: 'hsl(var(--primary-foreground))'
|
||||
},
|
||||
primarydark: {
|
||||
DEFAULT: 'hsl(var(--primary-dark))',
|
||||
foreground: 'hsl(var(--primary-foreground))'
|
||||
},
|
||||
primarylight: {
|
||||
DEFAULT: 'hsl(var(--primary-light))',
|
||||
foreground: 'hsl(var(--primary-foreground))'
|
||||
},
|
||||
secondary: {
|
||||
DEFAULT: 'hsl(var(--secondary))',
|
||||
foreground: 'hsl(var(--secondary-foreground))'
|
||||
|
Loading…
x
Reference in New Issue
Block a user