Compare commits
3 Commits
d765d92df7
...
18098d63ba
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
18098d63ba | ||
|
|
afebd8b335 | ||
|
|
75e548dc83 |
@ -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({
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 })
|
||||
|
||||
@ -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({
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>({
|
||||
|
||||
@ -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>({
|
||||
|
||||
@ -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()
|
||||
|
||||
|
||||
@ -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 (
|
||||
|
||||
@ -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()
|
||||
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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',
|
||||
},
|
||||
{
|
||||
|
||||
@ -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
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
import { CreateCategoryPage } from '~/pages/category-create'
|
||||
|
||||
const DashboardCategoryLayout = () => <CreateCategoryPage />
|
||||
export default DashboardCategoryLayout
|
||||
@ -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
|
||||
@ -0,0 +1,4 @@
|
||||
import { ContentsFormPage } from '~/pages/contents-form'
|
||||
|
||||
const DashboardContentCreateLayout = () => <ContentsFormPage />
|
||||
export default DashboardContentCreateLayout
|
||||
@ -0,0 +1,4 @@
|
||||
import { UpdateContentsPage } from '~/pages/contents-update'
|
||||
|
||||
const DashboardContentUpdateLayout = () => <UpdateContentsPage />
|
||||
export default DashboardContentUpdateLayout
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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)
|
||||
@ -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'
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user