create-nextjs-cms 0.6.4 → 0.6.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/templates/default/components/form/Form.tsx +8 -0
- package/templates/default/components/form/FormInputs.tsx +4 -0
- package/templates/default/components/form/helpers/_section-hot-reload.js +1 -1
- package/templates/default/components/form/inputs/SlugFormInput.tsx +129 -0
- package/templates/default/components/ui/input-group.tsx +54 -0
- package/templates/default/dynamic-schemas/schema.ts +383 -0
- package/templates/default/package.json +2 -2
package/package.json
CHANGED
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
RichTextFieldClientConfig,
|
|
25
25
|
SelectFieldClientConfig,
|
|
26
26
|
SelectMultipleFieldClientConfig,
|
|
27
|
+
SlugFieldClientConfig,
|
|
27
28
|
TextAreaFieldClientConfig,
|
|
28
29
|
TextFieldClientConfig,
|
|
29
30
|
VideoFieldClientConfig,
|
|
@@ -44,6 +45,7 @@ import {
|
|
|
44
45
|
colorFieldSchema,
|
|
45
46
|
mapFieldSchema,
|
|
46
47
|
passwordFieldSchema,
|
|
48
|
+
slugFieldSchema,
|
|
47
49
|
} from 'nextjs-cms/validators'
|
|
48
50
|
|
|
49
51
|
import { ConditionalField, FieldType } from 'nextjs-cms/core/types'
|
|
@@ -191,6 +193,12 @@ export default function Form({
|
|
|
191
193
|
[input.name]: passwordFieldSchema(input as PasswordFieldClientConfig),
|
|
192
194
|
})
|
|
193
195
|
break
|
|
196
|
+
|
|
197
|
+
case 'slug':
|
|
198
|
+
schema = schema.extend({
|
|
199
|
+
[input.name]: slugFieldSchema(input as SlugFieldClientConfig),
|
|
200
|
+
})
|
|
201
|
+
break
|
|
194
202
|
}
|
|
195
203
|
})
|
|
196
204
|
})
|
|
@@ -14,6 +14,7 @@ import MapFormInput from '@/components/form/inputs/MapFormInput'
|
|
|
14
14
|
import PasswordFormInput from '@/components/form/inputs/PasswordFormInput'
|
|
15
15
|
import TextareaFormInput from '@/components/form/inputs/TextareaFormInput'
|
|
16
16
|
import VideoFormInput from '@/components/form/inputs/VideoFormInput'
|
|
17
|
+
import SlugFormInput from '@/components/form/inputs/SlugFormInput'
|
|
17
18
|
import type { FieldClientConfig } from 'nextjs-cms/core/fields'
|
|
18
19
|
import {
|
|
19
20
|
CheckboxFieldClientConfig,
|
|
@@ -31,6 +32,7 @@ import {
|
|
|
31
32
|
TextAreaFieldClientConfig,
|
|
32
33
|
TextFieldClientConfig,
|
|
33
34
|
VideoFieldClientConfig,
|
|
35
|
+
SlugFieldClientConfig,
|
|
34
36
|
} from 'nextjs-cms/core/fields'
|
|
35
37
|
|
|
36
38
|
export default function FormInputs({ inputs, sectionName }: { inputs: FieldClientConfig[]; sectionName: string }) {
|
|
@@ -99,6 +101,8 @@ export default function FormInputs({ inputs, sectionName }: { inputs: FieldClien
|
|
|
99
101
|
case 'checkbox':
|
|
100
102
|
// case 'permission':
|
|
101
103
|
return <CheckboxFormInput input={input as CheckboxFieldClientConfig} key={input.name} />
|
|
104
|
+
case 'slug':
|
|
105
|
+
return <SlugFormInput input={input as SlugFieldClientConfig} key={input.name} />
|
|
102
106
|
default:
|
|
103
107
|
return null
|
|
104
108
|
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import React, { useCallback, useEffect, useRef } from 'react'
|
|
4
|
+
import FormInputElement from '@/components/form/FormInputElement'
|
|
5
|
+
import type { SlugFieldClientConfig } from 'nextjs-cms/core/fields'
|
|
6
|
+
import { useFormContext, useController, useWatch } from 'react-hook-form'
|
|
7
|
+
import { InputGroup, InputGroupInput, InputGroupAddon } from '@/components/ui/input-group'
|
|
8
|
+
import { Link2 } from 'lucide-react'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Convert a string to a URL-friendly slug (for real-time input).
|
|
12
|
+
* - Converts to lowercase
|
|
13
|
+
* - Replaces spaces with hyphens
|
|
14
|
+
* - Removes special characters (keeps letters from any language, numbers, and hyphens)
|
|
15
|
+
* - Collapses multiple consecutive hyphens into one
|
|
16
|
+
* - Keeps trailing hyphen (user might still be typing)
|
|
17
|
+
*/
|
|
18
|
+
function toSlugLive(value: string): string {
|
|
19
|
+
return value
|
|
20
|
+
.toLowerCase()
|
|
21
|
+
.replace(/\s+/g, '-') // Replace spaces with hyphens
|
|
22
|
+
.replace(/[^\p{L}\p{N}-]/gu, '') // Remove special characters (keep Unicode letters/numbers)
|
|
23
|
+
.replace(/-+/g, '-') // Collapse multiple hyphens
|
|
24
|
+
.replace(/^-/, '') // Remove leading hyphen only
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Normalize a slug (for blur/final value).
|
|
29
|
+
* Same as toSlugLive but also trims and removes trailing hyphens.
|
|
30
|
+
*/
|
|
31
|
+
function toSlugFinal(value: string): string {
|
|
32
|
+
return toSlugLive(value.trim()).replace(/-$/, '') // Remove trailing hyphen
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default function SlugFormInput({
|
|
36
|
+
input,
|
|
37
|
+
direction,
|
|
38
|
+
disabled = false,
|
|
39
|
+
}: {
|
|
40
|
+
input: SlugFieldClientConfig
|
|
41
|
+
direction?: 'row' | 'col'
|
|
42
|
+
disabled?: boolean
|
|
43
|
+
}) {
|
|
44
|
+
const { control } = useFormContext()
|
|
45
|
+
const {
|
|
46
|
+
field,
|
|
47
|
+
fieldState: { error },
|
|
48
|
+
} = useController({
|
|
49
|
+
name: input.name,
|
|
50
|
+
control,
|
|
51
|
+
defaultValue: input.value ?? '',
|
|
52
|
+
disabled: disabled,
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
// Watch the source field value
|
|
56
|
+
const sourceFieldValue = useWatch({
|
|
57
|
+
control,
|
|
58
|
+
name: input.forFieldName,
|
|
59
|
+
defaultValue: '',
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
// Track previous source value to only update when it actually changes
|
|
63
|
+
const previousSourceValueRef = useRef<string>(sourceFieldValue ?? '')
|
|
64
|
+
|
|
65
|
+
// Auto-generate slug from source field when it changes
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
const currentSourceValue = sourceFieldValue ?? ''
|
|
68
|
+
|
|
69
|
+
// Only update if the source field value actually changed
|
|
70
|
+
if (currentSourceValue !== previousSourceValueRef.current) {
|
|
71
|
+
previousSourceValueRef.current = currentSourceValue
|
|
72
|
+
|
|
73
|
+
if (currentSourceValue) {
|
|
74
|
+
const newSlug = toSlugFinal(currentSourceValue)
|
|
75
|
+
field.onChange(newSlug)
|
|
76
|
+
} else {
|
|
77
|
+
field.onChange('')
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}, [sourceFieldValue, field])
|
|
81
|
+
|
|
82
|
+
// Handle manual changes to the slug field
|
|
83
|
+
const handleChange = useCallback(
|
|
84
|
+
(e: React.ChangeEvent<HTMLInputElement>) => {
|
|
85
|
+
const newValue = e.target.value
|
|
86
|
+
// Apply slug normalization in real-time
|
|
87
|
+
field.onChange(toSlugLive(newValue))
|
|
88
|
+
},
|
|
89
|
+
[field],
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
// Handle blur - finalize the slug value (remove trailing hyphens)
|
|
93
|
+
const handleBlur = useCallback(() => {
|
|
94
|
+
field.onBlur()
|
|
95
|
+
if (field.value) {
|
|
96
|
+
const finalSlug = toSlugFinal(field.value)
|
|
97
|
+
if (finalSlug !== field.value) {
|
|
98
|
+
field.onChange(finalSlug)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}, [field])
|
|
102
|
+
|
|
103
|
+
return (
|
|
104
|
+
<FormInputElement
|
|
105
|
+
validationError={error}
|
|
106
|
+
value={input.value}
|
|
107
|
+
readonly={input.readonly}
|
|
108
|
+
label={input.label}
|
|
109
|
+
required={input.required}
|
|
110
|
+
>
|
|
111
|
+
<InputGroup className='bg-input'>
|
|
112
|
+
<InputGroupAddon align='inline-start' title='Auto-generated from linked field'>
|
|
113
|
+
<Link2 className='h-4 w-4' />
|
|
114
|
+
</InputGroupAddon>
|
|
115
|
+
<InputGroupInput
|
|
116
|
+
placeholder={input.placeholder ? input.placeholder : input.label}
|
|
117
|
+
type='text'
|
|
118
|
+
readOnly={disabled}
|
|
119
|
+
disabled={field.disabled}
|
|
120
|
+
name={field.name}
|
|
121
|
+
onChange={handleChange}
|
|
122
|
+
onBlur={handleBlur}
|
|
123
|
+
value={field.value ?? ''}
|
|
124
|
+
ref={field.ref}
|
|
125
|
+
/>
|
|
126
|
+
</InputGroup>
|
|
127
|
+
</FormInputElement>
|
|
128
|
+
)
|
|
129
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import { cn } from '@/lib/utils'
|
|
5
|
+
|
|
6
|
+
const InputGroup = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
7
|
+
({ className, ...props }, ref) => (
|
|
8
|
+
<div
|
|
9
|
+
ref={ref}
|
|
10
|
+
className={cn(
|
|
11
|
+
'flex items-stretch overflow-hidden rounded shadow-xs ring-2 ring-gray-300 outline-0 hover:ring-gray-400 focus-within:ring-blue-500 hover:focus-within:ring-blue-500',
|
|
12
|
+
className,
|
|
13
|
+
)}
|
|
14
|
+
{...props}
|
|
15
|
+
/>
|
|
16
|
+
),
|
|
17
|
+
)
|
|
18
|
+
InputGroup.displayName = 'InputGroup'
|
|
19
|
+
|
|
20
|
+
const InputGroupInput = React.forwardRef<HTMLInputElement, React.InputHTMLAttributes<HTMLInputElement>>(
|
|
21
|
+
({ className, ...props }, ref) => (
|
|
22
|
+
<input
|
|
23
|
+
ref={ref}
|
|
24
|
+
className={cn(
|
|
25
|
+
'placeholder:text-muted-foreground flex h-9 w-full bg-transparent px-3 py-1 text-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50',
|
|
26
|
+
className,
|
|
27
|
+
)}
|
|
28
|
+
{...props}
|
|
29
|
+
/>
|
|
30
|
+
),
|
|
31
|
+
)
|
|
32
|
+
InputGroupInput.displayName = 'InputGroupInput'
|
|
33
|
+
|
|
34
|
+
interface InputGroupAddonProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
35
|
+
align?: 'inline-start' | 'inline-end'
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const InputGroupAddon = React.forwardRef<HTMLDivElement, InputGroupAddonProps>(
|
|
39
|
+
({ className, align = 'inline-start', ...props }, ref) => (
|
|
40
|
+
<div
|
|
41
|
+
ref={ref}
|
|
42
|
+
className={cn(
|
|
43
|
+
'text-muted-foreground bg-muted flex items-center justify-center px-3 text-sm',
|
|
44
|
+
align === 'inline-start' && 'order-first border-e border-gray-300',
|
|
45
|
+
align === 'inline-end' && 'order-last border-s border-gray-300',
|
|
46
|
+
className,
|
|
47
|
+
)}
|
|
48
|
+
{...props}
|
|
49
|
+
/>
|
|
50
|
+
),
|
|
51
|
+
)
|
|
52
|
+
InputGroupAddon.displayName = 'InputGroupAddon'
|
|
53
|
+
|
|
54
|
+
export { InputGroup, InputGroupInput, InputGroupAddon }
|
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
import {mysqlTable,int,longtext,mysqlEnum,varchar,boolean,double,timestamp} from 'drizzle-orm/mysql-core'
|
|
2
|
+
|
|
3
|
+
export const AppInfoTable = mysqlTable('app_info', {
|
|
4
|
+
id: int('id').autoincrement().notNull().primaryKey(),
|
|
5
|
+
aboutEn: longtext('about_en').notNull(),
|
|
6
|
+
aboutAr: longtext('about_ar').notNull(),
|
|
7
|
+
aboutTr: longtext('about_tr').notNull(),
|
|
8
|
+
privacyEn: longtext('privacy_en').notNull(),
|
|
9
|
+
privacyAr: longtext('privacy_ar').notNull(),
|
|
10
|
+
privacyTr: longtext('privacy_tr').notNull()
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
export const UserReportsTable = mysqlTable('user_reports', {
|
|
15
|
+
id: int('id').autoincrement().notNull().primaryKey(),
|
|
16
|
+
contentType: mysqlEnum('content_type', ['ad', 'user']).notNull(),
|
|
17
|
+
reportType: mysqlEnum('report_type', ['explicit_content', 'wrong_information', 'no_longer_available', 'user_not_responsive', 'other']).notNull(),
|
|
18
|
+
contentId: int('content_id').notNull(),
|
|
19
|
+
catId: int('cat_id').notNull(),
|
|
20
|
+
userId: int('user_id'),
|
|
21
|
+
appId: varchar('app_id', { length: 36 }).notNull(),
|
|
22
|
+
title: varchar('title', { length: 255 }).notNull(),
|
|
23
|
+
slug: varchar('slug', { length: 255 }).notNull()
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
export const FeaturedSliderTable = mysqlTable('featured_slider', {
|
|
28
|
+
id: int('id').autoincrement().notNull().primaryKey(),
|
|
29
|
+
image: varchar('image', { length: 255 }).notNull(),
|
|
30
|
+
titleEn: varchar('title_en', { length: 255 }).notNull(),
|
|
31
|
+
titleAr: varchar('title_ar', { length: 255 }).notNull(),
|
|
32
|
+
titleTr: varchar('title_tr', { length: 255 }).notNull(),
|
|
33
|
+
descEn: longtext('desc_en').notNull(),
|
|
34
|
+
descAr: longtext('desc_ar').notNull(),
|
|
35
|
+
descTr: longtext('desc_tr').notNull()
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
export const MenuSettingsTable = mysqlTable('menu_settings', {
|
|
40
|
+
id: int('id').autoincrement().notNull().primaryKey(),
|
|
41
|
+
taxRate: varchar('tax_rate', { length: 255 }),
|
|
42
|
+
hideSlider: boolean('hide_slider')
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
export const ServicesTable = mysqlTable('services', {
|
|
47
|
+
id: int('id').autoincrement().notNull().primaryKey(),
|
|
48
|
+
title: varchar('title', { length: 255 }).notNull(),
|
|
49
|
+
catId: int('cat_id').notNull(),
|
|
50
|
+
coverphoto: varchar('coverphoto', { length: 255 }).notNull(),
|
|
51
|
+
price: int('price'),
|
|
52
|
+
currency: mysqlEnum('currency', ['USD', 'TRY', 'SYP']),
|
|
53
|
+
coverphotoPlaceholder: varchar('coverphoto_placeholder', { length: 255 }),
|
|
54
|
+
desc: longtext('desc'),
|
|
55
|
+
latitude: double('latitude'),
|
|
56
|
+
longitude: double('longitude'),
|
|
57
|
+
viewCount: int('view_count'),
|
|
58
|
+
status: mysqlEnum('status', ['pending_creation', 'active', 'pending_review', 'rejected', 'expired']),
|
|
59
|
+
govId: int('gov_id').notNull(),
|
|
60
|
+
districtId: int('district_id').notNull(),
|
|
61
|
+
subDistrictId: int('sub_district_id'),
|
|
62
|
+
townId: int('town_id')
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
export const RealestateTable = mysqlTable('realestate', {
|
|
67
|
+
id: int('id').autoincrement().notNull().primaryKey(),
|
|
68
|
+
catId: int('cat_id').notNull(),
|
|
69
|
+
title: varchar('title', { length: 255 }).notNull(),
|
|
70
|
+
price: int('price').notNull(),
|
|
71
|
+
currency: mysqlEnum('currency', ['USD', 'TRY', 'SYP']).notNull(),
|
|
72
|
+
spaceGross: int('space_gross').notNull(),
|
|
73
|
+
spaceNet: int('space_net').notNull(),
|
|
74
|
+
latitude: double('latitude').notNull(),
|
|
75
|
+
longitude: double('longitude').notNull(),
|
|
76
|
+
roomCount: varchar('room_count', { length: 255 }),
|
|
77
|
+
buildingAge: varchar('building_age', { length: 255 }),
|
|
78
|
+
floorCount: varchar('floor_count', { length: 255 }),
|
|
79
|
+
bathroomCount: varchar('bathroom_count', { length: 255 }),
|
|
80
|
+
floorLocation: varchar('floor_location', { length: 255 }),
|
|
81
|
+
heatingType: varchar('heating_type', { length: 255 }),
|
|
82
|
+
kitchenType: varchar('kitchen_type', { length: 255 }),
|
|
83
|
+
balcony: boolean('balcony'),
|
|
84
|
+
lift: boolean('lift'),
|
|
85
|
+
parkingType: varchar('parking_type', { length: 255 }),
|
|
86
|
+
furnished: boolean('furnished'),
|
|
87
|
+
belongsToSite: boolean('belongs_to_site'),
|
|
88
|
+
siteName: varchar('site_name', { length: 255 }),
|
|
89
|
+
installments: boolean('installments'),
|
|
90
|
+
exchangeable: boolean('exchangeable'),
|
|
91
|
+
fromWhom: varchar('from_whom', { length: 255 }),
|
|
92
|
+
buildingMembershipFees: int('building_membership_fees'),
|
|
93
|
+
deposit: int('deposit'),
|
|
94
|
+
coverphoto: varchar('coverphoto', { length: 255 }).notNull(),
|
|
95
|
+
coverphotoPlaceholder: varchar('coverphoto_placeholder', { length: 255 }),
|
|
96
|
+
desc: longtext('desc'),
|
|
97
|
+
viewCount: int('view_count'),
|
|
98
|
+
status: mysqlEnum('status', ['pending_creation', 'active', 'pending_review', 'rejected', 'expired']),
|
|
99
|
+
govId: int('gov_id').notNull(),
|
|
100
|
+
districtId: int('district_id').notNull(),
|
|
101
|
+
subDistrictId: int('sub_district_id'),
|
|
102
|
+
townId: int('town_id')
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
export const HomepageSliderTable = mysqlTable('homepage_slider', {
|
|
107
|
+
id: int('id').autoincrement().notNull().primaryKey(),
|
|
108
|
+
titleEn: varchar('title_en', { length: 255 }).notNull(),
|
|
109
|
+
titleAr: varchar('title_ar', { length: 255 }).notNull(),
|
|
110
|
+
titleTr: varchar('title_tr', { length: 255 }).notNull(),
|
|
111
|
+
subtitleEn: varchar('subtitle_en', { length: 255 }).notNull(),
|
|
112
|
+
subtitleAr: varchar('subtitle_ar', { length: 255 }).notNull(),
|
|
113
|
+
subtitleTr: varchar('subtitle_tr', { length: 255 }).notNull(),
|
|
114
|
+
photo: varchar('photo', { length: 255 }).notNull(),
|
|
115
|
+
buttonUrl: varchar('button_url', { length: 255 }),
|
|
116
|
+
buttonTextEn: varchar('button_text_en', { length: 255 }),
|
|
117
|
+
buttonTextAr: varchar('button_text_ar', { length: 255 }),
|
|
118
|
+
buttonTextTr: varchar('button_text_tr', { length: 255 }),
|
|
119
|
+
buttonUrlTarget: mysqlEnum('button_url_target', ['_blank', '_self'])
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
export const ContestSubscribersTable = mysqlTable('contest_subscribers', {
|
|
124
|
+
id: int('id').autoincrement().notNull().primaryKey(),
|
|
125
|
+
userId: int('user_id').notNull(),
|
|
126
|
+
contestId: varchar('contest_id', { length: 255 }).notNull()
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
export const ContestsTable = mysqlTable('contests', {
|
|
131
|
+
id: int('id').autoincrement().notNull().primaryKey(),
|
|
132
|
+
date: timestamp('date').notNull(),
|
|
133
|
+
prize: varchar('prize', { length: 255 }).notNull(),
|
|
134
|
+
winnerId: int('winner_id'),
|
|
135
|
+
tags: varchar('tags', { length: 255 })
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
export const NotificationsTable = mysqlTable('notifications', {
|
|
140
|
+
id: int('id').autoincrement().notNull().primaryKey(),
|
|
141
|
+
type: mysqlEnum('type', ['ad_price_updated', 'ad_updated', 'ad_activated', 'ad_pending_review', 'ad_expired', 'ad_rejected', 'ad_viewed', 'ad_favorited', 'ad_shared', 'ad_reported', 'ad_deleted', 'ad_created', 'contest_winner', 'contest_reminder', 'contest_created', 'custom']).notNull(),
|
|
142
|
+
contentId: int('content_id'),
|
|
143
|
+
contentCatId: int('content_cat_id'),
|
|
144
|
+
userId: int('user_id'),
|
|
145
|
+
message: varchar('message', { length: 255 })
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
export const ModerationTable = mysqlTable('moderation', {
|
|
150
|
+
id: int('id').autoincrement().notNull().primaryKey(),
|
|
151
|
+
contentType: mysqlEnum('content_type', ['ad', 'user']).notNull(),
|
|
152
|
+
contentId: int('content_id').notNull(),
|
|
153
|
+
catId: int('cat_id'),
|
|
154
|
+
userId: int('user_id').notNull(),
|
|
155
|
+
flagged: int('flagged').notNull(),
|
|
156
|
+
result: varchar('result', { length: 255 }).notNull()
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
export const JobsTable = mysqlTable('jobs', {
|
|
161
|
+
id: int('id').autoincrement().notNull().primaryKey(),
|
|
162
|
+
title: varchar('title', { length: 255 }).notNull(),
|
|
163
|
+
catId: int('cat_id').notNull(),
|
|
164
|
+
salary: int('salary'),
|
|
165
|
+
currency: mysqlEnum('currency', ['USD', 'TRY', 'SYP']).notNull(),
|
|
166
|
+
workMethod: varchar('work_method', { length: 255 }).notNull(),
|
|
167
|
+
minimumEducation: varchar('minimum_education', { length: 255 }).notNull(),
|
|
168
|
+
experienceLevel: varchar('experience_level', { length: 255 }).notNull(),
|
|
169
|
+
remote: boolean('remote'),
|
|
170
|
+
coverphoto: varchar('coverphoto', { length: 255 }).notNull(),
|
|
171
|
+
coverphotoPlaceholder: varchar('coverphoto_placeholder', { length: 255 }),
|
|
172
|
+
desc: longtext('desc'),
|
|
173
|
+
latitude: double('latitude'),
|
|
174
|
+
longitude: double('longitude'),
|
|
175
|
+
viewCount: int('view_count'),
|
|
176
|
+
status: mysqlEnum('status', ['pending_creation', 'active', 'pending_review', 'rejected', 'expired']),
|
|
177
|
+
govId: int('gov_id').notNull(),
|
|
178
|
+
districtId: int('district_id').notNull(),
|
|
179
|
+
subDistrictId: int('sub_district_id'),
|
|
180
|
+
townId: int('town_id')
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
export const FurnitureTable = mysqlTable('furniture', {
|
|
185
|
+
id: int('id').autoincrement().notNull().primaryKey(),
|
|
186
|
+
title: varchar('title', { length: 255 }).notNull(),
|
|
187
|
+
catId: int('cat_id').notNull(),
|
|
188
|
+
condition: varchar('condition', { length: 255 }).notNull(),
|
|
189
|
+
price: int('price').notNull(),
|
|
190
|
+
currency: mysqlEnum('currency', ['USD', 'TRY', 'SYP']).notNull(),
|
|
191
|
+
exchangeable: boolean('exchangeable'),
|
|
192
|
+
fromWhom: varchar('from_whom', { length: 255 }).notNull(),
|
|
193
|
+
coverphoto: varchar('coverphoto', { length: 255 }).notNull(),
|
|
194
|
+
coverphotoPlaceholder: varchar('coverphoto_placeholder', { length: 255 }),
|
|
195
|
+
desc: longtext('desc'),
|
|
196
|
+
latitude: double('latitude'),
|
|
197
|
+
longitude: double('longitude'),
|
|
198
|
+
viewCount: int('view_count'),
|
|
199
|
+
status: mysqlEnum('status', ['pending_creation', 'active', 'pending_review', 'rejected', 'expired']),
|
|
200
|
+
govId: int('gov_id').notNull(),
|
|
201
|
+
districtId: int('district_id').notNull(),
|
|
202
|
+
subDistrictId: int('sub_district_id'),
|
|
203
|
+
townId: int('town_id')
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
export const FiltersTable = mysqlTable('filters', {
|
|
208
|
+
id: int('id').autoincrement().notNull().primaryKey(),
|
|
209
|
+
title: varchar('title', { length: 255 }).notNull(),
|
|
210
|
+
Key: varchar('_key', { length: 255 }).notNull(),
|
|
211
|
+
fieldName: varchar('field_name', { length: 255 }).notNull(),
|
|
212
|
+
type: mysqlEnum('type', ['checkbox', 'select', 'text', 'finance', 'number', 'point']).notNull(),
|
|
213
|
+
tableName: varchar('table_name', { length: 255 }),
|
|
214
|
+
isMandatory: boolean('is_mandatory')
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
export const FaqTable = mysqlTable('faq', {
|
|
219
|
+
id: int('id').autoincrement().notNull().primaryKey(),
|
|
220
|
+
qEn: varchar('q_en', { length: 255 }).notNull(),
|
|
221
|
+
qAr: varchar('q_ar', { length: 255 }).notNull(),
|
|
222
|
+
qTr: varchar('q_tr', { length: 255 }),
|
|
223
|
+
aEn: longtext('a_en').notNull(),
|
|
224
|
+
aAr: longtext('a_ar'),
|
|
225
|
+
aTr: longtext('a_tr')
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
export const ErrorsTable = mysqlTable('errors', {
|
|
230
|
+
id: int('id').autoincrement().notNull().primaryKey(),
|
|
231
|
+
title: varchar('title', { length: 255 }).notNull(),
|
|
232
|
+
caseId: varchar('case_id', { length: 255 }).notNull(),
|
|
233
|
+
userId: int('user_id'),
|
|
234
|
+
itemSlug: varchar('item_slug', { length: 255 }),
|
|
235
|
+
desc: longtext('desc'),
|
|
236
|
+
isResolved: boolean('is_resolved')
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
export const ElectronicsTable = mysqlTable('electronics', {
|
|
241
|
+
id: int('id').autoincrement().notNull().primaryKey(),
|
|
242
|
+
title: varchar('title', { length: 255 }).notNull(),
|
|
243
|
+
catId: int('cat_id').notNull(),
|
|
244
|
+
condition: varchar('condition', { length: 255 }).notNull(),
|
|
245
|
+
price: int('price').notNull(),
|
|
246
|
+
currency: mysqlEnum('currency', ['USD', 'TRY', 'SYP']).notNull(),
|
|
247
|
+
exchangeable: boolean('exchangeable'),
|
|
248
|
+
installments: boolean('installments'),
|
|
249
|
+
fromWhom: varchar('from_whom', { length: 255 }).notNull(),
|
|
250
|
+
coverphoto: varchar('coverphoto', { length: 255 }).notNull(),
|
|
251
|
+
coverphotoPlaceholder: varchar('coverphoto_placeholder', { length: 255 }),
|
|
252
|
+
desc: longtext('desc'),
|
|
253
|
+
latitude: double('latitude'),
|
|
254
|
+
longitude: double('longitude'),
|
|
255
|
+
viewCount: int('view_count'),
|
|
256
|
+
status: mysqlEnum('status', ['pending_creation', 'active', 'pending_review', 'rejected', 'expired']),
|
|
257
|
+
govId: int('gov_id').notNull(),
|
|
258
|
+
districtId: int('district_id').notNull(),
|
|
259
|
+
subDistrictId: int('sub_district_id'),
|
|
260
|
+
townId: int('town_id')
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
export const ClothesTable = mysqlTable('clothes', {
|
|
265
|
+
id: int('id').autoincrement().notNull().primaryKey(),
|
|
266
|
+
title: varchar('title', { length: 255 }).notNull(),
|
|
267
|
+
catId: int('cat_id').notNull(),
|
|
268
|
+
condition: varchar('condition', { length: 255 }).notNull(),
|
|
269
|
+
price: int('price').notNull(),
|
|
270
|
+
currency: mysqlEnum('currency', ['USD', 'TRY', 'SYP']).notNull(),
|
|
271
|
+
exchangeable: boolean('exchangeable'),
|
|
272
|
+
fromWhom: varchar('from_whom', { length: 255 }).notNull(),
|
|
273
|
+
coverphoto: varchar('coverphoto', { length: 255 }).notNull(),
|
|
274
|
+
coverphotoPlaceholder: varchar('coverphoto_placeholder', { length: 255 }),
|
|
275
|
+
desc: longtext('desc'),
|
|
276
|
+
latitude: double('latitude'),
|
|
277
|
+
longitude: double('longitude'),
|
|
278
|
+
viewCount: int('view_count'),
|
|
279
|
+
status: mysqlEnum('status', ['pending_creation', 'active', 'pending_review', 'rejected', 'expired']),
|
|
280
|
+
govId: int('gov_id').notNull(),
|
|
281
|
+
districtId: int('district_id').notNull(),
|
|
282
|
+
subDistrictId: int('sub_district_id'),
|
|
283
|
+
townId: int('town_id')
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
export const CatsTable = mysqlTable('cats', {
|
|
288
|
+
id: int('id').autoincrement().notNull().primaryKey(),
|
|
289
|
+
catOrder: int('cat_order').notNull(),
|
|
290
|
+
slug: varchar('slug', { length: 255 }).notNull(),
|
|
291
|
+
titleEn: varchar('title_en', { length: 255 }).notNull(),
|
|
292
|
+
titleAr: varchar('title_ar', { length: 255 }).notNull(),
|
|
293
|
+
titleTr: varchar('title_tr', { length: 255 }).notNull(),
|
|
294
|
+
fullTitleEn: varchar('full_title_en', { length: 255 }),
|
|
295
|
+
fullTitleAr: varchar('full_title_ar', { length: 255 }),
|
|
296
|
+
fullTitleTr: varchar('full_title_tr', { length: 255 }),
|
|
297
|
+
image: varchar('image', { length: 255 }),
|
|
298
|
+
metaDescEn: varchar('meta_desc_en', { length: 255 }),
|
|
299
|
+
metaDescAr: varchar('meta_desc_ar', { length: 255 }),
|
|
300
|
+
metaDescTr: varchar('meta_desc_tr', { length: 255 }),
|
|
301
|
+
filters: varchar('filters', { length: 255 }),
|
|
302
|
+
tableName: varchar('table_name', { length: 255 }).notNull(),
|
|
303
|
+
adCount: int('ad_count'),
|
|
304
|
+
parentId: int('parent_id'),
|
|
305
|
+
level: int('level')
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
export const CarsTable = mysqlTable('cars', {
|
|
310
|
+
id: int('id').autoincrement().notNull().primaryKey(),
|
|
311
|
+
modelYear: int('model_year').notNull(),
|
|
312
|
+
model: varchar('model', { length: 255 }).notNull(),
|
|
313
|
+
title: varchar('title', { length: 255 }).notNull(),
|
|
314
|
+
catId: int('cat_id').notNull(),
|
|
315
|
+
govId: int('gov_id').notNull(),
|
|
316
|
+
districtId: int('district_id').notNull(),
|
|
317
|
+
subDistrictId: int('sub_district_id'),
|
|
318
|
+
townId: int('town_id'),
|
|
319
|
+
price: int('price').notNull(),
|
|
320
|
+
currency: mysqlEnum('currency', ['USD', 'TRY', 'SYP']).notNull(),
|
|
321
|
+
condition: varchar('condition', { length: 255 }).notNull(),
|
|
322
|
+
fromWhom: varchar('from_whom', { length: 255 }).notNull(),
|
|
323
|
+
engineCapacity: varchar('engine_capacity', { length: 255 }).notNull(),
|
|
324
|
+
enginePower: varchar('engine_power', { length: 255 }).notNull(),
|
|
325
|
+
tractionType: varchar('traction_type', { length: 255 }).notNull(),
|
|
326
|
+
bodyType: varchar('body_type', { length: 255 }).notNull(),
|
|
327
|
+
gearType: varchar('gear_type', { length: 255 }).notNull(),
|
|
328
|
+
fuelType: varchar('fuel_type', { length: 255 }).notNull(),
|
|
329
|
+
exchangeable: boolean('exchangeable'),
|
|
330
|
+
installments: boolean('installments'),
|
|
331
|
+
coverphoto: varchar('coverphoto', { length: 255 }).notNull(),
|
|
332
|
+
coverphotoPlaceholder: varchar('coverphoto_placeholder', { length: 255 }),
|
|
333
|
+
desc: longtext('desc'),
|
|
334
|
+
latitude: double('latitude'),
|
|
335
|
+
longitude: double('longitude'),
|
|
336
|
+
viewCount: int('view_count'),
|
|
337
|
+
status: mysqlEnum('status', ['pending_creation', 'active', 'pending_review', 'rejected', 'expired'])
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
export const CarsDbTable = mysqlTable('cars_db', {
|
|
342
|
+
id: int('id').autoincrement().notNull().primaryKey(),
|
|
343
|
+
name: varchar('name', { length: 255 }).notNull(),
|
|
344
|
+
parentId: int('parent_id'),
|
|
345
|
+
level: int('level')
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
export const BooksTable = mysqlTable('books', {
|
|
350
|
+
id: int('id').autoincrement().notNull().primaryKey(),
|
|
351
|
+
title: varchar('title', { length: 255 }).notNull(),
|
|
352
|
+
catId: int('cat_id').notNull(),
|
|
353
|
+
condition: varchar('condition', { length: 255 }).notNull(),
|
|
354
|
+
price: int('price').notNull(),
|
|
355
|
+
currency: mysqlEnum('currency', ['USD', 'TRY', 'SYP']).notNull(),
|
|
356
|
+
exchangeable: boolean('exchangeable'),
|
|
357
|
+
fromWhom: varchar('from_whom', { length: 255 }).notNull(),
|
|
358
|
+
coverphoto: varchar('coverphoto', { length: 255 }).notNull(),
|
|
359
|
+
coverphotoPlaceholder: varchar('coverphoto_placeholder', { length: 255 }),
|
|
360
|
+
desc: longtext('desc'),
|
|
361
|
+
latitude: double('latitude'),
|
|
362
|
+
longitude: double('longitude'),
|
|
363
|
+
viewCount: int('view_count'),
|
|
364
|
+
status: mysqlEnum('status', ['pending_creation', 'active', 'pending_review', 'rejected', 'expired']),
|
|
365
|
+
govId: int('gov_id').notNull(),
|
|
366
|
+
districtId: int('district_id').notNull(),
|
|
367
|
+
subDistrictId: int('sub_district_id'),
|
|
368
|
+
townId: int('town_id')
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
export const AddressTable = mysqlTable('address', {
|
|
373
|
+
id: int('id').autoincrement().notNull().primaryKey(),
|
|
374
|
+
catOrder: int('cat_order').notNull(),
|
|
375
|
+
titleEn: varchar('title_en', { length: 255 }).notNull(),
|
|
376
|
+
titleAr: varchar('title_ar', { length: 255 }).notNull(),
|
|
377
|
+
titleTr: varchar('title_tr', { length: 255 }).notNull(),
|
|
378
|
+
image: varchar('image', { length: 255 }),
|
|
379
|
+
path: varchar('path', { length: 255 }),
|
|
380
|
+
parentId: int('parent_id'),
|
|
381
|
+
level: int('level')
|
|
382
|
+
});
|
|
383
|
+
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"nanoid": "^5.1.2",
|
|
66
66
|
"next": "16.1.1",
|
|
67
67
|
"next-themes": "^0.4.6",
|
|
68
|
-
"nextjs-cms": "0.6.
|
|
68
|
+
"nextjs-cms": "0.6.6",
|
|
69
69
|
"plaiceholder": "^3.0.0",
|
|
70
70
|
"prettier-plugin-tailwindcss": "^0.7.2",
|
|
71
71
|
"qrcode": "^1.5.4",
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
"eslint-config-prettier": "^10.0.1",
|
|
99
99
|
"eslint-plugin-prettier": "^5.2.3",
|
|
100
100
|
"fs-extra": "^11.3.3",
|
|
101
|
-
"nextjs-cms-kit": "0.6.
|
|
101
|
+
"nextjs-cms-kit": "0.6.6",
|
|
102
102
|
"postcss": "^8.5.1",
|
|
103
103
|
"prettier": "3.5.0",
|
|
104
104
|
"raw-loader": "^4.0.2",
|