Compare commits

...

3 Commits

26 changed files with 61 additions and 67 deletions

View File

@ -1,7 +1,7 @@
import { z } from 'zod'
import { HttpServer } from '~/libs/http-server'
import type { TContentSchema } from '~/pages/contents-create'
import type { TContentSchema } from '~/pages/contents-form'
const newsResponseSchema = z.object({
data: z.object({

View File

@ -12,7 +12,7 @@ import { LeftArrow } from '~/components/icons/left-arrow'
import { Button } from '~/components/ui/button'
import { APP } from '~/configs/meta'
import { useNewsContext } from '~/contexts/news'
import type { loader } from '~/routes/_layout'
import type { loader } from '~/routes/_news'
export type ModalProperties = {
onClose: () => void
@ -35,7 +35,7 @@ const DESCRIPTIONS: DescriptionMap = {
export const SuccessModal = ({ isOpen, onClose }: ModalProperties) => {
const { setIsLoginOpen, setIsSubscribeOpen } = useNewsContext()
const loaderData = useRouteLoaderData<typeof loader>('routes/_layout')
const loaderData = useRouteLoaderData<typeof loader>('routes/_news')
const userData = loaderData?.userData
const message = isOpen

View File

@ -5,13 +5,13 @@ import { useRouteLoaderData } from 'react-router'
import { Button } from '~/components/ui/button'
import { CarouselButton } from '~/components/ui/button-slide'
import { useNewsContext } from '~/contexts/news'
import type { loader } from '~/routes/_layout'
import type { loader } from '~/routes/_news'
import type { TNews } from '~/types/news'
import { getPremiumAttribute } from '~/utils/render'
export const CarouselHero = (properties: TNews) => {
const { setIsSuccessOpen } = useNewsContext()
const loaderData = useRouteLoaderData<typeof loader>('routes/_layout')
const loaderData = useRouteLoaderData<typeof loader>('routes/_news')
const userData = loaderData?.userData
const { title, description, items } = properties
const [emblaReference, emblaApi] = useEmblaCarousel({ loop: false })

View File

@ -5,13 +5,13 @@ import { useRouteLoaderData } from 'react-router'
import { Button } from '~/components/ui/button'
import { CarouselButton } from '~/components/ui/button-slide'
import { useNewsContext } from '~/contexts/news'
import type { loader } from '~/routes/_layout'
import type { loader } from '~/routes/_news'
import type { TNews } from '~/types/news'
import { getPremiumAttribute } from '~/utils/render'
export const CarouselSection = (properties: TNews) => {
const { setIsSuccessOpen } = useNewsContext()
const loaderData = useRouteLoaderData<typeof loader>('routes/_layout')
const loaderData = useRouteLoaderData<typeof loader>('routes/_news')
const userData = loaderData?.userData
const { title, description, items } = properties
const [emblaReference, emblaApi] = useEmblaCarousel({

View File

@ -5,13 +5,13 @@ import { CarouselNextIcon } from '~/components/icons/carousel-next'
import { CarouselPreviousIcon } from '~/components/icons/carousel-previous'
import { Button } from '~/components/ui/button'
import { useNewsContext } from '~/contexts/news'
import type { loader } from '~/routes/_layout'
import type { loader } from '~/routes/_news'
import type { TNews } from '~/types/news'
import { getPremiumAttribute } from '~/utils/render'
export const CategorySection = (properties: TNews) => {
const { setIsSuccessOpen } = useNewsContext()
const loaderData = useRouteLoaderData<typeof loader>('routes/_layout')
const loaderData = useRouteLoaderData<typeof loader>('routes/_news')
const userData = loaderData?.userData
const { title, description, items } = properties

View File

@ -20,6 +20,10 @@ type TSwitchProperties<T extends FieldValues> = {
labelClassName?: string
className?: string
inputClassName?: string
options?: {
true: string
false: string
}
}
export const Switch = <TFormValues extends Record<string, unknown>>(
@ -34,6 +38,7 @@ export const Switch = <TFormValues extends Record<string, unknown>>(
labelClassName,
className,
inputClassName,
options,
} = properties
const {
@ -63,13 +68,22 @@ export const Switch = <TFormValues extends Record<string, unknown>>(
field.onChange(checked)
}}
className={twMerge(
'group relative flex h-7 w-14 cursor-pointer rounded-full bg-[#2E2F7C]/10 p-1 shadow transition-colors duration-200 ease-in-out focus:outline-none data-[checked]:bg-[#2E2F7C]/90 data-[focus]:outline-1 data-[focus]:outline-white',
'group flex h-7 cursor-pointer items-center rounded-full bg-[#2E2F7C]/10 p-1 shadow transition-colors duration-200 ease-in-out focus:outline-none data-[checked]:bg-[#2E2F7C]/90 data-[focus]:outline-1 data-[focus]:outline-white',
inputClassName,
)}
>
<span
<div
className={twMerge(
'order-2 text-xs transition duration-200 group-data-[checked]:order-1',
options?.true ? 'w-18' : 'w-8',
field.value ? 'text-white' : 'text-black/80',
)}
>
{field.value ? options?.true : options?.false}
</div>
<div
aria-hidden="true"
className="pointer-events-none inline-block size-5 translate-x-0 rounded-full bg-white ring-0 shadow-lg transition duration-200 ease-in-out group-data-[checked]:translate-x-7"
className="pointer-events-none order-1 size-5 rounded-full bg-white ring-0 shadow-lg transition duration-200 group-data-[checked]:order-2"
/>
</HeadlessSwitch>
</div>

View File

@ -9,7 +9,7 @@ import { Button } from '~/components/ui/button'
import { Combobox } from '~/components/ui/combobox'
import { Input } from '~/components/ui/input'
import { useNewsContext } from '~/contexts/news'
import type { loader } from '~/routes/_layout'
import type { loader } from '~/routes/_news'
export const registerSchema = z
.object({
@ -42,7 +42,7 @@ export const FormRegister = () => {
const [error, setError] = useState<string>()
const [disabled, setDisabled] = useState(false)
const fetcher = useFetcher()
const loaderData = useRouteLoaderData<typeof loader>('routes/_layout')
const loaderData = useRouteLoaderData<typeof loader>('routes/_news')
const subscriptions = loaderData?.subscriptionsData
const formMethods = useRemixForm<TRegisterSchema>({

View File

@ -7,7 +7,7 @@ import { z } from 'zod'
import { Button } from '~/components/ui/button'
import { Combobox } from '~/components/ui/combobox'
import { useNewsContext } from '~/contexts/news'
import type { loader } from '~/routes/_layout'
import type { loader } from '~/routes/_news'
export const subscribeSchema = z.object({
subscribe_plan: z
@ -30,7 +30,7 @@ export default function FormSubscription() {
const fetcher = useFetcher()
const [error, setError] = useState<string>()
const [disabled, setDisabled] = useState(false)
const loaderData = useRouteLoaderData<typeof loader>('routes/_layout')
const loaderData = useRouteLoaderData<typeof loader>('routes/_news')
const subscriptions = loaderData?.subscriptionsData
const formMethods = useRemixForm<TSubscribeSchema>({

View File

@ -7,7 +7,7 @@ import { MenuIcon } from '~/components/icons/menu'
import { Button } from '~/components/ui/button'
import { useNewsContext } from '~/contexts/news'
import { HeaderSearch } from '~/layouts/news/header-search'
import type { loader } from '~/routes/_layout'
import type { loader } from '~/routes/_news'
type THeaderMenuMobile = {
menu?: TCategoriesResponse['data']
@ -17,7 +17,7 @@ export default function HeaderMenuMobile(properties: THeaderMenuMobile) {
const { menu } = properties
const [isMenuOpen, setIsMenuOpen] = useState(false)
const { setIsLoginOpen } = useNewsContext()
const loaderData = useRouteLoaderData<typeof loader>('routes/_layout')
const loaderData = useRouteLoaderData<typeof loader>('routes/_news')
const userData = loaderData?.userData
const fetcher = useFetcher()

View File

@ -1,12 +1,12 @@
import { Link, useRouteLoaderData } from 'react-router'
import HeaderMenuMobile from '~/layouts/news/header-menu-mobile'
import type { loader } from '~/routes/_layout'
import type { loader } from '~/routes/_news'
import { HeaderSearch } from './header-search'
export const HeaderMenu = () => {
const loaderData = useRouteLoaderData<typeof loader>('routes/_layout')
const loaderData = useRouteLoaderData<typeof loader>('routes/_news')
const menu = loaderData?.categoriesData
return (

View File

@ -3,11 +3,11 @@ import { Link, useFetcher, useRouteLoaderData } from 'react-router'
import { Button } from '~/components/ui/button'
import { APP } from '~/configs/meta'
import { useNewsContext } from '~/contexts/news'
import type { loader } from '~/routes/_layout'
import type { loader } from '~/routes/_news'
export const HeaderTop = () => {
const { setIsLoginOpen } = useNewsContext()
const loaderData = useRouteLoaderData<typeof loader>('routes/_layout')
const loaderData = useRouteLoaderData<typeof loader>('routes/_news')
const userData = loaderData?.userData
const fetcher = useFetcher()

View File

@ -55,7 +55,7 @@ export const contentSchema = z.object({
export type TContentSchema = z.infer<typeof contentSchema>
export const CreateContentsPage = () => {
export const ContentsFormPage = () => {
const fetcher = useFetcher()
const navigate = useNavigate()
const loaderData = useRouteLoaderData<typeof loader>('routes/_admin.lg-admin')
@ -180,9 +180,10 @@ export const CreateContentsPage = () => {
<Switch
id="is_premium"
name="is_premium"
label="Premium"
label="Subscription"
labelClassName="text-sm font-medium text-[#363636]"
className="h-[42px]"
options={{ true: 'Premium', false: 'Normal' }}
/>
</div>

View File

@ -8,12 +8,12 @@ import type { TTagResponse } from '~/apis/common/get-tags'
import { Button } from '~/components/ui/button'
import { UiTable } from '~/components/ui/table'
import { TitleDashboard } from '~/components/ui/title-dashboard'
import type { loader } from '~/routes/_admin.lg-admin._dashboard.contents'
import type { loader } from '~/routes/_admin.lg-admin._dashboard.contents._index'
import { formatDate } from '~/utils/formatter'
export const ContentsPage = () => {
const loaderData = useRouteLoaderData<typeof loader>(
'routes/_admin.lg-admin._dashboard.contents',
'routes/_admin.lg-admin._dashboard.contents._index',
)
const newsData = loaderData?.newsData
@ -45,7 +45,7 @@ export const ContentsPage = () => {
},
{ title: 'Tag', data: 'tags' },
{
title: 'Premium',
title: 'Subscription',
data: 'is_premium',
},
{

View File

@ -3,14 +3,14 @@ import { useLocation, useRouteLoaderData } from 'react-router'
import { Card } from '~/components/ui/card'
import { CategorySection } from '~/components/ui/category-section'
import { DUMMY_DESCRIPTION } from '~/data/contents'
import type { loader } from '~/routes/_layout'
import type { loader } from '~/routes/_news'
import { BERITA } from './data'
export const NewsCategoriesPage = () => {
const { pathname } = useLocation()
const code = pathname.split('/')[2]
const loaderData = useRouteLoaderData<typeof loader>('routes/_layout')
const loaderData = useRouteLoaderData<typeof loader>('routes/_news')
const { name } =
loaderData?.categoriesData.find((item) => item.code === code) || {}
const { items } = BERITA

View File

@ -0,0 +1,4 @@
import { CreateCategoryPage } from '~/pages/category-create'
const DashboardCategoryLayout = () => <CreateCategoryPage />
export default DashboardCategoryLayout

View File

@ -2,7 +2,7 @@ import { getNews } from '~/apis/admin/get-news'
import { handleCookie } from '~/libs/cookies'
import { ContentsPage } from '~/pages/dashboard-contents'
import type { Route } from './+types/_admin.lg-admin._dashboard.contents'
import type { Route } from './+types/_admin.lg-admin._dashboard.contents._index'
export const loader = async ({ request }: Route.LoaderArgs) => {
const { staffToken } = await handleCookie(request)
@ -12,5 +12,5 @@ export const loader = async ({ request }: Route.LoaderArgs) => {
return { newsData }
}
const DashboardContentsLayout = () => <ContentsPage />
export default DashboardContentsLayout
const DashboardContentsIndexLayout = () => <ContentsPage />
export default DashboardContentsIndexLayout

View File

@ -0,0 +1,4 @@
import { ContentsFormPage } from '~/pages/contents-form'
const DashboardContentCreateLayout = () => <ContentsFormPage />
export default DashboardContentCreateLayout

View File

@ -0,0 +1,4 @@
import { UpdateContentsPage } from '~/pages/contents-update'
const DashboardContentUpdateLayout = () => <UpdateContentsPage />
export default DashboardContentUpdateLayout

View File

@ -1,11 +0,0 @@
import { AdminDashboardLayout } from '~/layouts/admin/dashboard'
import { CreateCategoryPage } from '~/pages/category-create'
const DashboardContentsLayout = () => {
return (
<AdminDashboardLayout>
<CreateCategoryPage />
</AdminDashboardLayout>
)
}
export default DashboardContentsLayout

View File

@ -1,11 +0,0 @@
import { AdminDashboardLayout } from '~/layouts/admin/dashboard'
import { CreateContentsPage } from '~/pages/contents-create'
const DashboardContentsLayout = () => {
return (
<AdminDashboardLayout>
<CreateContentsPage />
</AdminDashboardLayout>
)
}
export default DashboardContentsLayout

View File

@ -1,11 +0,0 @@
import { AdminDashboardLayout } from '~/layouts/admin/dashboard'
import { UpdateContentsPage } from '~/pages/contents-update'
const DashboardContentsLayout = () => {
return (
<AdminDashboardLayout>
<UpdateContentsPage />
</AdminDashboardLayout>
)
}
export default DashboardContentsLayout

View File

@ -7,7 +7,7 @@ import { NewsProvider } from '~/contexts/news'
import { NewsDefaultLayout } from '~/layouts/news/default'
import { handleCookie } from '~/libs/cookies'
import type { Route } from './+types/_layout'
import type { Route } from './+types/_news'
export const loader = async ({ request }: Route.LoaderArgs) => {
const { userToken } = await handleCookie(request)

View File

@ -5,7 +5,7 @@ import { XiorError } from 'xior'
import { createNewsRequest } from '~/apis/admin/create-news'
import { handleCookie } from '~/libs/cookies'
import { contentSchema, type TContentSchema } from '~/pages/contents-create'
import { contentSchema, type TContentSchema } from '~/pages/contents-form'
import type { Route } from './+types/actions.register'