+
{({ isActive }) => (
-
{name}
-
- {description}
-
+
{name}
+
{description}
)
diff --git a/app/routes/projects+/forcompanies.tsx b/app/routes/projects+/forcompanies.tsx
new file mode 100644
index 0000000..4c8fac7
--- /dev/null
+++ b/app/routes/projects+/forcompanies.tsx
@@ -0,0 +1,15 @@
+import { Outlet } from '@remix-run/react'
+
+export default function PortfolioForCompanies() {
+ return (
+
+
+ for companies
+
+
+
+
+
+
+ )
+}
diff --git a/app/routes/projects+/freelance.tsx b/app/routes/projects+/freelance.tsx
new file mode 100644
index 0000000..4f8cef6
--- /dev/null
+++ b/app/routes/projects+/freelance.tsx
@@ -0,0 +1,15 @@
+import { Outlet } from '@remix-run/react'
+
+export default function PortfolioFreelance() {
+ return (
+
+
+ freelance
+
+
+
+
+
+
+ )
+}
diff --git a/app/routes/projects+/index.tsx b/app/routes/projects+/index.tsx
new file mode 100644
index 0000000..0aaf108
--- /dev/null
+++ b/app/routes/projects+/index.tsx
@@ -0,0 +1,25 @@
+export default function PortfolioFreelance() {
+ return (
+
+
+ wochlife projects
+
+
+
+
+
Web Dev
+
+
web dev content
+
+
+
+
+ streetwear art
+
+
+
streetwear art content
+
+
+
+ )
+}
diff --git a/app/routes/projects.tsx b/app/routes/projects.tsx
new file mode 100644
index 0000000..711dada
--- /dev/null
+++ b/app/routes/projects.tsx
@@ -0,0 +1,111 @@
+import { type DataFunctionArgs, type MetaFunction } from '@remix-run/node'
+import { NavLink, Outlet } from '@remix-run/react'
+import {
+ bigBoxTitle,
+ boxInnerContentBoxInnerBox,
+ darkBoxBgClassList,
+ innerContentBoxTexts,
+ purpleBoxBgClassList,
+ purpleBoxInnerContentBox,
+} from '#app/components/classlists.tsx'
+import { cn } from '#app/utils/misc.tsx'
+import { requireUserWithRole } from '#app/utils/permissions.ts'
+
+export async function loader({ request }: DataFunctionArgs) {
+ await requireUserWithRole(request, 'admin') // Temporary DEVelopment Phase
+ return null
+}
+
+export default function ProjectsRoute() {
+ //* styling classes
+ // 1. grid, responsivness
+ const col1 =
+ 'md-to-lg:w-[35%] lg:w-[32%] lg-to-xl:w-[29%] xl:w-[26.502%] max-w-[460px]'
+ const col2 =
+ 'w-full md-to-lg:w-[65%] lg:w-[68%] lg-to-xl:w-[71%] xl:w-[73.498%] flex flex-col'
+
+ return (
+
+
+
+
projects
+
+
+
+ {({ isActive }) => (
+
+ )}
+
+
+ {({ isActive }) => (
+
+ )}
+
+
+ {({ isActive }) => (
+
+ )}
+
+
+
+
+
+
+
+ )
+}
+
+function ProjectsContentBox({
+ name,
+ description,
+ boxClass,
+ innerBoxClass,
+ imgSrc,
+}: {
+ name: string
+ description: string
+ boxClass?: string
+ innerBoxClass?: string
+ imgSrc?: string
+}) {
+ return (
+
+
+ {!!imgSrc && imgSrc.length && (
+
![]({imgSrc})
+ )}
+
+
+
{name}
+
{description}
+
+
+ )
+}
+
+export const meta: MetaFunction = () => [{ title: 'Wochlife - Projects' }]
diff --git a/app/routes/resources+/__brand-editor.tsx b/app/routes/resources+/__brand-editor.tsx
deleted file mode 100644
index 68929da..0000000
--- a/app/routes/resources+/__brand-editor.tsx
+++ /dev/null
@@ -1,540 +0,0 @@
-import {
- conform,
- list,
- useFieldList,
- useFieldset,
- useForm,
- type FieldConfig,
-} from '@conform-to/react'
-import { getFieldsetConstraint, parse } from '@conform-to/zod'
-import { createId as cuid } from '@paralleldrive/cuid2'
-import { type CarBrand, type CarBrandImage } from '@prisma/client'
-import {
- unstable_createMemoryUploadHandler as createMemoryUploadHandler,
- unstable_parseMultipartFormData as parseMultipartFormData,
- json,
- type DataFunctionArgs,
- type SerializeFrom,
-} from '@remix-run/node'
-import { Form, useFetcher } from '@remix-run/react'
-import { useRef, useState } from 'react'
-import { toast } from 'sonner'
-import { z } from 'zod'
-import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
-import {
- ErrorList,
- Field,
- SelectBox,
- TextareaField,
-} from '#app/components/forms.tsx'
-import { Button } from '#app/components/ui/button.tsx'
-import { Icon } from '#app/components/ui/icon.tsx'
-import { IconNames } from '#app/components/ui/icons/nameStrings.ts'
-import { Label } from '#app/components/ui/label.tsx'
-import { StatusButton } from '#app/components/ui/status-button.tsx'
-import { Textarea } from '#app/components/ui/textarea.tsx'
-import { prisma } from '#app/utils/db.server.ts'
-import { cn, getCarBrandImgSrc } from '#app/utils/misc.tsx'
-import { redirectWithToast } from '#app/utils/toast.server.ts'
-import { countryList } from './_country-list.tsx'
-
-const urlMaxLength = 50
-const titleMinLength = 1
-const titleMaxLength = 100
-const descriptionMinLength = 1
-const descriptionMaxLength = 10000
-const seoMaxLength = 156
-
-const MAX_UPLOAD_SIZE = 1024 * 1024 * 1 // 1MB
-
-const ImageFieldsetSchema = z.object({
- id: z.string().optional(),
- file: z
- .instanceof(File)
- .optional()
- .refine(file => {
- return !file || file.size <= MAX_UPLOAD_SIZE
- }, 'File size must be less than 1MB'),
- altText: z.string().optional(),
-})
-
-type ImageFieldset = z.infer
-
-function imageHasFile(
- image: ImageFieldset,
-): image is ImageFieldset & { file: NonNullable } {
- return Boolean(image.file?.size && image.file?.size > 0)
-}
-
-function imageHasId(
- image: ImageFieldset,
-): image is ImageFieldset & { id: NonNullable } {
- return image.id != null
-}
-
-const maxImages = 1
-
-const urlErrorRef = 'Invalid URL: Use only letters, numbers and dashes.'
-const imgsErrorRef =
- 'You have reached maximum number of images! (' + maxImages + ')'
-
-const CarBrandEditorSchema = z.object({
- id: z.string().optional(),
- url: z
- .string({ required_error: 'url is required' })
- .max(urlMaxLength)
- // eslint-disable-next-line no-useless-escape
- .regex(/^[a-zA-Z0-9\-]+$/, {
- message: urlErrorRef,
- })
- //allowing user to input both upper/lower, but always saving it in lowercase
- .transform(value => value.toLowerCase()),
- title: z.string().min(titleMinLength).max(titleMaxLength),
- description: z.string().min(descriptionMinLength).max(descriptionMaxLength),
- countryOfOrigin: z.string(),
- logoIcon: z.string().optional(),
- seo: z.string().max(seoMaxLength).optional(),
- images: z.array(ImageFieldsetSchema).max(maxImages).optional(),
-})
-
-export async function action({ request, params }: DataFunctionArgs) {
- const formData = await parseMultipartFormData(
- request,
- createMemoryUploadHandler({ maxPartSize: MAX_UPLOAD_SIZE }),
- )
-
- const submission = await parse(formData, {
- schema: CarBrandEditorSchema.superRefine(async (data, ctx) => {
- if (!data.id) return
-
- const carBrand = await prisma.carBrand.findUnique({
- select: { id: true },
- where: { id: data.id },
- })
- if (!carBrand) {
- ctx.addIssue({
- code: 'custom',
- message: 'CarBrand not found',
- })
- }
- }).transform(async ({ images = [], ...data }) => {
- return {
- ...data,
- imageUpdates: await Promise.all(
- images.filter(imageHasId).map(async i => {
- if (imageHasFile(i)) {
- return {
- id: i.id,
- altText: i.altText,
- contentType: i.file.type,
- blob: Buffer.from(await i.file.arrayBuffer()),
- }
- } else {
- return {
- id: i.id,
- altText: i.altText,
- }
- }
- }),
- ),
- newImages: await Promise.all(
- images
- .filter(imageHasFile)
- .filter(i => !i.id)
- .map(async image => {
- return {
- altText: image.altText,
- contentType: image.file.type,
- blob: Buffer.from(await image.file.arrayBuffer()),
- }
- }),
- ),
- }
- }),
- async: true,
- })
-
- if (submission.intent !== 'submit') {
- return json({ status: 'idle', submission } as const)
- }
-
- if (!submission.value) {
- return json({ status: 'error', submission } as const, { status: 400 })
- }
-
- const {
- id: carBrandId,
- url,
- title,
- description,
- countryOfOrigin,
- logoIcon,
- seo,
- imageUpdates = [],
- newImages = [],
- } = submission.value
-
- const updatedCarBrand = await prisma.carBrand.upsert({
- select: { id: true, title: true },
- where: { id: carBrandId ?? '__new_carBrand__' },
- create: {
- id: carBrandId ?? url,
- url, // has to be unique!! //TODO: error handling unique constraint
- title,
- description,
- countryOfOrigin,
- logoIcon,
- seo,
- images: { create: newImages },
- },
- update: {
- url,
- title,
- description,
- countryOfOrigin,
- logoIcon,
- seo,
- images: {
- deleteMany: { id: { notIn: imageUpdates.map(i => i.id) } },
- updateMany: imageUpdates.map(updates => ({
- where: { id: updates.id },
- data: { ...updates, id: updates.blob ? cuid() : updates.id },
- })),
- create: newImages,
- },
- },
- })
-
- let toastTitle
- let toastDescription
- if (params.id) {
- toastTitle = 'CarBrand Edited!'
- toastDescription = 'Your edits were saved. π'
- } else {
- toastTitle = 'CarBrand Created!'
- toastDescription = `CarBrand: "${updatedCarBrand.title}" successfully created!`
- }
-
- return redirectWithToast(`/admin/brands/${updatedCarBrand.id}`, {
- type: 'success',
- title: toastTitle,
- description: toastDescription,
- })
-}
-
-export function CarBrandEditor({
- carBrand,
-}: {
- carBrand?: SerializeFrom<
- Pick<
- CarBrand,
- | 'id'
- | 'url'
- | 'title'
- | 'description'
- | 'logoIcon'
- | 'seo'
- | 'countryOfOrigin'
- > & {
- images: Array>
- }
- >
-}) {
- const carBrandFetcher = useFetcher()
- const isPending = carBrandFetcher.state !== 'idle'
-
- const [form, fields] = useForm({
- id: 'carBrand-editor',
- constraint: getFieldsetConstraint(CarBrandEditorSchema),
- lastSubmission: carBrandFetcher.data?.submission,
- onValidate({ formData }) {
- const parsedData = parse(formData, { schema: CarBrandEditorSchema })
- const errorCheck = parsedData.error
-
- if (Object.entries(errorCheck).length) {
- if (
- errorCheck.url &&
- errorCheck.url.filter(url => url.includes(urlErrorRef))
- ) {
- toast.error(urlErrorRef)
- }
-
- if (errorCheck.images) {
- toast.error(imgsErrorRef)
- }
- }
-
- return parsedData
- },
- defaultValue: {
- url: carBrand?.url ?? '',
- title: carBrand?.title ?? '',
- description: carBrand?.description ?? '',
- countryOfOrigin: carBrand?.countryOfOrigin ?? '',
- logoIcon: carBrand?.logoIcon ?? '',
- seo: carBrand?.seo ?? '',
- images: carBrand?.images ?? [{}],
- },
- })
- const imageList = useFieldList(form.ref, fields.images)
-
- const iconNames = IconNames()
-
- return (
-
-
-
-
-
-
- Submit
-
-
-
- )
-}
-
-function ImageChooser({
- config,
-}: {
- config: FieldConfig>
-}) {
- const ref = useRef(null)
- const fields = useFieldset(ref, config)
- const existingImage = Boolean(fields.id.defaultValue)
- const [previewImage, setPreviewImage] = useState(
- fields.id.defaultValue ? getCarBrandImgSrc(fields.id.defaultValue) : null,
- )
- const [altText, setAltText] = useState(fields.altText.defaultValue ?? '')
-
- return (
-
- )
-}
-
-export function ErrorBoundary() {
- return (
- (
- No carBrand with the id "{params.carBrandId}" exists
- ),
- }}
- />
- )
-}
diff --git a/app/routes/resources+/__dealer-editor.tsx b/app/routes/resources+/__dealer-editor.tsx
deleted file mode 100644
index 560331b..0000000
--- a/app/routes/resources+/__dealer-editor.tsx
+++ /dev/null
@@ -1,494 +0,0 @@
-import {
- conform,
- list,
- useFieldList,
- useFieldset,
- useForm,
- type FieldConfig,
-} from '@conform-to/react'
-import { getFieldsetConstraint, parse } from '@conform-to/zod'
-import { createId as cuid } from '@paralleldrive/cuid2'
-import { type Dealer, type DealerImage } from '@prisma/client'
-import {
- unstable_createMemoryUploadHandler as createMemoryUploadHandler,
- unstable_parseMultipartFormData as parseMultipartFormData,
- json,
- type DataFunctionArgs,
- type SerializeFrom,
-} from '@remix-run/node'
-import { Form, useFetcher } from '@remix-run/react'
-import { useRef, useState } from 'react'
-import { toast } from 'sonner'
-import { z } from 'zod'
-import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
-import { ErrorList, Field, SelectBox } from '#app/components/forms.tsx'
-import { Button } from '#app/components/ui/button.tsx'
-import { Icon } from '#app/components/ui/icon.tsx'
-import { Label } from '#app/components/ui/label.tsx'
-import { StatusButton } from '#app/components/ui/status-button.tsx'
-import { Textarea } from '#app/components/ui/textarea.tsx'
-import { prisma } from '#app/utils/db.server.ts'
-import { cn, getDealerImgSrc } from '#app/utils/misc.tsx'
-import { redirectWithToast } from '#app/utils/toast.server.ts'
-import { countryList } from './_country-list.tsx'
-
-const urlMaxLength = 50
-const titleMinLength = 1
-const titleMaxLength = 100
-
-const MAX_UPLOAD_SIZE = 1024 * 1024 * 0.6 // 600kB
-
-const ImageFieldsetSchema = z.object({
- id: z.string().optional(),
- file: z
- .instanceof(File)
- .optional()
- .refine(file => {
- return !file || file.size <= MAX_UPLOAD_SIZE
- }, 'File size must be less than 600kB'),
- altText: z.string().optional(),
-})
-
-type ImageFieldset = z.infer
-
-function imageHasFile(
- image: ImageFieldset,
-): image is ImageFieldset & { file: NonNullable } {
- return Boolean(image.file?.size && image.file?.size > 0)
-}
-
-function imageHasId(
- image: ImageFieldset,
-): image is ImageFieldset & { id: NonNullable } {
- return image.id != null
-}
-
-const maxImages = 1
-
-const urlErrorRef = 'Invalid URL: Use only letters, numbers and dashes.'
-const imgsErrorRef =
- 'You have reached maximum number of images! (' + maxImages + ')'
-
-const DealerEditorSchema = z.object({
- id: z.string().optional(),
- url: z
- .string({ required_error: 'url is required' })
- .max(urlMaxLength)
- // eslint-disable-next-line no-useless-escape
- .regex(/^[a-zA-Z0-9\-]+$/, {
- message: urlErrorRef,
- })
- //allowing user to input both upper/lower, but always saving it in lowercase
- .transform(value => value.toLowerCase()),
- name: z.string().min(titleMinLength).max(titleMaxLength),
- state: z.string(),
- city: z.string(),
- address: z.string(),
- images: z.array(ImageFieldsetSchema).max(maxImages).optional(),
-})
-
-export async function action({ request, params }: DataFunctionArgs) {
- const formData = await parseMultipartFormData(
- request,
- createMemoryUploadHandler({ maxPartSize: MAX_UPLOAD_SIZE }),
- )
-
- const submission = await parse(formData, {
- schema: DealerEditorSchema.superRefine(async (data, ctx) => {
- if (!data.id) return
-
- const dealer = await prisma.dealer.findUnique({
- select: { id: true },
- where: { id: data.id },
- })
- if (!dealer) {
- ctx.addIssue({
- code: 'custom',
- message: 'Dealer not found',
- })
- }
- }).transform(async ({ images = [], ...data }) => {
- return {
- ...data,
- imageUpdates: await Promise.all(
- images.filter(imageHasId).map(async i => {
- if (imageHasFile(i)) {
- return {
- id: i.id,
- altText: i.altText,
- contentType: i.file.type,
- blob: Buffer.from(await i.file.arrayBuffer()),
- }
- } else {
- return {
- id: i.id,
- altText: i.altText,
- }
- }
- }),
- ),
- newImages: await Promise.all(
- images
- .filter(imageHasFile)
- .filter(i => !i.id)
- .map(async image => {
- return {
- altText: image.altText,
- contentType: image.file.type,
- blob: Buffer.from(await image.file.arrayBuffer()),
- }
- }),
- ),
- }
- }),
- async: true,
- })
-
- if (submission.intent !== 'submit') {
- return json({ status: 'idle', submission } as const)
- }
-
- if (!submission.value) {
- return json({ status: 'error', submission } as const, { status: 400 })
- }
-
- const {
- id: dealerId,
- url,
- name,
- state,
- city,
- address,
- imageUpdates = [],
- newImages = [],
- } = submission.value
-
- const updatedDealer = await prisma.dealer.upsert({
- select: { id: true, name: true },
- where: { id: dealerId ?? '__new_dealer__' },
- create: {
- url,
- name,
- state,
- city,
- address,
- images: { create: newImages },
- },
- update: {
- url,
- name,
- state,
- city,
- address,
- images: {
- deleteMany: { id: { notIn: imageUpdates.map(i => i.id) } },
- updateMany: imageUpdates.map(updates => ({
- where: { id: updates.id },
- data: { ...updates, id: updates.blob ? cuid() : updates.id },
- })),
- create: newImages,
- },
- },
- })
-
- let toastTitle
- let toastDescription
- if (params.id) {
- toastTitle = 'Dealer Edited!'
- toastDescription = 'Your edits were saved. π'
- } else {
- toastTitle = 'Dealer Created!'
- toastDescription = `Dealer: "${updatedDealer.name}" successfully created!`
- }
-
- return redirectWithToast(`/admin/dealers/${updatedDealer.id}`, {
- type: 'success',
- title: toastTitle,
- description: toastDescription,
- })
-}
-
-export function DealerEditor({
- dealer,
-}: {
- dealer?: SerializeFrom<
- Pick & {
- images: Array>
- }
- >
-}) {
- const dealerFetcher = useFetcher()
- const isPending = dealerFetcher.state !== 'idle'
-
- const [form, fields] = useForm({
- id: 'dealer-editor',
- constraint: getFieldsetConstraint(DealerEditorSchema),
- lastSubmission: dealerFetcher.data?.submission,
- onValidate({ formData }) {
- const parsedData = parse(formData, { schema: DealerEditorSchema })
- const errorCheck = parsedData.error
-
- if (Object.entries(errorCheck).length) {
- if (
- errorCheck.url &&
- errorCheck.url.filter(url => url.includes(urlErrorRef))
- ) {
- toast.error(urlErrorRef)
- }
- if (errorCheck.images) {
- toast.error(imgsErrorRef)
- }
- }
-
- return parsedData
- },
- defaultValue: {
- url: dealer?.url ?? '',
- name: dealer?.name ?? '',
- state: dealer?.state ?? '',
- city: dealer?.city ?? '',
- address: dealer?.address ?? '',
- images: dealer?.images ?? [{}],
- },
- })
- const imageList = useFieldList(form.ref, fields.images)
-
- return (
-
-
-
-
-
-
- Submit
-
-
-
- )
-}
-
-function ImageChooser({
- config,
-}: {
- config: FieldConfig>
-}) {
- const ref = useRef(null)
- const fields = useFieldset(ref, config)
- const existingImage = Boolean(fields.id.defaultValue)
- const [previewImage, setPreviewImage] = useState(
- fields.id.defaultValue ? getDealerImgSrc(fields.id.defaultValue) : null,
- )
- const [altText, setAltText] = useState(fields.altText.defaultValue ?? '')
-
- return (
-
- )
-}
-
-export function ErrorBoundary() {
- return (
- (
- No dealer with the id "{params.dealerId}" exists
- ),
- }}
- />
- )
-}
diff --git a/app/routes/resources+/__facility-editor.tsx b/app/routes/resources+/__facility-editor.tsx
deleted file mode 100644
index 41c6a2b..0000000
--- a/app/routes/resources+/__facility-editor.tsx
+++ /dev/null
@@ -1,194 +0,0 @@
-import { conform, useForm } from '@conform-to/react'
-import { getFieldsetConstraint, parse } from '@conform-to/zod'
-import { type CarModelFacility } from '@prisma/client'
-import {
- json,
- type DataFunctionArgs,
- type SerializeFrom,
-} from '@remix-run/node'
-import { Form, useFetcher } from '@remix-run/react'
-import { toast } from 'sonner'
-import { z } from 'zod'
-import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
-import { ErrorList, Field, SelectBox } from '#app/components/forms.tsx'
-import { IconNames } from '#app/components/ui/icons/nameStrings.ts'
-import { StatusButton } from '#app/components/ui/status-button.tsx'
-import { prisma } from '#app/utils/db.server.ts'
-import { redirectWithToast } from '#app/utils/toast.server.ts'
-
-const FacilityEditorSchema = z.object({
- id: z.string().optional(),
- name: z.string(),
- iconName: z.string().optional(),
-})
-
-export async function action({ params, request }: DataFunctionArgs) {
- const formData = await request.formData()
-
- const submission = await parse(formData, {
- schema: FacilityEditorSchema.superRefine(async (data, ctx) => {
- if (!data.id) return
-
- const facility = await prisma.carModelFacility.findUnique({
- select: { id: true },
- where: { id: data.id },
- })
- if (!facility) {
- ctx.addIssue({
- code: 'custom',
- message: 'Facility not found',
- })
- }
- }),
- async: true,
- })
-
- if (submission.intent !== 'submit') {
- return json({ status: 'idle', submission } as const)
- }
-
- if (!submission.value) {
- return json({ status: 'error', submission } as const, { status: 400 })
- }
-
- const { id: facilityId, name, iconName } = submission.value
-
- const updatedFacility = await prisma.carModelFacility.upsert({
- select: { name: true }, //name instead of id because of updatedFacility.name being needed as string for toast
- where: { id: facilityId ?? '__new_facility__' },
- create: {
- name,
- iconName,
- },
- update: {
- name,
- iconName,
- },
- })
-
- let toastTitle
- let toastDescription
- if (params.id) {
- toastTitle = 'Facility Saved!'
- toastDescription = `Facility "${updatedFacility.name}" saved.`
- } else {
- toastTitle = 'Facility Created!'
- toastDescription = `New facility "${updatedFacility.name}" successfully created.`
- }
-
- return redirectWithToast('/admin/models/facility', {
- type: 'success',
- title: toastTitle,
- description: toastDescription,
- })
-}
-
-export function FacilityEditor({
- facility,
- existingFacilities, //ready for not creating more items with the same name/icon
-}: {
- facility?: SerializeFrom>
- existingFacilities?: object
-}) {
- // TODO: implement - existingFacilities & don't allow to create the same twice
- // TODO: editing route?
-
- const facilityFetcher = useFetcher()
- const isPending = facilityFetcher.state !== 'idle'
-
- const [form, fields] = useForm({
- id: 'facility-editor',
- constraint: getFieldsetConstraint(FacilityEditorSchema),
- lastSubmission: facilityFetcher.data?.submission,
- onValidate({ formData }) {
- const parsedData = parse(formData, { schema: FacilityEditorSchema })
- const errorCheck = parsedData.error
-
- if (Object.entries(errorCheck).length) {
- const name = errorCheck.name
-
- if (name) {
- toast.error('Facility not filled.')
- }
- }
-
- return parsedData
- },
- defaultValue: {
- name: facility?.name ?? '',
- iconName: facility?.iconName ?? '',
- },
- })
-
- const iconNames = IconNames()
-
- return (
-
-
-
-
- {facility ? 'save' : 'create'}
-
-
- )
-}
-
-export function ErrorBoundary() {
- return (
- (
- No facility with the id "{params.facilityId}" exists
- ),
- }}
- />
- )
-}
diff --git a/app/routes/resources+/__model-editor.tsx b/app/routes/resources+/__model-editor.tsx
deleted file mode 100644
index 3a634bc..0000000
--- a/app/routes/resources+/__model-editor.tsx
+++ /dev/null
@@ -1,394 +0,0 @@
-import { conform, useForm } from '@conform-to/react'
-import { getFieldsetConstraint, parse } from '@conform-to/zod'
-import { type CarModelFacility, type CarModel } from '@prisma/client'
-import {
- json,
- type DataFunctionArgs,
- type SerializeFrom,
-} from '@remix-run/node'
-import { Form, useFetcher } from '@remix-run/react'
-import { useState } from 'react'
-import { toast } from 'sonner'
-import { z } from 'zod'
-import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
-import {
- ErrorList,
- Field,
- SelectBox,
- TextareaField,
-} from '#app/components/forms.tsx'
-import { Button } from '#app/components/ui/button.tsx'
-import { Icon } from '#app/components/ui/icon.tsx'
-import { StatusButton } from '#app/components/ui/status-button.tsx'
-import { prisma } from '#app/utils/db.server.ts'
-import { redirectWithToast } from '#app/utils/toast.server.ts'
-
-const urlMaxLength = 50
-const titleMinLength = 1
-const titleMaxLength = 100
-const descriptionMinLength = 1
-const descriptionMaxLength = 10000
-const seoMaxLength = 156
-
-const urlErrorRef = 'Invalid URL: Use only letters, numbers and dashes.'
-
-const CarModelEditorSchema = z.object({
- id: z.string().optional(),
- url: z
- .string({ required_error: 'url is required' })
- .max(urlMaxLength)
- // eslint-disable-next-line no-useless-escape
- .regex(/^[a-zA-Z0-9\-]+$/, {
- message: urlErrorRef,
- })
- //allowing user to input both upper/lower, but always saving it in lowercase
- .transform(value => value.toLowerCase()),
- title: z.string().min(titleMinLength).max(titleMaxLength),
- year: z.preprocess(
- number => parseInt(z.string().parse(number), 10),
- z.number(),
- ),
- description: z.string().min(descriptionMinLength).max(descriptionMaxLength),
- seo: z.string().max(seoMaxLength).optional(),
- carModelFacility: z
- .array(z.string().transform(value => value.split(',')))
- .optional(),
- carBrandId: z.string(),
-})
-
-export async function action({ request, params }: DataFunctionArgs) {
- const formData = await request.formData()
-
- const submission = await parse(formData, {
- schema: CarModelEditorSchema.superRefine(async (data, ctx) => {
- if (!data.id) return
-
- const carModel = await prisma.carModel.findUnique({
- select: { id: true },
- where: { id: data.id },
- })
- if (!carModel) {
- ctx.addIssue({
- code: 'custom',
- message: 'CarModel not found',
- })
- }
- }).transform(async ({ carModelFacility = [], ...data }) => {
- return {
- ...data,
- carModelFacility: carModelFacility, // Include the carModelFacility data
- }
- }),
- async: true,
- })
-
- if (submission.intent !== 'submit') {
- return json({ status: 'idle', submission } as const)
- }
-
- if (!submission.value) {
- return json({ status: 'error', submission } as const, { status: 400 })
- }
-
- const {
- id: carModelId,
- url,
- title,
- year,
- description,
- seo,
- carModelFacility = [],
- carBrandId,
- } = submission.value
-
- const updatedCarModel = await prisma.carModel.upsert({
- select: { id: true, title: true },
- where: { id: carModelId ?? '__new_carModel__' },
- create: {
- url, // has to be unique!
- title,
- year,
- description,
- seo,
- carModelFacility: {
- connect: carModelFacility.length
- ? carModelFacility[0].map(facilityId => ({ id: facilityId }))
- : [],
- },
- carBrandId: carBrandId,
- },
- update: {
- url,
- title,
- year,
- description,
- seo,
- carModelFacility: {
- set: [],
- connect: carModelFacility.length
- ? carModelFacility[0].map(facilityId => ({ id: facilityId }))
- : [],
- },
- },
- })
-
- let toastTitle
- let toastDescription
- if (params.id) {
- toastTitle = 'CarModel Edited!'
- toastDescription = 'Your edits were saved. π'
- } else {
- toastTitle = 'CarModel Created!'
- toastDescription = `CarModel: "${updatedCarModel.title}" successfully created!`
- }
-
- return redirectWithToast(`/admin/models/${updatedCarModel.id}`, {
- type: 'success',
- title: toastTitle,
- description: toastDescription,
- })
-}
-
-export function CarModelEditor({
- carModel,
- facilities,
- availableBrands,
-}: {
- carModel?: SerializeFrom<
- Pick<
- CarModel,
- 'id' | 'url' | 'title' | 'year' | 'description' | 'seo' | 'carBrandId'
- > & {
- carModelFacility: Array<
- Pick
- >
- }
- >
- facilities?: object
- availableBrands: string[]
-}) {
- const carModelFetcher = useFetcher()
- const isPending = carModelFetcher.state !== 'idle'
-
- const facilityValues = Object.values(facilities ?? {})
- // Define a state variable to hold selected facility IDs
- const [selectedFacilities, setSelectedFacilities] = useState(
- carModel?.carModelFacility?.map(facility => facility.id) ?? [],
- )
-
- // Handle checkbox changes
- const handleFacilityChange = (event: React.ChangeEvent) => {
- const facilityId = event.target.value
- if (event.target.checked) {
- // Facility is selected, add it to the selectedFacilities array
- setSelectedFacilities([...selectedFacilities, facilityId])
- } else {
- // Facility is unselected, remove it from the selectedFacilities array
- setSelectedFacilities(selectedFacilities.filter(id => id !== facilityId))
- }
- }
-
- const [form, fields] = useForm({
- id: 'carModel-editor',
- constraint: getFieldsetConstraint(CarModelEditorSchema),
- lastSubmission: carModelFetcher.data?.submission,
- onValidate({ formData }) {
- const parsedData = parse(formData, { schema: CarModelEditorSchema })
- const errorCheck = parsedData.error
-
- if (Object.entries(errorCheck).length) {
- if (
- errorCheck.url &&
- errorCheck.url.filter(url => url.includes(urlErrorRef))
- ) {
- toast.error(urlErrorRef)
- }
- }
-
- return parsedData
- },
- defaultValue: {
- url: carModel?.url ?? '',
- title: carModel?.title ?? '',
- year: carModel?.year ?? '',
- description: carModel?.description ?? '',
- seo: carModel?.seo ?? '',
- facilities: carModel?.carModelFacility ?? selectedFacilities,
- carBrandId: carModel?.carBrandId ?? '',
- },
- })
-
- return (
-
-
-
-
-
-
- Submit
-
-
-
- )
-}
-
-export function ErrorBoundary() {
- return (
- (
- No carModel with the id "{params.carModelId}" exists
- ),
- }}
- />
- )
-}
-
-function getAvailableYears() {
- const currentYear = new Date().getFullYear()
- const startYear = 1914
-
- const years = []
- for (let year = startYear; year <= currentYear; year++) {
- years.push(year.toString())
- }
-
- return years.reverse()
-}
diff --git a/app/routes/resources+/__model-gallery-selector.tsx b/app/routes/resources+/__model-gallery-selector.tsx
deleted file mode 100644
index a579a9b..0000000
--- a/app/routes/resources+/__model-gallery-selector.tsx
+++ /dev/null
@@ -1,245 +0,0 @@
-import { conform, useForm } from '@conform-to/react'
-import { getFieldsetConstraint, parse } from '@conform-to/zod'
-import { type CarModel, type CarModelsGalleryImage } from '@prisma/client'
-import {
- json,
- type DataFunctionArgs,
- type SerializeFrom,
-} from '@remix-run/node'
-import { Form, useFetcher } from '@remix-run/react'
-import { useState } from 'react'
-import { z } from 'zod'
-import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
-import { ErrorList, Field } from '#app/components/forms.tsx'
-import { Button } from '#app/components/ui/button.tsx'
-import { StatusButton } from '#app/components/ui/status-button.tsx'
-import { prisma } from '#app/utils/db.server.ts'
-import { getCarModelsGalleryImgSrc } from '#app/utils/misc.tsx'
-import { redirectWithToast } from '#app/utils/toast.server.ts'
-
-const CarModelEditorSchema = z.object({
- id: z.string().optional(),
- carModelGalleryImages: z
- .array(z.string().transform(value => value.split(',')))
- .optional(),
-})
-
-export async function action({ request, params }: DataFunctionArgs) {
- const formData = await request.formData()
-
- const submission = await parse(formData, {
- schema: CarModelEditorSchema.superRefine(async (data, ctx) => {
- if (!data.id) return
-
- const carModel = await prisma.carModel.findUnique({
- select: { id: true },
- where: { id: data.id },
- })
- if (!carModel) {
- ctx.addIssue({
- code: 'custom',
- message: 'CarModel not found',
- })
- }
- }).transform(async ({ carModelGalleryImages = [], ...data }) => {
- return {
- ...data,
- carModelGalleryImages: carModelGalleryImages,
- }
- }),
- async: true,
- })
-
- if (submission.intent !== 'submit') {
- return json({ status: 'idle', submission } as const)
- }
-
- if (!submission.value) {
- return json({ status: 'error', submission } as const, { status: 400 })
- }
-
- const { id: carModelId, carModelGalleryImages = [] } = submission.value
-
- const updatedCarModel = await prisma.carModel.update({
- select: { id: true, title: true },
- where: { id: carModelId ?? '__new_carModel__' },
- data: {
- carModelGalleryImages: {
- set: [],
- connect: carModelGalleryImages.length
- ? carModelGalleryImages[0].map(gallerImageId => ({ id: gallerImageId }))
- : [],
- },
- },
- })
-
- let toastTitle
- let toastDescription
- if (params.id) {
- toastTitle = 'CarModel Edited!'
- toastDescription = 'Your edits were saved. π'
- } else {
- toastTitle = 'CarModel Created!'
- toastDescription = `CarModel: "${updatedCarModel.title}" successfully created!`
- }
-
- return redirectWithToast(`/admin/models/${updatedCarModel.id}`, {
- type: 'success',
- title: toastTitle,
- description: toastDescription,
- })
-}
-
-export function GallerySelector({
- carModel,
- galleries,
-}: {
- carModel?: SerializeFrom<
- Pick & {
- carModelGalleryImages: Array>
- }
- >
- galleries?: object //{ id: string, name: string, images: { id: string } }
-}) {
- const carModelFetcher = useFetcher()
- const isPending = carModelFetcher.state !== 'idle'
-
- // handling gallery images selection and their selected/non-selected states
- const allImages = galleries
- ? Object.values(galleries).flatMap(item =>
- item.images.map((image: { id: string }) => ({
- id: image.id,
- galleryName: item.name,
- })),
- )
- : []
-
- // Define a state variable to hold selected galleryImage IDs
- const [selectedGalleryImages, setSelectedGalleryImages] = useState(
- carModel?.carModelGalleryImages?.map(gallery => gallery.id) ?? [],
- )
-
- // Handle checkbox changes
- const handleGalleryImagesChange = (
- event: React.ChangeEvent,
- ) => {
- const galleryImageId = event.target.value
- if (event.target.checked) {
- // Gallery Image is selected, add it to the selectedGalleryImages array
- setSelectedGalleryImages([...selectedGalleryImages, galleryImageId])
- } else {
- // Gallery Image is unselected, remove it from the selectedGalleryImages array
- setSelectedGalleryImages(
- selectedGalleryImages.filter(id => id !== galleryImageId),
- )
- }
- }
-
- const [form, fields] = useForm({
- id: 'carModel-editor',
- constraint: getFieldsetConstraint(CarModelEditorSchema),
- lastSubmission: carModelFetcher.data?.submission,
- onValidate({ formData }) {
- return parse(formData, { schema: CarModelEditorSchema })
- },
- // defaultValue: {
- // carModelGalleryImages: carModel?.carModelGalleryImages
- // ? (carModel?.carModelGalleryImages).map(galleryImage => galleryImage.id)
- // : selectedGalleryImages,
- // },
- })
-
- return (
-
-
-
-
-
-
- Submit
-
-
-
- )
-}
-
-export function ErrorBoundary() {
- return (
- (
- No carModel with the id "{params.carModelId}" exists
- ),
- }}
- />
- )
-}
diff --git a/app/routes/resources+/__model-preview-images-selector.tsx b/app/routes/resources+/__model-preview-images-selector.tsx
deleted file mode 100644
index d151b68..0000000
--- a/app/routes/resources+/__model-preview-images-selector.tsx
+++ /dev/null
@@ -1,253 +0,0 @@
-import { conform, useForm } from '@conform-to/react'
-import { getFieldsetConstraint, parse } from '@conform-to/zod'
-import {
- type CarModel,
- type CarModelsGalleryImage,
-} from '@prisma/client'
-import {
- json,
- type DataFunctionArgs,
- type SerializeFrom,
-} from '@remix-run/node'
-import { Form, useFetcher } from '@remix-run/react'
-import { useState } from 'react'
-import { z } from 'zod'
-import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
-import { ErrorList, Field } from '#app/components/forms.tsx'
-import { Button } from '#app/components/ui/button.tsx'
-import { StatusButton } from '#app/components/ui/status-button.tsx'
-import { prisma } from '#app/utils/db.server.ts'
-import { getCarModelsGalleryImgSrc } from '#app/utils/misc.tsx'
-import { redirectWithToast } from '#app/utils/toast.server.ts'
-
-const CarModelEditorSchema = z.object({
- id: z.string().optional(),
- carModelPreviewImages: z
- .array(z.string().transform(value => value.split(',')))
- .optional(),
-})
-
-export async function action({ request, params }: DataFunctionArgs) {
- const formData = await request.formData()
-
- const submission = await parse(formData, {
- schema: CarModelEditorSchema.superRefine(async (data, ctx) => {
- if (!data.id) return
-
- const carModel = await prisma.carModel.findUnique({
- select: { id: true },
- where: { id: data.id },
- })
- if (!carModel) {
- ctx.addIssue({
- code: 'custom',
- message: 'CarModel not found',
- })
- }
- }).transform(
- async ({ carModelPreviewImages = [], ...data }) => {
- return {
- ...data,
- carModelPreviewImages: carModelPreviewImages,
- }
- },
- ),
- async: true,
- })
-
- if (submission.intent !== 'submit') {
- return json({ status: 'idle', submission } as const)
- }
-
- if (!submission.value) {
- return json({ status: 'error', submission } as const, { status: 400 })
- }
-
- const {
- id: carModelId,
- carModelPreviewImages = [],
- } = submission.value
-
- const updatedCarModel = await prisma.carModel.update({
- select: { id: true, title: true },
- where: { id: carModelId ?? '__new_carModel__' },
- data: {
- carModelPreviewImages: {
- set: [],
- connect: carModelPreviewImages.length
- ? carModelPreviewImages[0].map(gallerImageId => ({ id: gallerImageId }))
- : [],
- },
- },
- })
-
- let toastTitle
- let toastDescription
- if (params.id) {
- toastTitle = 'CarModel Edited!'
- toastDescription = 'Your edits were saved. π'
- } else {
- toastTitle = 'CarModel Created!'
- toastDescription = `CarModel: "${updatedCarModel.title}" successfully created!`
- }
-
- return redirectWithToast(`/admin/models/${updatedCarModel.id}`, {
- type: 'success',
- title: toastTitle,
- description: toastDescription,
- })
-}
-
-export function PreviewImagesSelector({
- carModel,
- galleries,
-}: {
- carModel?: SerializeFrom<
- Pick & {
- carModelPreviewImages: Array>
- }
- >
- galleries?: object //{ id: string, name: string, images: { id: string } }
-}) {
- const carModelFetcher = useFetcher()
- const isPending = carModelFetcher.state !== 'idle'
-
- // handling gallery images selection and their selected/non-selected states
- const allImages = galleries
- ? Object.values(galleries).flatMap(item =>
- item.images.map((image: { id: string }) => ({
- id: image.id,
- galleryName: item.name,
- })),
- )
- : []
-
- // Define a state variable to hold selected galleryImage IDs
- const [selectedGalleryImages, setSelectedGalleryImages] = useState(
- carModel?.carModelPreviewImages?.map(gallery => gallery.id) ?? [],
- )
-
- // Handle checkbox changes
- const handleGalleryImagesChange = (
- event: React.ChangeEvent,
- ) => {
- const galleryImageId = event.target.value
- if (event.target.checked) {
- // Gallery Image is selected, add it to the selectedGalleryImages array
- setSelectedGalleryImages([...selectedGalleryImages, galleryImageId])
- } else {
- // Gallery Image is unselected, remove it from the selectedGalleryImages array
- setSelectedGalleryImages(
- selectedGalleryImages.filter(id => id !== galleryImageId),
- )
- }
- }
-
- const [form, fields] = useForm({
- id: 'carModel-editor',
- constraint: getFieldsetConstraint(CarModelEditorSchema),
- lastSubmission: carModelFetcher.data?.submission,
- onValidate({ formData }) {
- return parse(formData, { schema: CarModelEditorSchema })
- },
- // defaultValue: {
- // carModelPreviewImages: carModel?.carModelPreviewImages
- // ? (carModel?.carModelPreviewImages).map(galleryImage => galleryImage.id)
- // : selectedGalleryImages,
- // },
- })
-
- return (
-
-
-
-
-
-
- Submit
-
-
-
- )
-}
-
-export function ErrorBoundary() {
- return (
- (
- No carModel with the id "{params.carModelId}" exists
- ),
- }}
- />
- )
-}
diff --git a/app/routes/resources+/__models-gallery-editor.tsx b/app/routes/resources+/__models-gallery-editor.tsx
deleted file mode 100644
index 929c62c..0000000
--- a/app/routes/resources+/__models-gallery-editor.tsx
+++ /dev/null
@@ -1,443 +0,0 @@
-import {
- conform,
- list,
- useFieldList,
- useFieldset,
- useForm,
- type FieldConfig,
-} from '@conform-to/react'
-import { getFieldsetConstraint, parse } from '@conform-to/zod'
-import { createId as cuid } from '@paralleldrive/cuid2'
-import { type CarModelsGallery, type CarModelsGalleryImage } from '@prisma/client'
-import {
- unstable_createMemoryUploadHandler as createMemoryUploadHandler,
- unstable_parseMultipartFormData as parseMultipartFormData,
- json,
- type DataFunctionArgs,
- type SerializeFrom,
-} from '@remix-run/node'
-import { Form, useFetcher } from '@remix-run/react'
-import { useRef, useState } from 'react'
-import { toast } from 'sonner'
-import { z } from 'zod'
-import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
-import { ErrorList, Field } from '#app/components/forms.tsx'
-import { Button } from '#app/components/ui/button.tsx'
-import { Icon } from '#app/components/ui/icon.tsx'
-import { Label } from '#app/components/ui/label.tsx'
-import { StatusButton } from '#app/components/ui/status-button.tsx'
-import { Textarea } from '#app/components/ui/textarea.tsx'
-import { prisma } from '#app/utils/db.server.ts'
-import { cn, getCarModelsGalleryImgSrc } from '#app/utils/misc.tsx'
-import { redirectWithToast } from '#app/utils/toast.server.ts'
-
-const maxImages = 20
-const MAX_UPLOAD_SIZE = 1024 * 1024 * 0.7 // 700kB
-
-const ImageFieldsetSchema = z.object({
- id: z.string().optional(),
- file: z
- .instanceof(File)
- .optional()
- .refine(file => {
- return !file || file.size <= MAX_UPLOAD_SIZE
- }, 'File size must be less than 700kB'),
- altText: z.string().optional(),
-})
-
-type ImageFieldset = z.infer
-
-function imageHasFile(
- image: ImageFieldset,
-): image is ImageFieldset & { file: NonNullable } {
- return Boolean(image.file?.size && image.file?.size > 0)
-}
-
-function imageHasId(
- image: ImageFieldset,
-): image is ImageFieldset & { id: NonNullable } {
- return image.id != null
-}
-
-const urlErrorRef = 'Invalid URL: Use only letters, numbers and dashes.'
-const imgsErrorRef =
- 'You have reached maximum number of images! (' + maxImages + ')'
-
-const CarModelsGalleryEditorSchema = z.object({
- id: z.string().optional(),
- name: z.string(),
- images: z.array(ImageFieldsetSchema).max(maxImages).optional(),
-})
-
-export async function action({ request, params }: DataFunctionArgs) {
- const formData = await parseMultipartFormData(
- request,
- createMemoryUploadHandler({ maxPartSize: MAX_UPLOAD_SIZE }),
- )
-
- const submission = await parse(formData, {
- schema: CarModelsGalleryEditorSchema.superRefine(async (data, ctx) => {
- if (!data.id) return
-
- const carModelsGallery = await prisma.carModelsGallery.findUnique({
- select: { id: true },
- where: { id: data.id },
- })
- if (!carModelsGallery) {
- ctx.addIssue({
- code: 'custom',
- message: 'CarModelsGallery not found',
- })
- }
- }).transform(async ({ images = [], ...data }) => {
- return {
- ...data,
- imageUpdates: await Promise.all(
- images.filter(imageHasId).map(async i => {
- if (imageHasFile(i)) {
- return {
- id: i.id,
- altText: i.altText,
- contentType: i.file.type,
- blob: Buffer.from(await i.file.arrayBuffer()),
- }
- } else {
- return {
- id: i.id,
- altText: i.altText,
- }
- }
- }),
- ),
- newImages: await Promise.all(
- images
- .filter(imageHasFile)
- .filter(i => !i.id)
- .map(async image => {
- return {
- altText: image.altText,
- contentType: image.file.type,
- blob: Buffer.from(await image.file.arrayBuffer()),
- }
- }),
- ),
- }
- }),
- async: true,
- })
-
- if (submission.intent !== 'submit') {
- return json({ status: 'idle', submission } as const)
- }
-
- if (!submission.value) {
- return json({ status: 'error', submission } as const, { status: 400 })
- }
-
- const {
- id: carModelId,
- name,
- imageUpdates = [],
- newImages = [],
- } = submission.value
-
- const updatedCarModelsGallery = await prisma.carModelsGallery.upsert({
- select: { id: true, name: true },
- where: { id: carModelId ?? '__new_carModel__' },
- create: {
- name,
- images: { create: newImages },
- },
- update: {
- name,
- images: {
- deleteMany: { id: { notIn: imageUpdates.map(i => i.id) } },
- updateMany: imageUpdates.map(updates => ({
- where: { id: updates.id },
- data: { ...updates, id: updates.blob ? cuid() : updates.id },
- })),
- create: newImages,
- },
- },
- })
-
- let toastTitle
- let toastDescription
- if (params.id) {
- toastTitle = 'CarModelsGallery Edited!'
- toastDescription = 'Your edits were saved. π'
- } else {
- toastTitle = 'CarModelsGallery Created!'
- toastDescription = `CarModelsGallery: "${updatedCarModelsGallery.name}" successfully created!`
- }
-
- return redirectWithToast(`/admin/models/gallery/${updatedCarModelsGallery.id}`, {
- type: 'success',
- title: toastTitle,
- description: toastDescription,
- })
-}
-
-export function CarModelsGalleryEditor({
- carModelsGallery,
-}: {
- carModelsGallery?: SerializeFrom<
- Pick & {
- images: Array>
- }
- >
-}) {
- const carModelFetcher = useFetcher()
- const isPending = carModelFetcher.state !== 'idle'
-
- const [form, fields] = useForm({
- id: 'carModelsGallery-editor',
- constraint: getFieldsetConstraint(CarModelsGalleryEditorSchema),
- lastSubmission: carModelFetcher.data?.submission,
- onValidate({ formData }) {
- const parsedData = parse(formData, { schema: CarModelsGalleryEditorSchema })
- const errorCheck = parsedData.error
-
- if (Object.entries(errorCheck).length) {
- if (
- errorCheck.url &&
- errorCheck.url.filter(url => url.includes(urlErrorRef))
- ) {
- toast.error(urlErrorRef)
- }
-
- if (errorCheck.images) {
- toast.error(imgsErrorRef)
- }
- }
-
- return parsedData
- },
- defaultValue: {
- name: carModelsGallery?.name ?? '',
- images: carModelsGallery?.images ?? [{}],
- },
- })
- const galleryImageList = useFieldList(form.ref, fields.images)
-
- return (
-
-
-
-
-
-
- {carModelsGallery ? 'Save' : 'Create'}
-
-
-
- )
-}
-
-function ImageChooser({
- config,
-}: {
- config: FieldConfig>
-}) {
- const ref = useRef(null)
- const fields = useFieldset(ref, config)
- const existingImage = Boolean(fields.id.defaultValue)
- const [previewImage, setPreviewImage] = useState(
- fields.id.defaultValue
- ? getCarModelsGalleryImgSrc(fields.id.defaultValue)
- : null,
- )
- const [altText, setAltText] = useState(fields.altText.defaultValue ?? '')
-
- const imageIdParts = config.id?.split('-')
- const imageIdvalueAfterLastDash = imageIdParts
- ? imageIdParts[imageIdParts.length - 1]
- : ''
- const imageNumber = parseInt(imageIdvalueAfterLastDash) + 1 + '. image'
-
- return (
-
- )
-}
-
-export function ErrorBoundary() {
- return (
- (
- No carModelsGallery with the id "{params.carModelId}" exists
- ),
- }}
- />
- )
-}
diff --git a/app/routes/resources+/_country-list.tsx b/app/routes/resources+/_country-list.tsx
deleted file mode 100644
index 49ba64c..0000000
--- a/app/routes/resources+/_country-list.tsx
+++ /dev/null
@@ -1,197 +0,0 @@
-export const countryList = [
- 'Afghanistan',
- 'Albania',
- 'Algeria',
- 'Andorra',
- 'Angola',
- 'Antigua and Barbuda',
- 'Argentina',
- 'Armenia',
- 'Australia',
- 'Austria',
- 'Azerbaijan',
- 'Bahamas',
- 'Bahrain',
- 'Bangladesh',
- 'Barbados',
- 'Belarus',
- 'Belgium',
- 'Belize',
- 'Benin',
- 'Bhutan',
- 'Bolivia',
- 'Bosnia and Herzegovina',
- 'Botswana',
- 'Brazil',
- 'Brunei',
- 'Bulgaria',
- 'Burkina Faso',
- 'Burundi',
- "CΓ΄te d'Ivoire",
- 'Cabo Verde',
- 'Cambodia',
- 'Cameroon',
- 'Canada',
- 'Central African Republic',
- 'Chad',
- 'Chile',
- 'China',
- 'Colombia',
- 'Comoros',
- 'Congo (Congo-Brazzaville)',
- 'Costa Rica',
- 'Croatia',
- 'Cuba',
- 'Cyprus',
- 'Czechia (Czech Republic)',
- 'Democratic Republic of the Congo',
- 'Denmark',
- 'Djibouti',
- 'Dominica',
- 'Dominican Republic',
- 'Ecuador',
- 'Egypt',
- 'El Salvador',
- 'Equatorial Guinea',
- 'Eritrea',
- 'Estonia',
- 'Eswatini (fmr. "Swaziland")',
- 'Ethiopia',
- 'Fiji',
- 'Finland',
- 'France',
- 'Gabon',
- 'Gambia',
- 'Georgia',
- 'Germany',
- 'Ghana',
- 'Greece',
- 'Grenada',
- 'Guatemala',
- 'Guinea',
- 'Guinea-Bissau',
- 'Guyana',
- 'Haiti',
- 'Holy See',
- 'Honduras',
- 'Hungary',
- 'Iceland',
- 'India',
- 'Indonesia',
- 'Iran',
- 'Iraq',
- 'Ireland',
- 'Israel',
- 'Italy',
- 'Jamaica',
- 'Japan',
- 'Jordan',
- 'Kazakhstan',
- 'Kenya',
- 'Kiribati',
- 'Kuwait',
- 'Kyrgyzstan',
- 'Laos',
- 'Latvia',
- 'Lebanon',
- 'Lesotho',
- 'Liberia',
- 'Libya',
- 'Liechtenstein',
- 'Lithuania',
- 'Luxembourg',
- 'Madagascar',
- 'Malawi',
- 'Malaysia',
- 'Maldives',
- 'Mali',
- 'Malta',
- 'Marshall Islands',
- 'Mauritania',
- 'Mauritius',
- 'Mexico',
- 'Micronesia',
- 'Moldova',
- 'Monaco',
- 'Mongolia',
- 'Montenegro',
- 'Morocco',
- 'Mozambique',
- 'Myanmar (formerly Burma)',
- 'Namibia',
- 'Nauru',
- 'Nepal',
- 'Netherlands',
- 'New Zealand',
- 'Nicaragua',
- 'Niger',
- 'Nigeria',
- 'North Korea',
- 'North Macedonia',
- 'Norway',
- 'Oman',
- 'Pakistan',
- 'Palau',
- 'Palestine State',
- 'Panama',
- 'Papua New Guinea',
- 'Paraguay',
- 'Peru',
- 'Philippines',
- 'Poland',
- 'Portugal',
- 'Qatar',
- 'Romania',
- 'Russia',
- 'Rwanda',
- 'Saint Kitts and Nevis',
- 'Saint Lucia',
- 'Saint Vincent and the Grenadines',
- 'Samoa',
- 'San Marino',
- 'Sao Tome and Principe',
- 'Saudi Arabia',
- 'Senegal',
- 'Serbia',
- 'Seychelles',
- 'Sierra Leone',
- 'Singapore',
- 'Slovakia',
- 'Slovenia',
- 'Solomon Islands',
- 'Somalia',
- 'South Africa',
- 'South Korea',
- 'South Sudan',
- 'Spain',
- 'Sri Lanka',
- 'Sudan',
- 'Suriname',
- 'Sweden',
- 'Switzerland',
- 'Syria',
- 'Tajikistan',
- 'Tanzania',
- 'Thailand',
- 'Timor-Leste',
- 'Togo',
- 'Tonga',
- 'Trinidad and Tobago',
- 'Tunisia',
- 'Turkey',
- 'Turkmenistan',
- 'Tuvalu',
- 'Uganda',
- 'Ukraine',
- 'United Arab Emirates',
- 'United Kingdom',
- 'United States of America',
- 'Uruguay',
- 'Uzbekistan',
- 'Vanuatu',
- 'Venezuela',
- 'Vietnam',
- 'Yemen',
- 'Zambia',
- 'Zimbabwe',
-]
diff --git a/app/routes/resources+/_similar-items-loader.tsx b/app/routes/resources+/_similar-items-loader.tsx
deleted file mode 100644
index 94ddf44..0000000
--- a/app/routes/resources+/_similar-items-loader.tsx
+++ /dev/null
@@ -1,18 +0,0 @@
-import { offersAndServicesBoxesClassList, offersAndServicesContainerClassList } from "#app/components/classlists.tsx";
-
-export function SimilarItemsLoader() {
-
- return (
-
-
-
find your niche
-
-
-
-
Offers And Services Loader boxes
-
Offers And Services Loader boxes
-
Offers And Services Loader boxes
-
-
- )
-}
diff --git a/app/routes/resources+/brands-images.$imageId.tsx b/app/routes/resources+/brands-images.$imageId.tsx
deleted file mode 100644
index 03dfba1..0000000
--- a/app/routes/resources+/brands-images.$imageId.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import { type DataFunctionArgs } from '@remix-run/node'
-import { prisma } from '#app/utils/db.server.ts'
-import { invariantResponse } from '#app/utils/misc.tsx'
-
-export async function loader({ params }: DataFunctionArgs) {
- invariantResponse(params.imageId, 'Image ID is required', { status: 400 })
- const image = await prisma.carBrandImage.findUnique({
- where: { id: params.imageId },
- select: { contentType: true, blob: true },
- })
-
- invariantResponse(image, 'Not found', { status: 404 })
-
- return new Response(image.blob, {
- headers: {
- 'Content-Type': image.contentType,
- 'Content-Length': Buffer.byteLength(image.blob).toString(),
- 'Content-Disposition': `inline; filename="${params.imageId}"`,
- 'Cache-Control': 'public, max-age=31536000, immutable',
- },
- })
-}
diff --git a/app/routes/resources+/carModels-gallery-images.$imageId.tsx b/app/routes/resources+/carModels-gallery-images.$imageId.tsx
deleted file mode 100644
index cf5392c..0000000
--- a/app/routes/resources+/carModels-gallery-images.$imageId.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import { type DataFunctionArgs } from '@remix-run/node'
-import { prisma } from '#app/utils/db.server.ts'
-import { invariantResponse } from '#app/utils/misc.tsx'
-
-export async function loader({ params }: DataFunctionArgs) {
- invariantResponse(params.imageId, 'Image ID is required', { status: 400 })
- const image = await prisma.carModelsGalleryImage.findUnique({
- where: { id: params.imageId },
- select: { contentType: true, blob: true },
- })
-
- invariantResponse(image, 'Not found', { status: 404 })
-
- return new Response(image.blob, {
- headers: {
- 'Content-Type': image.contentType,
- 'Content-Length': Buffer.byteLength(image.blob).toString(),
- 'Content-Disposition': `inline; filename="${params.imageId}"`,
- 'Cache-Control': 'public, max-age=31536000, immutable',
- },
- })
-}
diff --git a/app/styles/customComponents.css b/app/styles/customComponents.css
index eeb7bcd..ecb0252 100644
--- a/app/styles/customComponents.css
+++ b/app/styles/customComponents.css
@@ -93,7 +93,7 @@
}
@media (max-height: 875px) {
- .custom-portfolio-sections-height {
+ .custom-content-sections-height {
@apply max-h-[183px];
}
.custom-projects-box-max-height {
@@ -104,7 +104,7 @@
.custom-max-heights {
@apply max-h-[595px];
}
- .custom-portfolio-sections-height {
+ .custom-content-sections-height {
@apply max-h-[207px];
}
.custom-max-margin-welcome-box {
@@ -149,8 +149,6 @@
}
}
-
-
/* custom global section */
img,
svg,
diff --git a/app/utils/extended-theme.ts b/app/utils/extended-theme.ts
index f199224..4b38c0a 100644
--- a/app/utils/extended-theme.ts
+++ b/app/utils/extended-theme.ts
@@ -192,7 +192,7 @@ export const extendedTheme = {
'9999': '9999',
},
backgroundImage: {
- 'dark-box-gradient':
+ 'dark-gradient':
'linear-gradient(to bottom right, rgba(27, 27, 27, 0.8) 0%, rgba(16, 16, 16, 0.8) 50%, rgba(16, 16, 16, .9) 100%)',
'menu-box-gradient':
'linear-gradient(to bottom right, rgba(24, 24, 24, .86) 0%, rgba(18, 18, 18, .86) 50%, rgba(16, 16, 16, .9) 100%)',
diff --git a/prisma/migrations/20231208151344_init_with_custom_models_for_car_models/migration.sql b/prisma/migrations/20231208151344_init_with_custom_models_for_car_models/migration.sql
deleted file mode 100644
index a42ee16..0000000
--- a/prisma/migrations/20231208151344_init_with_custom_models_for_car_models/migration.sql
+++ /dev/null
@@ -1,128 +0,0 @@
--- CreateTable
-CREATE TABLE "CarModel" (
- "id" TEXT NOT NULL PRIMARY KEY,
- "url" TEXT NOT NULL,
- "title" TEXT NOT NULL,
- "description" TEXT NOT NULL,
- "seo" TEXT,
- "visibility" BOOLEAN NOT NULL DEFAULT false,
- "price1" INTEGER NOT NULL,
- "additionalNightPrice1" INTEGER NOT NULL,
- "price2" INTEGER,
- "additionalNightPrice2" INTEGER,
- "price3" INTEGER,
- "additionalNightPrice3" INTEGER,
- "numberOfGuestsForDefaultPrice" INTEGER NOT NULL,
- "maxGuests" INTEGER NOT NULL,
- "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updatedAt" DATETIME NOT NULL
-);
-
--- CreateTable
-CREATE TABLE "CarModelsGallery" (
- "id" TEXT NOT NULL PRIMARY KEY,
- "name" TEXT NOT NULL
-);
-
--- CreateTable
-CREATE TABLE "CarModelsGalleryImage" (
- "id" TEXT NOT NULL PRIMARY KEY,
- "altText" TEXT,
- "contentType" TEXT NOT NULL,
- "blob" BLOB NOT NULL,
- "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updatedAt" DATETIME NOT NULL,
- "carModelsGalleryId" TEXT NOT NULL,
- CONSTRAINT "CarModelsGalleryImage_carModelsGalleryId_fkey" FOREIGN KEY ("carModelsGalleryId") REFERENCES "CarModelsGallery" ("id") ON DELETE CASCADE ON UPDATE CASCADE
-);
-
--- CreateTable
-CREATE TABLE "CarModelFacility" (
- "id" TEXT NOT NULL PRIMARY KEY,
- "name" TEXT NOT NULL,
- "iconName" TEXT
-);
-
--- CreateTable
-CREATE TABLE "Page" (
- "id" TEXT NOT NULL PRIMARY KEY,
- "url" TEXT NOT NULL,
- "title" TEXT NOT NULL,
- "content" TEXT NOT NULL,
- "seo" TEXT,
- "visibility" BOOLEAN NOT NULL DEFAULT false,
- "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updatedAt" DATETIME NOT NULL
-);
-
--- CreateTable
-CREATE TABLE "PageImage" (
- "id" TEXT NOT NULL PRIMARY KEY,
- "altText" TEXT,
- "contentType" TEXT NOT NULL,
- "blob" BLOB NOT NULL,
- "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updatedAt" DATETIME NOT NULL,
- "pageId" TEXT NOT NULL,
- CONSTRAINT "PageImage_pageId_fkey" FOREIGN KEY ("pageId") REFERENCES "Page" ("id") ON DELETE CASCADE ON UPDATE CASCADE
-);
-
--- CreateTable
-CREATE TABLE "_CarModelToCarModelFacility" (
- "A" TEXT NOT NULL,
- "B" TEXT NOT NULL,
- CONSTRAINT "_CarModelToCarModelFacility_A_fkey" FOREIGN KEY ("A") REFERENCES "CarModel" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
- CONSTRAINT "_CarModelToCarModelFacility_B_fkey" FOREIGN KEY ("B") REFERENCES "CarModelFacility" ("id") ON DELETE CASCADE ON UPDATE CASCADE
-);
-
--- CreateTable
-CREATE TABLE "_galleryImages" (
- "A" TEXT NOT NULL,
- "B" TEXT NOT NULL,
- CONSTRAINT "_galleryImages_A_fkey" FOREIGN KEY ("A") REFERENCES "CarModel" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
- CONSTRAINT "_galleryImages_B_fkey" FOREIGN KEY ("B") REFERENCES "CarModelsGalleryImage" ("id") ON DELETE CASCADE ON UPDATE CASCADE
-);
-
--- CreateTable
-CREATE TABLE "_previewImages" (
- "A" TEXT NOT NULL,
- "B" TEXT NOT NULL,
- CONSTRAINT "_previewImages_A_fkey" FOREIGN KEY ("A") REFERENCES "CarModel" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
- CONSTRAINT "_previewImages_B_fkey" FOREIGN KEY ("B") REFERENCES "CarModelsGalleryImage" ("id") ON DELETE CASCADE ON UPDATE CASCADE
-);
-
--- CreateIndex
-CREATE UNIQUE INDEX "CarModel_url_key" ON "CarModel"("url");
-
--- CreateIndex
-CREATE UNIQUE INDEX "CarModelsGallery_id_key" ON "CarModelsGallery"("id");
-
--- CreateIndex
-CREATE INDEX "CarModelsGalleryImage_carModelsGalleryId_idx" ON "CarModelsGalleryImage"("carModelsGalleryId");
-
--- CreateIndex
-CREATE UNIQUE INDEX "CarModelFacility_id_key" ON "CarModelFacility"("id");
-
--- CreateIndex
-CREATE UNIQUE INDEX "Page_url_key" ON "Page"("url");
-
--- CreateIndex
-CREATE INDEX "PageImage_pageId_idx" ON "PageImage"("pageId");
-
--- CreateIndex
-CREATE UNIQUE INDEX "_CarModelToCarModelFacility_AB_unique" ON "_CarModelToCarModelFacility"("A", "B");
-
--- CreateIndex
-CREATE INDEX "_CarModelToCarModelFacility_B_index" ON "_CarModelToCarModelFacility"("B");
-
--- CreateIndex
-CREATE UNIQUE INDEX "_galleryImages_AB_unique" ON "_galleryImages"("A", "B");
-
--- CreateIndex
-CREATE INDEX "_galleryImages_B_index" ON "_galleryImages"("B");
-
--- CreateIndex
-CREATE UNIQUE INDEX "_previewImages_AB_unique" ON "_previewImages"("A", "B");
-
--- CreateIndex
-CREATE INDEX "_previewImages_B_index" ON "_previewImages"("B");
diff --git a/prisma/migrations/20231212082435_car_brand_icon_logo/migration.sql b/prisma/migrations/20231212082435_car_brand_icon_logo/migration.sql
deleted file mode 100644
index 5fa0efb..0000000
--- a/prisma/migrations/20231212082435_car_brand_icon_logo/migration.sql
+++ /dev/null
@@ -1,2 +0,0 @@
--- AlterTable
-ALTER TABLE "CarBrand" ADD COLUMN "icon" TEXT;
diff --git a/prisma/migrations/20231212082952_logo_icon_car_brand/migration.sql b/prisma/migrations/20231212082952_logo_icon_car_brand/migration.sql
deleted file mode 100644
index 9b73031..0000000
--- a/prisma/migrations/20231212082952_logo_icon_car_brand/migration.sql
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- Warnings:
-
- - You are about to drop the column `icon` on the `CarBrand` table. All the data in the column will be lost.
-
-*/
--- RedefineTables
-PRAGMA foreign_keys=OFF;
-CREATE TABLE "new_CarBrand" (
- "id" TEXT NOT NULL PRIMARY KEY,
- "url" TEXT NOT NULL,
- "title" TEXT NOT NULL,
- "description" TEXT NOT NULL,
- "logoIcon" TEXT,
- "seo" TEXT,
- "visibility" BOOLEAN NOT NULL DEFAULT false,
- "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updatedAt" DATETIME NOT NULL
-);
-INSERT INTO "new_CarBrand" ("createdAt", "description", "id", "seo", "title", "updatedAt", "url", "visibility") SELECT "createdAt", "description", "id", "seo", "title", "updatedAt", "url", "visibility" FROM "CarBrand";
-DROP TABLE "CarBrand";
-ALTER TABLE "new_CarBrand" RENAME TO "CarBrand";
-CREATE UNIQUE INDEX "CarBrand_url_key" ON "CarBrand"("url");
-PRAGMA foreign_key_check;
-PRAGMA foreign_keys=ON;
diff --git a/prisma/migrations/20231212083433_car_models_preps/migration.sql b/prisma/migrations/20231212083433_car_models_preps/migration.sql
deleted file mode 100644
index 2f292e4..0000000
--- a/prisma/migrations/20231212083433_car_models_preps/migration.sql
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- Warnings:
-
- - You are about to drop the column `additionalNightPrice1` on the `CarModel` table. All the data in the column will be lost.
- - You are about to drop the column `additionalNightPrice2` on the `CarModel` table. All the data in the column will be lost.
- - You are about to drop the column `additionalNightPrice3` on the `CarModel` table. All the data in the column will be lost.
- - You are about to drop the column `maxGuests` on the `CarModel` table. All the data in the column will be lost.
- - You are about to drop the column `numberOfGuestsForDefaultPrice` on the `CarModel` table. All the data in the column will be lost.
- - You are about to drop the column `price1` on the `CarModel` table. All the data in the column will be lost.
- - You are about to drop the column `price2` on the `CarModel` table. All the data in the column will be lost.
- - You are about to drop the column `price3` on the `CarModel` table. All the data in the column will be lost.
-
-*/
--- RedefineTables
-PRAGMA foreign_keys=OFF;
-CREATE TABLE "new_CarModel" (
- "id" TEXT NOT NULL PRIMARY KEY,
- "url" TEXT NOT NULL,
- "title" TEXT NOT NULL,
- "seo" TEXT,
- "visibility" BOOLEAN NOT NULL DEFAULT false,
- "description" TEXT,
- "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updatedAt" DATETIME NOT NULL
-);
-INSERT INTO "new_CarModel" ("createdAt", "description", "id", "seo", "title", "updatedAt", "url", "visibility") SELECT "createdAt", "description", "id", "seo", "title", "updatedAt", "url", "visibility" FROM "CarModel";
-DROP TABLE "CarModel";
-ALTER TABLE "new_CarModel" RENAME TO "CarModel";
-CREATE UNIQUE INDEX "CarModel_url_key" ON "CarModel"("url");
-PRAGMA foreign_key_check;
-PRAGMA foreign_keys=ON;
diff --git a/prisma/migrations/20231212084029_car_models_and_brands_connection/migration.sql b/prisma/migrations/20231212084029_car_models_and_brands_connection/migration.sql
deleted file mode 100644
index 760a3ca..0000000
--- a/prisma/migrations/20231212084029_car_models_and_brands_connection/migration.sql
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- Warnings:
-
- - Added the required column `carBrandId` to the `CarModel` table without a default value. This is not possible if the table is not empty.
-
-*/
--- RedefineTables
-PRAGMA foreign_keys=OFF;
-CREATE TABLE "new_CarModel" (
- "id" TEXT NOT NULL PRIMARY KEY,
- "url" TEXT NOT NULL,
- "title" TEXT NOT NULL,
- "seo" TEXT,
- "visibility" BOOLEAN NOT NULL DEFAULT false,
- "description" TEXT,
- "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updatedAt" DATETIME NOT NULL,
- "carBrandId" TEXT NOT NULL,
- CONSTRAINT "CarModel_carBrandId_fkey" FOREIGN KEY ("carBrandId") REFERENCES "CarBrand" ("id") ON DELETE CASCADE ON UPDATE CASCADE
-);
-INSERT INTO "new_CarModel" ("createdAt", "description", "id", "seo", "title", "updatedAt", "url", "visibility") SELECT "createdAt", "description", "id", "seo", "title", "updatedAt", "url", "visibility" FROM "CarModel";
-DROP TABLE "CarModel";
-ALTER TABLE "new_CarModel" RENAME TO "CarModel";
-CREATE UNIQUE INDEX "CarModel_url_key" ON "CarModel"("url");
-PRAGMA foreign_key_check;
-PRAGMA foreign_keys=ON;
diff --git a/prisma/migrations/20231212104451_country_for_brand/migration.sql b/prisma/migrations/20231212104451_country_for_brand/migration.sql
deleted file mode 100644
index f32dd93..0000000
--- a/prisma/migrations/20231212104451_country_for_brand/migration.sql
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- Warnings:
-
- - Added the required column `countrOfOrigin` to the `CarBrand` table without a default value. This is not possible if the table is not empty.
-
-*/
--- RedefineTables
-PRAGMA foreign_keys=OFF;
-CREATE TABLE "new_CarBrand" (
- "id" TEXT NOT NULL PRIMARY KEY,
- "url" TEXT NOT NULL,
- "title" TEXT NOT NULL,
- "description" TEXT NOT NULL,
- "countrOfOrigin" TEXT NOT NULL,
- "logoIcon" TEXT,
- "seo" TEXT,
- "visibility" BOOLEAN NOT NULL DEFAULT false,
- "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updatedAt" DATETIME NOT NULL
-);
-INSERT INTO "new_CarBrand" ("createdAt", "description", "id", "logoIcon", "seo", "title", "updatedAt", "url", "visibility") SELECT "createdAt", "description", "id", "logoIcon", "seo", "title", "updatedAt", "url", "visibility" FROM "CarBrand";
-DROP TABLE "CarBrand";
-ALTER TABLE "new_CarBrand" RENAME TO "CarBrand";
-CREATE UNIQUE INDEX "CarBrand_url_key" ON "CarBrand"("url");
-PRAGMA foreign_key_check;
-PRAGMA foreign_keys=ON;
diff --git a/prisma/migrations/20231212104650_spelling_error/migration.sql b/prisma/migrations/20231212104650_spelling_error/migration.sql
deleted file mode 100644
index 054cd9e..0000000
--- a/prisma/migrations/20231212104650_spelling_error/migration.sql
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- Warnings:
-
- - You are about to drop the column `countrOfOrigin` on the `CarBrand` table. All the data in the column will be lost.
- - Added the required column `countryOfOrigin` to the `CarBrand` table without a default value. This is not possible if the table is not empty.
-
-*/
--- RedefineTables
-PRAGMA foreign_keys=OFF;
-CREATE TABLE "new_CarBrand" (
- "id" TEXT NOT NULL PRIMARY KEY,
- "url" TEXT NOT NULL,
- "title" TEXT NOT NULL,
- "description" TEXT NOT NULL,
- "countryOfOrigin" TEXT NOT NULL,
- "logoIcon" TEXT,
- "seo" TEXT,
- "visibility" BOOLEAN NOT NULL DEFAULT false,
- "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updatedAt" DATETIME NOT NULL
-);
-INSERT INTO "new_CarBrand" ("createdAt", "description", "id", "logoIcon", "seo", "title", "updatedAt", "url", "visibility") SELECT "createdAt", "description", "id", "logoIcon", "seo", "title", "updatedAt", "url", "visibility" FROM "CarBrand";
-DROP TABLE "CarBrand";
-ALTER TABLE "new_CarBrand" RENAME TO "CarBrand";
-CREATE UNIQUE INDEX "CarBrand_url_key" ON "CarBrand"("url");
-PRAGMA foreign_key_check;
-PRAGMA foreign_keys=ON;
diff --git a/prisma/migrations/20231212105208_car_models_expantion/migration.sql b/prisma/migrations/20231212105208_car_models_expantion/migration.sql
deleted file mode 100644
index 918546a..0000000
--- a/prisma/migrations/20231212105208_car_models_expantion/migration.sql
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- Warnings:
-
- - Added the required column `year` to the `CarModel` table without a default value. This is not possible if the table is not empty.
-
-*/
--- RedefineTables
-PRAGMA foreign_keys=OFF;
-CREATE TABLE "new_CarModel" (
- "id" TEXT NOT NULL PRIMARY KEY,
- "url" TEXT NOT NULL,
- "title" TEXT NOT NULL,
- "visibility" BOOLEAN NOT NULL DEFAULT false,
- "year" TEXT NOT NULL,
- "description" TEXT,
- "seo" TEXT,
- "videoLinks" TEXT,
- "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updatedAt" DATETIME NOT NULL,
- "carBrandId" TEXT NOT NULL,
- CONSTRAINT "CarModel_carBrandId_fkey" FOREIGN KEY ("carBrandId") REFERENCES "CarBrand" ("id") ON DELETE CASCADE ON UPDATE CASCADE
-);
-INSERT INTO "new_CarModel" ("carBrandId", "createdAt", "description", "id", "seo", "title", "updatedAt", "url", "visibility") SELECT "carBrandId", "createdAt", "description", "id", "seo", "title", "updatedAt", "url", "visibility" FROM "CarModel";
-DROP TABLE "CarModel";
-ALTER TABLE "new_CarModel" RENAME TO "CarModel";
-CREATE UNIQUE INDEX "CarModel_url_key" ON "CarModel"("url");
-PRAGMA foreign_key_check;
-PRAGMA foreign_keys=ON;
diff --git a/prisma/migrations/20231212124728_year_to_int/migration.sql b/prisma/migrations/20231212124728_year_to_int/migration.sql
deleted file mode 100644
index dda8c07..0000000
--- a/prisma/migrations/20231212124728_year_to_int/migration.sql
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- Warnings:
-
- - You are about to alter the column `year` on the `CarModel` table. The data in that column could be lost. The data in that column will be cast from `String` to `Int`.
-
-*/
--- RedefineTables
-PRAGMA foreign_keys=OFF;
-CREATE TABLE "new_CarModel" (
- "id" TEXT NOT NULL PRIMARY KEY,
- "url" TEXT NOT NULL,
- "title" TEXT NOT NULL,
- "visibility" BOOLEAN NOT NULL DEFAULT false,
- "year" INTEGER NOT NULL,
- "description" TEXT,
- "seo" TEXT,
- "videoLinks" TEXT,
- "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updatedAt" DATETIME NOT NULL,
- "carBrandId" TEXT NOT NULL,
- CONSTRAINT "CarModel_carBrandId_fkey" FOREIGN KEY ("carBrandId") REFERENCES "CarBrand" ("id") ON DELETE CASCADE ON UPDATE CASCADE
-);
-INSERT INTO "new_CarModel" ("carBrandId", "createdAt", "description", "id", "seo", "title", "updatedAt", "url", "videoLinks", "visibility", "year") SELECT "carBrandId", "createdAt", "description", "id", "seo", "title", "updatedAt", "url", "videoLinks", "visibility", "year" FROM "CarModel";
-DROP TABLE "CarModel";
-ALTER TABLE "new_CarModel" RENAME TO "CarModel";
-CREATE UNIQUE INDEX "CarModel_url_key" ON "CarModel"("url");
-PRAGMA foreign_key_check;
-PRAGMA foreign_keys=ON;
diff --git a/prisma/migrations/20231212142454_car_models_foreign_key_and_indexing/migration.sql b/prisma/migrations/20231212142454_car_models_foreign_key_and_indexing/migration.sql
deleted file mode 100644
index 1a04820..0000000
--- a/prisma/migrations/20231212142454_car_models_foreign_key_and_indexing/migration.sql
+++ /dev/null
@@ -1,5 +0,0 @@
--- CreateIndex
-CREATE INDEX "CarModel_carBrandId_idx" ON "CarModel"("carBrandId");
-
--- CreateIndex
-CREATE INDEX "CarModel_carBrandId_updatedAt_idx" ON "CarModel"("carBrandId", "updatedAt");
diff --git a/prisma/migrations/20231212151413_dealer_schema/migration.sql b/prisma/migrations/20231212151413_dealer_schema/migration.sql
deleted file mode 100644
index bc86a69..0000000
--- a/prisma/migrations/20231212151413_dealer_schema/migration.sql
+++ /dev/null
@@ -1,29 +0,0 @@
--- CreateTable
-CREATE TABLE "Dealer" (
- "id" TEXT NOT NULL PRIMARY KEY,
- "url" TEXT NOT NULL,
- "name" TEXT NOT NULL,
- "state" TEXT NOT NULL,
- "city" TEXT NOT NULL,
- "address" TEXT NOT NULL,
- "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updatedAt" DATETIME NOT NULL
-);
-
--- CreateTable
-CREATE TABLE "DealerImage" (
- "id" TEXT NOT NULL PRIMARY KEY,
- "altText" TEXT,
- "contentType" TEXT NOT NULL,
- "blob" BLOB NOT NULL,
- "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updatedAt" DATETIME NOT NULL,
- "dealerId" TEXT NOT NULL,
- CONSTRAINT "DealerImage_dealerId_fkey" FOREIGN KEY ("dealerId") REFERENCES "Dealer" ("id") ON DELETE CASCADE ON UPDATE CASCADE
-);
-
--- CreateIndex
-CREATE UNIQUE INDEX "Dealer_url_key" ON "Dealer"("url");
-
--- CreateIndex
-CREATE INDEX "DealerImage_dealerId_idx" ON "DealerImage"("dealerId");
diff --git a/prisma/migrations/20231212073816_car_brand_and_its_gallery/migration.sql b/prisma/migrations/20231221141742_removing_unnecessary_models/migration.sql
similarity index 56%
rename from prisma/migrations/20231212073816_car_brand_and_its_gallery/migration.sql
rename to prisma/migrations/20231221141742_removing_unnecessary_models/migration.sql
index 90aa084..363b856 100644
--- a/prisma/migrations/20231212073816_car_brand_and_its_gallery/migration.sql
+++ b/prisma/migrations/20231221141742_removing_unnecessary_models/migration.sql
@@ -1,9 +1,9 @@
-- CreateTable
-CREATE TABLE "CarBrand" (
+CREATE TABLE "Page" (
"id" TEXT NOT NULL PRIMARY KEY,
"url" TEXT NOT NULL,
"title" TEXT NOT NULL,
- "description" TEXT NOT NULL,
+ "content" TEXT NOT NULL,
"seo" TEXT,
"visibility" BOOLEAN NOT NULL DEFAULT false,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
@@ -11,19 +11,19 @@ CREATE TABLE "CarBrand" (
);
-- CreateTable
-CREATE TABLE "CarBrandImage" (
+CREATE TABLE "PageImage" (
"id" TEXT NOT NULL PRIMARY KEY,
"altText" TEXT,
"contentType" TEXT NOT NULL,
"blob" BLOB NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
- "carBrandId" TEXT NOT NULL,
- CONSTRAINT "CarBrandImage_carBrandId_fkey" FOREIGN KEY ("carBrandId") REFERENCES "CarBrand" ("id") ON DELETE CASCADE ON UPDATE CASCADE
+ "pageId" TEXT NOT NULL,
+ CONSTRAINT "PageImage_pageId_fkey" FOREIGN KEY ("pageId") REFERENCES "Page" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateIndex
-CREATE UNIQUE INDEX "CarBrand_url_key" ON "CarBrand"("url");
+CREATE UNIQUE INDEX "Page_url_key" ON "Page"("url");
-- CreateIndex
-CREATE INDEX "CarBrandImage_carBrandId_idx" ON "CarBrandImage"("carBrandId");
+CREATE INDEX "PageImage_pageId_idx" ON "PageImage"("pageId");
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index 358f810..791602d 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -168,89 +168,6 @@ model Connection {
@@unique([providerName, providerId])
}
-model CarBrand {
- id String @id @default(cuid())
- url String @unique
- title String
- description String
- countryOfOrigin String
- logoIcon String?
- seo String?
- visibility Boolean @default(false)
- images CarBrandImage[]
- carModels CarModel[]
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
-}
-
-model CarBrandImage {
- id String @id @default(cuid())
- altText String?
- contentType String
- blob Bytes
-
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
-
- carBrand CarBrand @relation(fields: [carBrandId], references: [id], onDelete: Cascade, onUpdate: Cascade)
- carBrandId String
-
- // non-unique foreign key
- @@index([carBrandId])
-}
-
-model CarModel {
- id String @id @default(cuid())
- url String @unique
- title String
- visibility Boolean @default(false)
- year Int
- description String?
- seo String?
- videoLinks String?
- carModelFacility CarModelFacility[]
- carModelGalleryImages CarModelsGalleryImage[] @relation("galleryImages")
- carModelPreviewImages CarModelsGalleryImage[] @relation("previewImages")
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- carBrand CarBrand @relation(fields: [carBrandId], references: [id], onDelete: Cascade, onUpdate: Cascade)
- carBrandId String
-
- // non-unique foreign key
- @@index([carBrandId])
- // This helps our order by in the user search a LOT
- @@index([carBrandId, updatedAt])
-}
-
-model CarModelsGallery {
- id String @id @unique @default(cuid())
- name String
- images CarModelsGalleryImage[]
-}
-
-model CarModelsGalleryImage {
- id String @id @default(cuid())
- altText String?
- contentType String
- blob Bytes
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- carModelsGallery CarModelsGallery @relation(fields: [carModelsGalleryId], references: [id], onDelete: Cascade, onUpdate: Cascade)
- carModelsGalleryId String
- carModelGalleryImages CarModel[] @relation("galleryImages")
- carModelPreviewImages CarModel[] @relation("previewImages")
-
- // non-unique foreign key
- @@index([carModelsGalleryId])
-}
-
-model CarModelFacility {
- id String @id @unique @default(cuid())
- name String
- iconName String?
- carModels CarModel[]
-}
-
model Page {
id String @id @default(cuid())
url String @unique
@@ -281,32 +198,3 @@ model PageImage {
// non-unique foreign key
@@index([pageId])
}
-
-model Dealer {
- id String @id @default(cuid())
- url String @unique
- name String
- state String
- city String
- address String
- images DealerImage[]
-
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
-}
-
-model DealerImage {
- id String @id @default(cuid())
- altText String?
- contentType String
- blob Bytes
-
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
-
- dealer Dealer @relation(fields: [dealerId], references: [id], onDelete: Cascade, onUpdate: Cascade)
- dealerId String
-
- // non-unique foreign key
- @@index([dealerId])
-}