Compare commits
No commits in common. "2b8d0604e09d7238a1a18952d541341ca4a567dd" and "4fa3873dda92f770d6f65ab8d043a844aa5cc6f0" have entirely different histories.
2b8d0604e0
...
4fa3873dda
@ -2,7 +2,7 @@ import { Link } from 'react-router'
|
|||||||
|
|
||||||
import { APP } from '~/data/meta'
|
import { APP } from '~/data/meta'
|
||||||
|
|
||||||
export const Banner = () => {
|
export default function Banner() {
|
||||||
return (
|
return (
|
||||||
<div className="min-h-[65px] sm:mx-10">
|
<div className="min-h-[65px] sm:mx-10">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
|
|||||||
@ -5,7 +5,7 @@ interface BreadcrumbProperty {
|
|||||||
slug: string
|
slug: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Breadcrumb = (property: BreadcrumbProperty) => {
|
const Breadcrumb = (property: BreadcrumbProperty) => {
|
||||||
const { slug } = property
|
const { slug } = property
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
@ -20,3 +20,5 @@ export const Breadcrumb = (property: BreadcrumbProperty) => {
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default Breadcrumb
|
||||||
|
|||||||
@ -1,78 +0,0 @@
|
|||||||
import { useState, type ComponentProps, type ReactNode } from 'react'
|
|
||||||
import {
|
|
||||||
get,
|
|
||||||
useFormContext,
|
|
||||||
type FieldError,
|
|
||||||
type FieldValues,
|
|
||||||
type Path,
|
|
||||||
type RegisterOptions,
|
|
||||||
} from 'react-hook-form'
|
|
||||||
|
|
||||||
import { EyeIcon } from '~/components/icons/eye'
|
|
||||||
|
|
||||||
import { Button } from './button'
|
|
||||||
|
|
||||||
type TInputProperties<T extends FieldValues> = Omit<
|
|
||||||
ComponentProps<'input'>,
|
|
||||||
'size'
|
|
||||||
> & {
|
|
||||||
id: string
|
|
||||||
label?: ReactNode
|
|
||||||
name: Path<T>
|
|
||||||
rules?: RegisterOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Input = <TFormValues extends Record<string, unknown>>(
|
|
||||||
properties: TInputProperties<TFormValues>,
|
|
||||||
) => {
|
|
||||||
const { id, label, name, rules, type = 'text', ...rest } = properties
|
|
||||||
const [inputType, setInputType] = useState(type)
|
|
||||||
|
|
||||||
const {
|
|
||||||
register,
|
|
||||||
formState: { errors },
|
|
||||||
} = useFormContext()
|
|
||||||
|
|
||||||
const error: FieldError = get(errors, name)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="relative">
|
|
||||||
<label
|
|
||||||
htmlFor={id}
|
|
||||||
className="mb-1 block text-gray-700"
|
|
||||||
>
|
|
||||||
{label} {error && <span className="text-red-500">{error.message}</span>}
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
id={id}
|
|
||||||
type={inputType}
|
|
||||||
className="w-full rounded-md border border-[#DFDFDF] p-2"
|
|
||||||
{...register(name, rules)}
|
|
||||||
{...rest}
|
|
||||||
/>
|
|
||||||
{type === 'password' && (
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
variant="icon"
|
|
||||||
size="fit"
|
|
||||||
className="absolute top-9 right-3 text-gray-500"
|
|
||||||
onClick={() =>
|
|
||||||
setInputType(inputType === 'password' ? 'text' : 'password')
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{inputType === 'password' ? (
|
|
||||||
<EyeIcon
|
|
||||||
width={15}
|
|
||||||
height={15}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<EyeIcon
|
|
||||||
width={15}
|
|
||||||
height={15}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -40,7 +40,7 @@ const dataSocialMedia = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
export const IconsSocial: FC<SocialMediaProperties> = ({ className }) => {
|
const IconsSocial: FC<SocialMediaProperties> = ({ className }) => {
|
||||||
return (
|
return (
|
||||||
<div className={twMerge('flex gap-2', className)}>
|
<div className={twMerge('flex gap-2', className)}>
|
||||||
{dataSocialMedia.map(({ url, icon: Icon }, index) => (
|
{dataSocialMedia.map(({ url, icon: Icon }, index) => (
|
||||||
@ -56,3 +56,5 @@ export const IconsSocial: FC<SocialMediaProperties> = ({ className }) => {
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default IconsSocial
|
||||||
|
|||||||
@ -2,9 +2,9 @@ import { type PropsWithChildren } from 'react'
|
|||||||
|
|
||||||
import { PopupModal } from '~/components/popup/modal'
|
import { PopupModal } from '~/components/popup/modal'
|
||||||
import { SuccessModal } from '~/components/popup/success-modal'
|
import { SuccessModal } from '~/components/popup/success-modal'
|
||||||
import { Banner } from '~/components/ui/banner'
|
import Banner from '~/components/ui/banner'
|
||||||
import { useNewsContext } from '~/contexts/news'
|
import { useNewsContext } from '~/contexts/news'
|
||||||
import { FormForgotPassword } from '~/layouts/news/form-forgot-password'
|
import FormForgotPassword from '~/layouts/news/form-forgot-password'
|
||||||
import { FormLogin } from '~/layouts/news/form-login'
|
import { FormLogin } from '~/layouts/news/form-login'
|
||||||
import { FormRegister } from '~/layouts/news/form-register'
|
import { FormRegister } from '~/layouts/news/form-register'
|
||||||
|
|
||||||
@ -50,7 +50,6 @@ export const NewsDefaultLayout = (properties: PropsWithChildren) => {
|
|||||||
setIsRegisterOpen={setIsRegisterOpen}
|
setIsRegisterOpen={setIsRegisterOpen}
|
||||||
setIsLoginOpen={setIsLoginOpen}
|
setIsLoginOpen={setIsLoginOpen}
|
||||||
setIsForgetOpen={setForgetOpen}
|
setIsForgetOpen={setForgetOpen}
|
||||||
setIsSuccessModalOpen={setIsSuccessModalOpen}
|
|
||||||
/>
|
/>
|
||||||
</PopupModal>
|
</PopupModal>
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { Button } from '~/components/ui/button'
|
import { Button } from '~/components/ui/button'
|
||||||
|
|
||||||
export const FormForgotPassword = () => {
|
export default function FormForgotPassword() {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-center justify-center">
|
<div className="flex flex-col items-center justify-center">
|
||||||
<div className="w-full max-w-md">
|
<div className="w-full max-w-md">
|
||||||
|
|||||||
@ -1,93 +1,90 @@
|
|||||||
// import { EyeIcon, EyeOffIcon } from 'lucide-react'
|
// import { EyeIcon, EyeOffIcon } from 'lucide-react'
|
||||||
import { zodResolver } from '@hookform/resolvers/zod'
|
import { useState, type Dispatch, type SetStateAction } from 'react'
|
||||||
import { type Dispatch, type SetStateAction } from 'react'
|
|
||||||
import { FormProvider, useForm } from 'react-hook-form'
|
|
||||||
import { z } from 'zod'
|
|
||||||
|
|
||||||
|
import { EyeIcon } from '~/components/icons/eye'
|
||||||
import { Button } from '~/components/ui/button'
|
import { Button } from '~/components/ui/button'
|
||||||
import { Input } from '~/components/ui/input'
|
|
||||||
|
|
||||||
const loginSchema = z.object({
|
|
||||||
email: z.string().email('Email tidak valid'),
|
|
||||||
password: z.string().min(6, 'Kata sandi minimal 6 karakter'),
|
|
||||||
})
|
|
||||||
|
|
||||||
export type TLoginSchema = z.infer<typeof loginSchema>
|
|
||||||
|
|
||||||
type TProperties = {
|
type TProperties = {
|
||||||
setIsRegisterOpen: Dispatch<SetStateAction<boolean>>
|
setIsRegisterOpen: Dispatch<SetStateAction<boolean>>
|
||||||
setIsLoginOpen: Dispatch<SetStateAction<boolean>>
|
setIsLoginOpen: Dispatch<SetStateAction<boolean>>
|
||||||
setIsForgetOpen: Dispatch<SetStateAction<boolean>>
|
setIsForgetOpen: Dispatch<SetStateAction<boolean>>
|
||||||
setIsSuccessModalOpen: Dispatch<SetStateAction<boolean>>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FormLogin = (properties: TProperties) => {
|
export const FormLogin = (properties: TProperties) => {
|
||||||
const {
|
const { setIsRegisterOpen, setIsLoginOpen, setIsForgetOpen } = properties
|
||||||
setIsRegisterOpen,
|
const [showPassword, setShowPassword] = useState(false)
|
||||||
setIsLoginOpen,
|
|
||||||
setIsForgetOpen,
|
|
||||||
setIsSuccessModalOpen,
|
|
||||||
} = properties
|
|
||||||
|
|
||||||
const formMethods = useForm<TLoginSchema>({
|
|
||||||
resolver: zodResolver(loginSchema),
|
|
||||||
})
|
|
||||||
|
|
||||||
const { handleSubmit } = formMethods
|
|
||||||
|
|
||||||
const onSubmit = handleSubmit((data) => {
|
|
||||||
console.log('data', data) // eslint-disable-line no-console
|
|
||||||
setIsSuccessModalOpen(true)
|
|
||||||
setIsLoginOpen(false)
|
|
||||||
})
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-center">
|
<div className="flex items-center justify-center">
|
||||||
<div className="w-full max-w-md">
|
<div className="w-full max-w-md">
|
||||||
<FormProvider {...formMethods}>
|
<form>
|
||||||
<form
|
{/* Input Email / No Telepon */}
|
||||||
onSubmit={onSubmit}
|
<div className="mb-4">
|
||||||
className="space-y-4"
|
<label
|
||||||
>
|
htmlFor="email"
|
||||||
<Input
|
className="mb-1 block text-gray-700"
|
||||||
id="email"
|
|
||||||
label="Email / No Telepon"
|
|
||||||
placeholder="Contoh: legal@legalgo.id"
|
|
||||||
name="email"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Input
|
|
||||||
id="password"
|
|
||||||
label="Kata Sandi"
|
|
||||||
placeholder="Masukkan Kata Sandi"
|
|
||||||
name="password"
|
|
||||||
type="password"
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Lupa Kata Sandi */}
|
|
||||||
<div className="flex items-center justify-between text-sm">
|
|
||||||
<span className="text-gray-600">Lupa Kata Sandi?</span>
|
|
||||||
<Button
|
|
||||||
onClick={() => {
|
|
||||||
setIsLoginOpen(false)
|
|
||||||
setIsForgetOpen(true)
|
|
||||||
}}
|
|
||||||
className="font-semibold text-[#2E2F7C]"
|
|
||||||
variant="link"
|
|
||||||
>
|
|
||||||
Reset Kata Sandi
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Tombol Masuk */}
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
className="w-full rounded-md bg-[#2E2F7C] py-2 text-white transition hover:bg-blue-800"
|
|
||||||
>
|
>
|
||||||
Masuk
|
Email/No. Telepon
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Contoh: legal@legalgo.id"
|
||||||
|
className="focus:inheriten w-full rounded-md border border-[#DFDFDF] p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Input Password */}
|
||||||
|
<div className="relative mb-4">
|
||||||
|
<label
|
||||||
|
htmlFor="password"
|
||||||
|
className="mb-1 block text-gray-700 focus:outline-[#2E2F7C]"
|
||||||
|
>
|
||||||
|
Kata Sandi
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type={showPassword ? 'text' : 'password'}
|
||||||
|
placeholder="Masukkan Kata Sandi"
|
||||||
|
className="w-full rounded-md border border-[#DFDFDF] p-2 pr-10 focus:outline-[#2E2F7C]"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="absolute top-9 right-3 text-gray-500"
|
||||||
|
onClick={() => setShowPassword(!showPassword)}
|
||||||
|
>
|
||||||
|
{showPassword ? (
|
||||||
|
<EyeIcon
|
||||||
|
width={15}
|
||||||
|
height={15}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<EyeIcon
|
||||||
|
width={15}
|
||||||
|
height={15}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Lupa Kata Sandi */}
|
||||||
|
<div className="mb-4 flex items-center justify-between text-sm">
|
||||||
|
<span className="text-gray-600">Lupa Kata Sandi?</span>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
setIsLoginOpen(false)
|
||||||
|
setIsForgetOpen(true)
|
||||||
|
}}
|
||||||
|
className="font-semibold text-[#2E2F7C]"
|
||||||
|
variant="link"
|
||||||
|
>
|
||||||
|
Reset Kata Sandi
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</div>
|
||||||
</FormProvider>
|
|
||||||
|
{/* Tombol Masuk */}
|
||||||
|
<Button className="w-full rounded-md bg-[#2E2F7C] py-2 text-white transition hover:bg-blue-800">
|
||||||
|
Masuk
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
|
|
||||||
{/* Link Daftar */}
|
{/* Link Daftar */}
|
||||||
<div className="mt-4 text-center text-sm">
|
<div className="mt-4 text-center text-sm">
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { Breadcrumb } from '~/components/ui/breadcrumb'
|
import Breadcrumb from '~/components/ui/breadcrumb'
|
||||||
import { Card } from '~/components/ui/card'
|
import { Card } from '~/components/ui/card'
|
||||||
import { Carousel } from '~/components/ui/carousel'
|
import { Carousel } from '~/components/ui/carousel'
|
||||||
import { IconsSocial } from '~/components/ui/social-share'
|
import IconsSocial from '~/components/ui/social-share'
|
||||||
|
|
||||||
import { BERITA, CONTENT } from './data'
|
import { BERITA, CONTENT } from './data'
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user