Merge pull request #4 from ardeman/feature/slicing

Feature/slicing
This commit is contained in:
Ardeman 2025-02-22 11:37:57 +08:00 committed by GitHub
commit 5a97427756
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 836 additions and 58 deletions

View File

@ -1,4 +1,5 @@
@import 'tailwindcss';
@plugin "@tailwindcss/typography";
@theme {
--font-sans: 'Inter', ui-sans-serif, system-ui, sans-serif,

View File

@ -0,0 +1,23 @@
import type { JSX, SVGProps } from 'react'
export const LeftArrow = (
properties: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>,
) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
x="0px"
y="0px"
width={100}
height={100}
viewBox="0 0 70 70"
fill="currentColor"
{...properties}
>
<path
d="M1.60494 17.938C1.05815 18.4849 0.750977 19.2266 0.750977 20C0.750977 20.7734 1.05815 21.5152 1.60494 22.0621L18.1045 38.5617C18.6546 39.093 19.3914 39.387 20.1561 39.3803C20.9208 39.3737 21.6524 39.0669 22.1932 38.5262C22.7339 37.9854 23.0407 37.2539 23.0473 36.4891C23.054 35.7244 22.76 34.9876 22.2287 34.4375L10.7079 22.9167H49.3333C50.1068 22.9167 50.8487 22.6094 51.3957 22.0624C51.9426 21.5154 52.2499 20.7736 52.2499 20C52.2499 19.2265 51.9426 18.4846 51.3957 17.9376C50.8487 17.3907 50.1068 17.0834 49.3333 17.0834H10.7079L22.2287 5.56254C22.76 5.01245 23.054 4.27569 23.0473 3.51095C23.0407 2.74621 22.7339 2.01467 22.1932 1.4739C21.6524 0.933127 20.9208 0.626385 20.1561 0.619739C19.3914 0.613094 18.6546 0.907077 18.1045 1.43837L1.60494 17.938Z"
fill="#2E2F7C"
/>
</svg>
)
}

View File

