Skip to content

Commit

Permalink
added auth pages
Browse files Browse the repository at this point in the history
  • Loading branch information
emirrtopaloglu committed Feb 17, 2024
1 parent a8d7251 commit 26466d7
Show file tree
Hide file tree
Showing 14 changed files with 725 additions and 17 deletions.
2 changes: 1 addition & 1 deletion components.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"config": "tailwind.config.js",
"css": "src/styles/globals.css",
"baseColor": "gray",
"cssVariables": false,
"cssVariables": true,
"prefix": ""
},
"aliases": {
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
},
"dependencies": {
"@hookform/resolvers": "^3.3.4",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-slot": "^1.0.2",
"@reduxjs/toolkit": "^2.1.0",
"@tanstack/react-query": "^5.18.1",
Expand All @@ -24,7 +26,8 @@
"react-redux": "^9.1.0",
"tailwind-merge": "^2.2.1",
"tailwindcss-animate": "^1.0.7",
"yup": "^1.3.3"
"yup": "^1.3.3",
"zod": "^3.22.4"
},
"devDependencies": {
"autoprefixer": "^10.4.17",
Expand Down
Binary file added public/assets/images/auth-layout-image.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 7 additions & 7 deletions src/components/ui/button.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@ import { cva } from "class-variance-authority";
import { cn } from "@/src/lib/utils"

const buttonVariants = cva(
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-gray-950 disabled:pointer-events-none disabled:opacity-50 dark:focus-visible:ring-gray-300",
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
default:
"bg-gray-900 text-gray-50 shadow hover:bg-gray-900/90 dark:bg-gray-50 dark:text-gray-900 dark:hover:bg-gray-50/90",
"bg-primary text-primary-foreground shadow hover:bg-primary/90",
destructive:
"bg-red-500 text-gray-50 shadow-sm hover:bg-red-500/90 dark:bg-red-900 dark:text-gray-50 dark:hover:bg-red-900/90",
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
outline:
"border border-gray-200 bg-white shadow-sm hover:bg-gray-100 hover:text-gray-900 dark:border-gray-800 dark:bg-gray-950 dark:hover:bg-gray-800 dark:hover:text-gray-50",
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
secondary:
"bg-gray-100 text-gray-900 shadow-sm hover:bg-gray-100/80 dark:bg-gray-800 dark:text-gray-50 dark:hover:bg-gray-800/80",
ghost: "hover:bg-gray-100 hover:text-gray-900 dark:hover:bg-gray-800 dark:hover:text-gray-50",
link: "text-gray-900 underline-offset-4 hover:underline dark:text-gray-50",
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-9 px-4 py-2",
Expand Down
22 changes: 22 additions & 0 deletions src/components/ui/checkbox.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import * as React from "react"
import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
import { CheckIcon } from "@radix-ui/react-icons"

import { cn } from "@/src/lib/utils"

const Checkbox = React.forwardRef(({ className, ...props }, ref) => (
<CheckboxPrimitive.Root
ref={ref}
className={cn(
"peer h-4 w-4 shrink-0 rounded-sm border border-primary shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
className
)}
{...props}>
<CheckboxPrimitive.Indicator className={cn("flex items-center justify-center text-current")}>
<CheckIcon className="h-4 w-4" />
</CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root>
))
Checkbox.displayName = CheckboxPrimitive.Root.displayName

export { Checkbox }
133 changes: 133 additions & 0 deletions src/components/ui/form.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { Controller, FormProvider, useFormContext } from "react-hook-form";

import { cn } from "@/src/lib/utils"
import { Label } from "@/src/components/ui/label"

const Form = FormProvider

const FormFieldContext = React.createContext({})

const FormField = (
{
...props
}
) => {
return (
(<FormFieldContext.Provider value={{ name: props.name }}>
<Controller {...props} />
</FormFieldContext.Provider>)
);
}

const useFormField = () => {
const fieldContext = React.useContext(FormFieldContext)
const itemContext = React.useContext(FormItemContext)
const { getFieldState, formState } = useFormContext()

const fieldState = getFieldState(fieldContext.name, formState)

if (!fieldContext) {
throw new Error("useFormField should be used within <FormField>")
}

const { id } = itemContext

return {
id,
name: fieldContext.name,
formItemId: `${id}-form-item`,
formDescriptionId: `${id}-form-item-description`,
formMessageId: `${id}-form-item-message`,
...fieldState,
}
}

const FormItemContext = React.createContext({})

const FormItem = React.forwardRef(({ className, ...props }, ref) => {
const id = React.useId()

return (
(<FormItemContext.Provider value={{ id }}>
<div ref={ref} className={cn("space-y-2", className)} {...props} />
</FormItemContext.Provider>)
);
})
FormItem.displayName = "FormItem"

const FormLabel = React.forwardRef(({ className, ...props }, ref) => {
const { error, formItemId } = useFormField()

return (
(<Label
ref={ref}
className={cn(error && "text-destructive", className)}
htmlFor={formItemId}
{...props} />)
);
})
FormLabel.displayName = "FormLabel"

const FormControl = React.forwardRef(({ ...props }, ref) => {
const { error, formItemId, formDescriptionId, formMessageId } = useFormField()

return (
(<Slot
ref={ref}
id={formItemId}
aria-describedby={
!error
? `${formDescriptionId}`
: `${formDescriptionId} ${formMessageId}`
}
aria-invalid={!!error}
{...props} />)
);
})
FormControl.displayName = "FormControl"

const FormDescription = React.forwardRef(({ className, ...props }, ref) => {
const { formDescriptionId } = useFormField()

return (
(<p
ref={ref}
id={formDescriptionId}
className={cn("text-[0.8rem] text-muted-foreground", className)}
{...props} />)
);
})
FormDescription.displayName = "FormDescription"

const FormMessage = React.forwardRef(({ className, children, ...props }, ref) => {
const { error, formMessageId } = useFormField()
const body = error ? String(error?.message) : children

if (!body) {
return null
}

return (
(<p
ref={ref}
id={formMessageId}
className={cn("text-[0.8rem] font-medium text-destructive", className)}
{...props}>
{body}
</p>)
);
})
FormMessage.displayName = "FormMessage"

export {
useFormField,
Form,
FormItem,
FormLabel,
FormControl,
FormDescription,
FormMessage,
FormField,
}
19 changes: 19 additions & 0 deletions src/components/ui/input.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import * as React from "react"

import { cn } from "@/src/lib/utils"

const Input = React.forwardRef(({ className, type, ...props }, ref) => {
return (
(<input
type={type}
className={cn(
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
className
)}
ref={ref}
{...props} />)
);
})
Input.displayName = "Input"

export { Input }
16 changes: 16 additions & 0 deletions src/components/ui/label.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import * as React from "react"
import * as LabelPrimitive from "@radix-ui/react-label"
import { cva } from "class-variance-authority";

import { cn } from "@/src/lib/utils"

const labelVariants = cva(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
)

const Label = React.forwardRef(({ className, ...props }, ref) => (
<LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props} />
))
Label.displayName = LabelPrimitive.Root.displayName

export { Label }
120 changes: 120 additions & 0 deletions src/pages/auth/login.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { zodResolver } from "@hookform/resolvers/zod";
import { SubmitHandler, useForm } from "react-hook-form";
import * as z from "zod";
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/src/components/ui/form";
import { Input } from "@/src/components/ui/input";
import Link from "next/link";
import { Checkbox } from "@/src/components/ui/checkbox";
import { Button } from "@/src/components/ui/button";
import AuthLayout from "@/src/views/pages/auth/auth-layout";

const loginSchema = z.object({
email: z.string().email({
message: "error.invalid_email",
}),
password: z.string().min(8, {
message: "error.min_length",
}),
remember: z.boolean().optional(),
});

const LoginPage = () => {
const form = useForm({
resolver: zodResolver(loginSchema),
defaultValues: {
email: "",
password: "",
remember: false,
},
});

const onSubmit = (data) => {
console.log(data);
};

return (
<AuthLayout>
<div className="flex flex-col justify-center">
<h1 className="mb-2">👋 Hoş geldiniz</h1>
<p className="mb-4">Toplulukları keşfedin.</p>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>E-posta adresi</FormLabel>
<FormControl>
<Input placeholder="E-posta adresinizi girin" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="password"
render={({ field }) => (
<FormItem>
<FormLabel>Şifre</FormLabel>
<FormControl>
<Input placeholder="Şifrenizi girin" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<div className="flex justify-between">
<FormField
control={form.control}
name="remember"
render={({ field }) => (
<FormItem className="flex justify-center items-center space-x-2">
<FormControl>
<Checkbox
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
<FormLabel className="text-primary font-normal">
Beni hatırla
</FormLabel>
</FormItem>
)}
/>
<Link
href="/auth/forgot-password"
className="text-muted hover:underline text-sm"
>
Şifremi unuttum
</Link>
</div>
<Button type="submit" size="lg" className="w-full">
Giriş Yap
</Button>
</form>
</Form>
<div className="flex items-center justify-center space-x-2 my-4">
<p className="text-sm">Hesabınız yok mu?</p>
<Link
href="/auth/register"
className="text-primary hover:underline text-sm"
>
Kayıt ol
</Link>
</div>
</div>
</AuthLayout>
);
};

export default LoginPage;
Loading

0 comments on commit 26466d7

Please sign in to comment.