@ -12,7 +12,7 @@ export const LinkIcon = (
height={95}
stroke="currentColor"
fill="currentColor"
stroke-width="0"
strokeWidth="0"
viewBox="0 0 1024 1024"
{...properties}
>

View File

@ -0,0 +1,30 @@
import type { ReactNode } from 'react'
interface ModalProperties {
isOpen: boolean
onClose: () => void
children: ReactNode
}
export default function PopupModal({
isOpen,
onClose,
children,
}: ModalProperties) {
if (!isOpen) return
return (
<>
<div className="bg-opacity-50 fixed inset-0 z-50 grid place-items-center bg-gray-300/50">
<button
onClick={onClose}
className="absolute top-5 right-5 z-50 bg-red-500 p-3 text-gray-500 hover:text-gray-800"
>
</button>
<div className="relative rounded-lg bg-white p-6 shadow-lg">
{children}
</div>
</div>
</>
)
}

View File

@ -0,0 +1,48 @@
import { Link } from 'react-router'
import { LeftArrow } from '~/components/icons/left-arrow'
import { APP } from '~/data/meta'
export default function PopupSuccessPayment() {
return (
<div className="flex min-h-screen items-center justify-center">
<div className="w-full max-w-md p-6">
<div className="absolute top-[80px] left-[50px]">
<Link
to="/#"
className="mt-2 h-full py-2"
>
<LeftArrow
width={'70px'}
height={'70px'}
></LeftArrow>
</Link>
</div>
<div className="mb-6 flex justify-center">
<Link to="/news">
<img
src={APP.logo}
alt={APP.title}
className="h-[80px]"
/>
</Link>
</div>
<div className="mb-4 p-4 text-center">
<p className="text-[#565658]">Selamat! Pembayaran anda berhasil!</p>
<div className="my-10 flex justify-center">
<img
src={'/public/images/back-to-home.svg'}
alt={APP.title}
className="h-[350px]"
/>
</div>
<button className="mt-5 w-full rounded-md bg-[#2E2F7C] py-2 text-white transition hover:bg-blue-800">
Back to Home
</button>
</div>
</div>
</div>
)
}

View File

@ -0,0 +1,48 @@
import { Link } from 'react-router'
import { LeftArrow } from '~/components/icons/left-arrow'
import { APP } from '~/data/meta'
export default function PopupSuccesRegister() {
return (
<div className="flex min-h-screen items-center justify-center">
<div className="w-full max-w-md p-6">
<div className="absolute top-[80px] left-[50px]">
<Link
to="/#"
className="mt-2 h-full py-2"
>
<LeftArrow
width={'70px'}
height={'70px'}
></LeftArrow>
</Link>
</div>
<div className="mb-6 flex justify-center">
<Link to="/news">
<img
src={APP.logo}
alt={APP.title}
className="h-[80px]"
/>
</Link>
</div>
<div className="mb-4 p-4 text-center">
<p className="text-[#565658]">Selamat! pendaftaran anda berhasil!</p>
<div className="my-10 flex justify-center">
<img
src={'/public/images/back-to-home.svg'}
alt={APP.title}
className="h-[350px]"
/>
</div>
<button className="mt-5 w-full rounded-md bg-[#2E2F7C] py-2 text-white transition hover:bg-blue-800">
Back to Home
</button>
</div>
</div>
</div>
)
}

View File

@ -0,0 +1,50 @@
import { Link } from 'react-router'
import { LeftArrow } from '~/components/icons/left-arrow'
import { APP } from '~/data/meta'
export default function PopupSuccessResetPass() {
return (
<div className="flex min-h-screen items-center justify-center">
<div className="w-full max-w-md p-6">
<div className="absolute top-[80px] left-[50px]">
<Link
to="/#"
className="mt-2 h-full py-2"
>
<LeftArrow
width={'70px'}
height={'70px'}
></LeftArrow>
</Link>
</div>
<div className="mb-6 flex justify-center">
<Link to="/news">
<img
src={APP.logo}
alt={APP.title}
className="h-[80px]"
/>
</Link>
</div>
<div className="mb-4 p-4 text-center">
<p className="text-[#565658]">
Link Reset Password telah dikirmkan ke email anda
</p>
<div className="my-10 flex justify-center">
<img
src={'/public/images/back-to-home.svg'}
alt={APP.title}
className="h-[350px]"
/>
</div>
<button className="mt-5 w-full rounded-md bg-[#2E2F7C] py-2 text-white transition hover:bg-blue-800">
Back to Home
</button>
</div>
</div>
</div>
)
}

View File

@ -2,9 +2,9 @@ import { Link } from 'react-router'
import { APP } from '~/data/meta'
export const Banner = () => {
export default function Banner() {
return (
<div className="min-h-[65px] bg-amber-400 sm:mx-10">
<div className="min-h-[65px] sm:mx-10">
<div className="relative">
<Link
to="/#"

View File

@ -9,7 +9,7 @@ import { Button } from './button'
export const Carousel = (properties: TNews) => {
const location = useLocation()
const hasCategory = location.pathname.includes('/categories/')
const hasCategory = location.pathname.includes('/category/')
const { title, description, items, type } = properties
return (
@ -71,8 +71,11 @@ export const Carousel = (properties: TNews) => {
)}
>
<div className={`${type === 'hero' ? 'hidden' : ''} `}>
{tags?.map((item) => (
<span className="my-3 mr-2 inline-block rounded bg-gray-200 px-3 py-1">
{tags?.map((item, index) => (
<span
key={index}
className="my-3 mr-2 inline-block rounded bg-gray-200 px-3 py-1"
>
{item}
</span>
))}
@ -97,7 +100,7 @@ export const Carousel = (properties: TNews) => {
size="block"
as={Link}
to={`detail/${slug}`}
className={twMerge('', type === 'hero' ? '' : 'mb-5 sm:mb-0')}
className={twMerge('', type === 'hero' ? '' : 'mb-5')}
>
View More
</Button>

View File

@ -0,0 +1,63 @@
import { Link } from 'react-router'
import { LeftArrow } from '~/components/icons/left-arrow'
import { APP } from '~/data/meta'
export default function FormForgotPassword() {
return (
<div className="flex items-center justify-center">
<div className="w-full max-w-md p-6">
<div className="absolute top-[80px] left-[50px]">
<Link
to="/#"
className="mt-2 h-full py-2"
>
<LeftArrow
width={'70px'}
height={'70px'}
></LeftArrow>
</Link>
</div>
<div className="mb-6 flex justify-center">
<Link to="/news">
<img
src={APP.logo}
alt={APP.title}
className="h-[100px]"
/>
</Link>
</div>
<div className="mb-4 p-4 text-center">
<p className="text-[#565658]">
Selamat Datang, silakan isi keterangan akun Anda untuk melanjutkan!
</p>
</div>
<form>
{/* Input Email / No Telepon */}
<div className="mb-4">
<label
htmlFor="email"
className="mb-1 block text-gray-700"
>
Email/No. Telepon
</label>
<input
type="text"
placeholder="Contoh: legal@legalgo.id"
className="focus:inheriten w-full rounded-md border border-[#DFDFDF] p-2"
required
/>
</div>
{/* Tombol Masuk */}
<button className="mt-5 w-full rounded-md bg-[#2E2F7C] py-2 text-white transition hover:bg-blue-800">
Daftar
</button>
</form>
</div>
</div>
)
}

View File

@ -0,0 +1,112 @@
// import { EyeIcon, EyeOffIcon } from 'lucide-react'
import { useState } from 'react'
import { Link } from 'react-router'
import { LeftArrow } from '~/components/icons/left-arrow'
import { APP } from '~/data/meta'
const FormLogin = () => {
const [showPassword, setShowPassword] = useState(false)
return (
<div className="flex min-h-screen items-center justify-center">
<div className="w-full max-w-md p-6">
<div className="absolute top-[80px] left-[50px]">
<Link
to="/#"
className="mt-2 h-full py-2"
>
<LeftArrow
width={'70px'}
height={'70px'}
></LeftArrow>
</Link>
</div>
<div className="mb-6 flex justify-center">
<Link to="/news">
<img
src={APP.logo}
alt={APP.title}
className="h-[80px]"
/>
</Link>
</div>
<div className="mb-4 p-4 text-center">
<p className="text-[#565658]">
Selamat Datang, silakan daftarkan akun Anda untuk melanjutkan!
</p>
</div>
<form>
{/* Input Email / No Telepon */}
<div className="mb-4">
<label
htmlFor="email"
className="mb-1 block text-gray-700"
>
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 ? <EyeOffIcon size={18} /> : <EyeIcon size={18} />} */}
</button>
</div>
{/* Lupa Kata Sandi */}
<div className="mb-4 flex justify-between">
<span className="text-gray-600">Lupa Kata Sandi?</span>
<Link
to="/reset-password"
className="font-semibold text-[#2E2F7C]"
>
Reset Kata Sandi
</Link>
</div>
{/* Tombol Masuk */}
<button className="w-full rounded-md bg-[#2E2F7C] py-2 text-white transition hover:bg-blue-800">
Masuk
</button>
</form>
{/* Link Daftar */}
<div className="mt-4 text-center text-sm">
Belum punya akun?{' '}
<Link
to="/register"
className="font-semibold text-[#2E2F7C]"
>
Daftar Disini
</Link>
</div>
</div>
</div>
)
}
export default FormLogin

View File

@ -0,0 +1,141 @@
// import { EyeIcon, EyeOffIcon } from 'lucide-react'
import { useState } from 'react'
import { Link } from 'react-router'
import { LeftArrow } from '~/components/icons/left-arrow'
import { APP } from '~/data/meta'
export default function FormRegister() {
const [showPassword, setShowPassword] = useState(false)
return (
<div className="flex items-center justify-center">
<div className="w-full max-w-md p-6">
<div className="absolute top-[80px] left-[50px]">
<Link
to="/#"
className="mt-2 h-full py-2"
>
<LeftArrow
width={'70px'}
height={'70px'}
></LeftArrow>
</Link>
</div>
<div className="mb-6 flex justify-center">
<Link to="/news">
<img
src={APP.logo}
alt={APP.title}
className="h-[800px]"
/>
</Link>
</div>
<div className="mb-4 p-4 text-center">
<p className="text-[#565658]">
Selamat Datang, silakan isi keterangan akun Anda untuk melanjutkan!
</p>
</div>
<form>
{/* Input Email / No Telepon */}
<div className="mb-4">
<label
htmlFor="email"
className="mb-1 block text-gray-700"
>
Email/No. Telepon
</label>
<input
type="text"
placeholder="Contoh: legal@legalgo.id"
className="focus:inheriten w-full rounded-md border border-[#DFDFDF] p-2"
required
/>
</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]"
required
/>
<button
type="button"
className="absolute top-9 right-3 text-gray-500"
onClick={() => setShowPassword(!showPassword)}
>
{/* {showPassword ? <EyeOffIcon size={18} /> : <EyeIcon size={18} />} */}
</button>
</div>
{/* Reinput Password */}
<div className="relative mb-4">
<label
htmlFor="password"
className="mb-1 block text-gray-700 focus:outline-[#2E2F7C]"
>
Ulangi 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]"
required
/>
<button
type="button"
className="absolute top-9 right-3 text-gray-500"
onClick={() => setShowPassword(!showPassword)}
>
{/* {showPassword ? <EyeOffIcon size={18} /> : <EyeIcon size={18} />} */}
</button>
</div>
{/* No Telepon */}
<div className="mb-4">
<label
htmlFor="no-telpon"
className="mb-1 block text-gray-700"
>
No. Telepon
</label>
<input
type="text"
placeholder="Contoh: legal@legalgo.id"
className="focus:inheriten w-full rounded-md border border-[#DFDFDF] p-2"
required
/>
</div>
{/* Subscribe*/}
<div className="mb-4">
<label
htmlFor="subscription"
className="mb-1 block text-gray-700"
>
Subscription
</label>
<select className="focus:inheriten w-full rounded-md border border-[#DFDFDF] p-2">
<option selected>Subscription</option>
</select>
</div>
{/* Tombol Masuk */}
<button className="mt-5 w-full rounded-md bg-[#2E2F7C] py-2 text-white transition hover:bg-blue-800">
Daftar
</button>
</form>
</div>
</div>
)
}

View File

@ -0,0 +1,61 @@
import React from 'react'
import { Link } from 'react-router'
import { LeftArrow } from '~/components/icons/left-arrow'
import { APP } from '~/data/meta'
export default function FormSubscription() {
return (
<div className="flex items-center justify-center">
<div className="w-full max-w-md p-6">
<div className="absolute top-[80px] left-[50px]">
<Link
to="/#"
className="mt-2 h-full py-2"
>
<LeftArrow
width={'70px'}
height={'70px'}
></LeftArrow>
</Link>
</div>
<div className="mb-6 flex justify-center">
<Link to="/news">
<img
src={APP.logo}
alt={APP.title}
className="h-[80px]"
/>
</Link>
</div>
<div className="mb-4 p-4 text-center">
<p className="text-[#565658]">
Selamat Datang, silakan Pilih Subscription Anda untuk melanjutkan!
</p>
</div>
<form>
{/* Subscribe*/}
<div className="mb-4">
<label
htmlFor="subscription"
className="mb-1 block text-gray-700"
>
Subscription
</label>
<select className="focus:inheriten w-full rounded-md border border-[#DFDFDF] p-2">
<option selected>Subscription</option>
</select>
</div>
{/* Tombol Masuk */}
<button className="mt-5 w-full rounded-md bg-[#2E2F7C] py-2 text-white transition hover:bg-blue-800">
Daftar
</button>
</form>
</div>
</div>
)
}

View File

@ -13,11 +13,11 @@ export default function HeaderMenuMobile() {
}
return (
<>
<div className="relative z-50 flex min-h-[65px] bg-[#2E2F7C] font-[sans-serif] tracking-wide text-white sm:hidden sm:px-10">
<div className="relative z-40 flex min-h-[65px] bg-[#2E2F7C] font-[sans-serif] tracking-wide text-white sm:hidden sm:px-10">
<div className="mx-auto flex w-full max-w-screen-xl flex-wrap items-center gap-4 align-middle">
{/* Menu */}
<div
className={`z-50 transition-transform duration-300 max-lg:fixed max-lg:top-0 max-lg:left-0 max-lg:h-full max-lg:w-full max-lg:overflow-auto max-lg:bg-[#2E2F7C] max-lg:p-6 max-lg:shadow-md ${
className={`z-40 transition-transform duration-300 max-lg:fixed max-lg:top-0 max-lg:left-0 max-lg:h-full max-lg:w-full max-lg:overflow-auto max-lg:bg-[#2E2F7C] max-lg:p-6 max-lg:shadow-md ${
isMenuOpen ? 'translate-x-0' : '-translate-x-full'
}`}
>
@ -38,8 +38,11 @@ export default function HeaderMenuMobile() {
{/* List Menu */}
<ul className="mx-10 max-lg:space-y-3 lg:ml-14 lg:flex lg:gap-x-5">
{MENU.map((item) => (
<li className="px-3 max-lg:border-b max-lg:py-3">
{MENU.map((item, index) => (
<li
key={index}
className="px-3 max-lg:border-b max-lg:py-3"
>
<Link
key={item.title}
to={item.url}
@ -78,7 +81,7 @@ export default function HeaderMenuMobile() {
</svg>
</button>
<div className="w-full py-3">
<HeaderSearch></HeaderSearch>
<HeaderSearch />
</div>
</div>
</div>

View File

@ -1,42 +1,59 @@
import { useState } from 'react'
import { Link } from 'react-router'
import PopupModal from '~/components/popup/modal'
import { Button } from '~/components/ui/button'
import FormLogin from '~/components/ui/form-login'
import { APP } from '~/data/meta'
export const HeaderTop = () => {
const [isModalOpen, setModalOpen] = useState(false)
return (
<div className="flex h-[60px] items-center justify-between bg-white px-5 align-middle sm:h-[100px] sm:gap-[15px] sm:px-[50px] sm:py-[20px]">
<Link
to="/news"
className="mt-2 h-full py-2"
>
<img
src={APP.logo}
alt={APP.title}
className="h-3/4 w-auto sm:h-full"
/>
</Link>
<div className="hidden h-full items-center py-1.5 font-light whitespace-pre-line sm:flex">
{APP.description}
</div>
<div className="flex items-center gap-[15px]">
<Button className="h-8 w-auto rounded-none px-3 text-xs sm:h-[50px] sm:w-[150px] sm:text-lg">
About Us
</Button>
<Button
variant="newsSecondary"
className="hidden sm:block"
<>
<div className="flex h-[60px] items-center justify-between bg-white px-5 align-middle sm:h-[100px] sm:gap-[15px] sm:px-[50px] sm:py-[20px]">
<Link
to="/news"
className="mt-2 h-full py-2"
>
Akun
</Button>
<div className="w-[50px] sm:w-[60px]">
<img
alt="language"
src="/flags/id.svg"
className="shadow-sm"
src={APP.logo}
alt={APP.title}
className="h-3/4 w-auto sm:h-full"
/>
</Link>
<div className="hidden h-full items-center py-1.5 font-light whitespace-pre-line sm:flex">
{APP.description}
</div>
<div className="flex items-center gap-[15px]">
<Button className="h-8 w-auto rounded-none px-3 text-xs sm:h-[50px] sm:w-[150px] sm:text-lg">
About Us
</Button>
<Button
variant="newsSecondary"
className="hidden sm:block"
onClick={() => setModalOpen(true)}
>
Akun
</Button>
<div
className="w-[50px] sm:w-[60px]"
onClick={() => setModalOpen(true)}
>
<img
alt="language"
src="/flags/id.svg"
className="shadow-sm"
/>
</div>
</div>
</div>
</div>
<PopupModal
isOpen={isModalOpen}
onClose={() => setModalOpen(false)}
>
<FormLogin />
</PopupModal>
</>
)
}

View File

@ -20,6 +20,102 @@ export const BERITA: TNews = {
description: 'Berita Terhangat hari ini',
type: 'grid',
items: [
{
title: 'Travelling as a way of self-discovery and progress',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.',
featured: '/images/news-2.jpg',
tags: ['Hukum Property'],
slug: 'travelling-as-a-way-of-self-discovery-and-progress',
},
{
title: 'Travelling as a way of self-discovery and progress',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.',
featured: '/images/news-2.jpg',
tags: ['Hukum Property'],
slug: 'travelling-as-a-way-of-self-discovery-and-progress',
},
{
title: 'Travelling as a way of self-discovery and progress',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.',
featured: '/images/news-2.jpg',
tags: ['Hukum Property'],
slug: 'travelling-as-a-way-of-self-discovery-and-progress',
},
{
title: 'Travelling as a way of self-discovery and progress',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.',
featured: '/images/news-2.jpg',
tags: ['Hukum Property'],
slug: 'travelling-as-a-way-of-self-discovery-and-progress',
},
{
title: 'Travelling as a way of self-discovery and progress',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.',
featured: '/images/news-2.jpg',
tags: ['Hukum Property'],
slug: 'travelling-as-a-way-of-self-discovery-and-progress',
},
{
title: 'Travelling as a way of self-discovery and progress',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.',
featured: '/images/news-2.jpg',
tags: ['Hukum Property'],
slug: 'travelling-as-a-way-of-self-discovery-and-progress',
},
{
title: 'Travelling as a way of self-discovery and progress',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.',
featured: '/images/news-2.jpg',
tags: ['Hukum Property'],
slug: 'travelling-as-a-way-of-self-discovery-and-progress',
},
{
title: 'Travelling as a way of self-discovery and progress',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.',
featured: '/images/news-2.jpg',
tags: ['Hukum Property'],
slug: 'travelling-as-a-way-of-self-discovery-and-progress',
},
{
title: 'Travelling as a way of self-discovery and progress',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.',
featured: '/images/news-2.jpg',
tags: ['Hukum Property'],
slug: 'travelling-as-a-way-of-self-discovery-and-progress',
},
{
title: 'Travelling as a way of self-discovery and progress',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.',
featured: '/images/news-2.jpg',
tags: ['Hukum Property'],
slug: 'travelling-as-a-way-of-self-discovery-and-progress',
},
{
title: 'Travelling as a way of self-discovery and progress',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.',
featured: '/images/news-2.jpg',
tags: ['Hukum Property'],
slug: 'travelling-as-a-way-of-self-discovery-and-progress',
},
{
title: 'Travelling as a way of self-discovery and progress',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.',
featured: '/images/news-2.jpg',
tags: ['Hukum Property'],
slug: 'travelling-as-a-way-of-self-discovery-and-progress',
},
{
title: 'Travelling as a way of self-discovery and progress',
content:

View File

@ -2,8 +2,39 @@ import type { TNews, TNewsDetail } from '~/types/news'
export const CONTENT: TNewsDetail = {
title: 'Hotman Paris Membuka Perpustakaan di tengah Diskotik',
content:
'Pengacara Kondang, Hotman Paris Hutapea, membuka sebuah perpustakaan baru di dalam diskotik nya yang berlokasi di daerah Jakarta Pusat, Hotman berkata Perpustakaan ini dibuka dengan harapan untuk meningkatkan gairah membaca masyarakat Indonesia, namun sayangnya..',
content: `<div class="container">
<h1>Pengertian dan Jenis Hukum</h1><p>Hukum adalah sistem aturan yang dibuat dan ditegakkan oleh lembaga berwenang untuk mengatur perilaku manusia dalam masyarakat. Hukum bertujuan untuk menciptakan ketertiban, keadilan, dan keseimbangan dalam kehidupan sosial.</p>
<h2>Jenis-Jenis Hukum</h2>
<h3>1. Hukum Berdasarkan Sumbernya</h3>
<ul>
<li><strong>Hukum Undang-Undang:</strong> Hukum yang tertulis dan dibuat oleh pemerintah atau legislatif.</li>
<li><strong>Hukum Kebiasaan:</strong> Hukum yang berkembang berdasarkan adat dan kebiasaan masyarakat.</li>
<li><strong>Hukum Yurisprudensi:</strong> Hukum yang ditetapkan berdasarkan keputusan hakim sebelumnya.</li>
<li><strong>Hukum Traktat:</strong> Hukum yang berasal dari perjanjian antarnegara.</li>
</ul>
<h3>2. Hukum Berdasarkan Wilayah Berlakunya</h3>
<ul>
<li><strong>Hukum Nasional:</strong> Hukum yang berlaku dalam suatu negara tertentu.</li>
<li><strong>Hukum Internasional:</strong> Hukum yang mengatur hubungan antara negara-negara.</li>
</ul>
<h3>3. Hukum Berdasarkan Isinya</h3>
<ul>
<li><strong>Hukum Publik:</strong> Hukum yang mengatur hubungan antara negara dengan warga negara, termasuk hukum pidana, tata negara, dan administrasi.</li>
<li><strong>Hukum Privat:</strong> Hukum yang mengatur hubungan antarindividu, seperti hukum perdata dan dagang.</li>
</ul>
<h3>4. Hukum Berdasarkan Bentuknya</h3>
<ul>
<li><strong>Hukum Tertulis:</strong> Hukum yang dicantumkan dalam peraturan resmi seperti undang-undang.</li>
<li><strong>Hukum Tidak Tertulis:</strong> Hukum yang hidup dalam masyarakat dan diakui oleh norma sosial.</li>
</ul>
<h2>Kesimpulan</h2>
<p>Hukum memainkan peran penting dalam mengatur kehidupan masyarakat. Dengan adanya hukum, ketertiban dan keadilan dapat terwujud. Memahami jenis-jenis hukum membantu kita dalam mengetahui hak dan kewajiban sebagai warga negara.</p>
</div>`,
featured: '/images/news-1.jpg',
slug: 'hotman-paris-membuka-perpustakaan-di-tengah-diskotik',
author: 'John Doe',

View File

@ -41,21 +41,7 @@ export const NewsDetailPage = () => {
className="object-center"
/>
</div>
<article className="my-8">
<div>{content}</div>
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Nesciunt
asperiores corporis, facilis praesentium tenetur rerum officiis!
Perspiciatis, sed cupiditate. Libero eos, cupiditate perferendis
delectus accusamus culpa veniam voluptatem sequi soluta hic optio
dolor, provident perspiciatis nihil sit. Est facere itaque natus
saepe odio ipsam recusandae at mollitia deserunt. Laboriosam atque
id aperiam tempore corporis magnam dolores vitae, maxime modi
quibusdam architecto sed aliquam error suscipit distinctio ratione
dolorum exercitationem vero sapiente? Commodi rem quidem vitae
eaque, consequuntur maxime facilis ea aliquam odio atque magni
delectus rerum fugiat aliquid, qui omnis incidunt libero quasi
distinctio exercitationem, reprehenderit minus officiis velit enim.
</article>
<article className="pross prose-stone">{content}</article>
<div className="flex items-end justify-between border-b-3 border-b-gray-300 py-4">
<div className="flex flex-col">

View File

@ -43,6 +43,10 @@ export function Layout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<head>
<link
rel="stylesheet"
href="https://unpkg.com/@tailwindcss/typography@0.4.x/dist/typography.min.css"
/>
<meta charSet="utf-8" />
<meta
name="viewport"

View File

@ -0,0 +1,23 @@
import { useState } from 'react'
import PopupModal from '~/components/popup/modal'
import FormLogin from '~/components/ui/form-login'
const AuthLayout = () => {
const [isModalOpen, setModalOpen] = useState(true)
return (
<div className="relative">
<div className="flex min-h-screen items-center justify-center bg-gray-100">
{/* Modal */}
<PopupModal
isOpen={isModalOpen}
onClose={() => setModalOpen(true)}
>
<FormLogin />
</PopupModal>
</div>
</div>
)
}
export default AuthLayout

View File

@ -1,6 +1,6 @@
import { Outlet } from 'react-router'
import { Banner } from '~/components/ui/banner'
import Banner from '~/components/ui/banner'
import { FooterLinks } from '~/layouts/footer-links'
import { FooterNewsletter } from '~/layouts/footer-newsletter'
import { HeaderMenu } from '~/layouts/header-menu'

View File

@ -31,6 +31,7 @@
"@commitlint/is-ignored": "^19.6.0",
"@eslint/js": "^9.19.0",
"@react-router/dev": "^7.1.3",
"@tailwindcss/typography": "^0.5.16",
"@tailwindcss/vite": "^4.0.0",
"@types/node": "^20.17.16",
"@types/react": "^19.0.1",

37
pnpm-lock.yaml generated
View File

@ -54,6 +54,9 @@ importers:
'@react-router/dev':
specifier: ^7.1.3
version: 7.1.3(@react-router/serve@7.1.3(react-router@7.1.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(typescript@5.7.3))(@types/node@20.17.16)(babel-plugin-macros@3.1.0)(lightningcss@1.29.1)(react-router@7.1.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(typescript@5.7.3)(vite@5.4.14(@types/node@20.17.16)(lightningcss@1.29.1))
'@tailwindcss/typography':
specifier: ^0.5.16
version: 0.5.16(tailwindcss@4.0.1)
'@tailwindcss/vite':
specifier: ^4.0.0
version: 4.0.1(vite@5.4.14(@types/node@20.17.16)(lightningcss@1.29.1))
@ -1245,6 +1248,11 @@ packages:
resolution: {integrity: sha512-3z1SpWoDeaA6K6jd92CRrGyDghOcRILEgyWVHRhaUm/tcpiazwJpU9BSG0xB7GGGnl9capojaC+zme/nKsZd/w==}
engines: {node: '>= 10'}
'@tailwindcss/typography@0.5.16':
resolution: {integrity: sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA==}
peerDependencies:
tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1'
'@tailwindcss/vite@4.0.1':
resolution: {integrity: sha512-ZkwMBA7uR+nyrafIZI8ce3PduE0dDVFVmxmInCUPTN17Jgy6RfEPXzqtL5fz658eDDxKa5xZ+gmiTt+5AMD0pw==}
peerDependencies:
@ -1694,6 +1702,11 @@ packages:
resolution: {integrity: sha512-ljnSOCOiMbklF+dwPbpooyB78foId02vUrTDogWzu6ca2DCNB7Kc/BHEGBnYOlUYtwXvSW0mWTwaiO2pwFIoRg==}
hasBin: true
cssesc@3.0.0:
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
engines: {node: '>=4'}
hasBin: true
csstype@3.1.3:
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
@ -2731,6 +2744,9 @@ packages:
lodash.camelcase@4.3.0:
resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==}
lodash.castarray@4.4.0:
resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==}
lodash.isplainobject@4.0.6:
resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
@ -3100,6 +3116,10 @@ packages:
resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==}
engines: {node: '>= 0.4'}
postcss-selector-parser@6.0.10:
resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==}
engines: {node: '>=4'}
postcss@8.5.1:
resolution: {integrity: sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==}
engines: {node: ^10 || ^12 || >=14}
@ -5111,6 +5131,14 @@ snapshots:
'@tailwindcss/oxide-win32-arm64-msvc': 4.0.1
'@tailwindcss/oxide-win32-x64-msvc': 4.0.1
'@tailwindcss/typography@0.5.16(tailwindcss@4.0.1)':
dependencies:
lodash.castarray: 4.4.0
lodash.isplainobject: 4.0.6
lodash.merge: 4.6.2
postcss-selector-parser: 6.0.10
tailwindcss: 4.0.1
'@tailwindcss/vite@4.0.1(vite@5.4.14(@types/node@20.17.16)(lightningcss@1.29.1))':
dependencies:
'@tailwindcss/node': 4.0.1
@ -5614,6 +5642,8 @@ snapshots:
cssbeautify@0.3.1: {}
cssesc@3.0.0: {}
csstype@3.1.3: {}
d3-color@3.1.0: {}
@ -6783,6 +6813,8 @@ snapshots:
lodash.camelcase@4.3.0: {}
lodash.castarray@4.4.0: {}
lodash.isplainobject@4.0.6: {}
lodash.kebabcase@4.1.1: {}
@ -7108,6 +7140,11 @@ snapshots:
possible-typed-array-names@1.0.0: {}
postcss-selector-parser@6.0.10:
dependencies:
cssesc: 3.0.0
util-deprecate: 1.0.2
postcss@8.5.1:
dependencies:
nanoid: 3.3.8