Compare commits
9
Commits
e9cb17ed67
...
018a1f2767
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
018a1f2767 | ||
|
|
3132fcb8eb | ||
|
|
3183098926 | ||
|
|
a661739844 | ||
|
|
2a4f33172b | ||
|
|
849acf4c34 | ||
|
|
1600d99c5d | ||
|
|
30364fcab7 | ||
|
|
6cb99f603a |
@@ -7,6 +7,11 @@ MONGODB_DB=mozdit
|
|||||||
MONGO_ROOT_USER=admin
|
MONGO_ROOT_USER=admin
|
||||||
MONGO_ROOT_PASSWORD=changeme
|
MONGO_ROOT_PASSWORD=changeme
|
||||||
|
|
||||||
|
# Payload CMS (MITHOME-86) — generálj egyedi, erős titkot ehhez a
|
||||||
|
# környezethez (pl. `openssl rand -hex 32`); ne ossz meg értéket másik
|
||||||
|
# environmenttel.
|
||||||
|
PAYLOAD_SECRET=changeme
|
||||||
|
|
||||||
# Publikus site URL (beég build időben a Dockerfile-ba)
|
# Publikus site URL (beég build időben a Dockerfile-ba)
|
||||||
NEXT_PUBLIC_SITE_URL=https://mozdit.hu
|
NEXT_PUBLIC_SITE_URL=https://mozdit.hu
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,11 @@ MONGODB_DB=mozdit
|
|||||||
MONGO_ROOT_USER=admin
|
MONGO_ROOT_USER=admin
|
||||||
MONGO_ROOT_PASSWORD=changeme
|
MONGO_ROOT_PASSWORD=changeme
|
||||||
|
|
||||||
|
# Payload CMS (MITHOME-86) — generálj egyedi, erős titkot ehhez a
|
||||||
|
# környezethez (pl. `openssl rand -hex 32`); ne ossz meg értéket másik
|
||||||
|
# environmenttel.
|
||||||
|
PAYLOAD_SECRET=changeme
|
||||||
|
|
||||||
# Publikus site URL (beég build időben a Dockerfile-ba)
|
# Publikus site URL (beég build időben a Dockerfile-ba)
|
||||||
NEXT_PUBLIC_SITE_URL=https://stage.mozdit.hu
|
NEXT_PUBLIC_SITE_URL=https://stage.mozdit.hu
|
||||||
|
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ Szükséges változók (`.env` és `proto/.env.local`):
|
|||||||
- `NEXT_PUBLIC_WEBMAIL_URL` — Webmail service URL
|
- `NEXT_PUBLIC_WEBMAIL_URL` — Webmail service URL
|
||||||
- `NEXT_PUBLIC_CONTACT_EMAIL` — Kapcsolati email cím
|
- `NEXT_PUBLIC_CONTACT_EMAIL` — Kapcsolati email cím
|
||||||
- `PLANE_API_KEY` — Plane szinkronizációhoz (a `.mcp.json`-ban is lehet)
|
- `PLANE_API_KEY` — Plane szinkronizációhoz (a `.mcp.json`-ban is lehet)
|
||||||
|
- `PAYLOAD_SECRET` — Payload CMS JWT/session aláíráshoz (MITHOME-86); környezetenként egyedi, erős érték
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -96,6 +96,26 @@ Next.js 15 alapú weboldal a mozdIT Bt. számára, Docker Compose-szal deployolv
|
|||||||
|
|
||||||
## 📋 Backlog (v1.0.2+)
|
## 📋 Backlog (v1.0.2+)
|
||||||
|
|
||||||
|
### EPIC: Payload CMS migráció (MITHOME-85)
|
||||||
|
|
||||||
|
Cél: az ügyfél önállóan, admin felületen szerkeszthesse a tartalmat — a JSON content rendszer (`proto/src/content/pages/*.json`) és a hozzá épült egyedi CMS (`content-editor.js`) lecserélése Payload CMS-re (Next.js App Router-be épülő, MongoDB adapterrel).
|
||||||
|
|
||||||
|
| Plane | Feladat | Státusz |
|
||||||
|
|-------|---------|---------|
|
||||||
|
| MITHOME-85 | **EPIC**: Áttérés Payload CMS-re (admin felület az ügyfélnek) | 📋 |
|
||||||
|
| MITHOME-86 | Payload CMS alapinstallálás: config, MongoDB adapter, admin route | ✅ |
|
||||||
|
| MITHOME-87 | Home/About/Services/Contact/Common Globals kialakítása és JSON tartalom migrálása | ✅ |
|
||||||
|
| MITHOME-88 | LegalPages collection (adatvedelem, hasznalati-feltetelek) migrálása | 📋 |
|
||||||
|
| MITHOME-89 | Partners + Media collection: logófeltöltés és transparent-logo funkció migrálása | 📋 |
|
||||||
|
| MITHOME-90 | Users collection: ügyfél admin bejelentkezés és access control | 📋 |
|
||||||
|
| MITHOME-91 | Frontend átállítása Payload Local API-ra, JSON content rendszer kivezetése | 📋 |
|
||||||
|
| MITHOME-92 | Draft/preview és verziózás bekapcsolása (Verziók panel utódja) | 📋 |
|
||||||
|
| MITHOME-93 | Régi egyedi CMS (content-editor.js) leépítése | 📋 |
|
||||||
|
| MITHOME-94 | Opcionális: ContactSubmissions collection a Mongoose modell helyett | 📋 |
|
||||||
|
| MITHOME-95 | .agent/ és CLAUDE.md dokumentáció frissítése Payload architektúrára | 📋 |
|
||||||
|
| MITHOME-96 | Tesztek migrálása: content schema tesztek helyett Payload collection/global tesztek | 📋 |
|
||||||
|
| MITHOME-97 | Deploy/Docker frissítés: PAYLOAD_SECRET, admin bundle, Dockerfile/deploy.sh | 📋 |
|
||||||
|
|
||||||
| Plane | Feladat | Státusz |
|
| Plane | Feladat | Státusz |
|
||||||
|-------|---------|---------|
|
|-------|---------|---------|
|
||||||
| MITHOME-15 | Production domain, Nginx reverse proxy és HTTPS | 📋 |
|
| MITHOME-15 | Production domain, Nginx reverse proxy és HTTPS | 📋 |
|
||||||
@@ -159,6 +179,9 @@ docker-compose -f docker-compose.dev.yml down
|
|||||||
---
|
---
|
||||||
|
|
||||||
## Frissítési Napló
|
## Frissítési Napló
|
||||||
|
- **2026-09-10**: MITHOME-87 (Home/About/Services/Contact/Common Globals + JSON migráció) kész. Munka közben két, MITHOME-86-hoz visszanyúló hibát javítottunk: (1) a gyökér src/app/layout.tsx ütközött a Payload (payload)/layout.tsx-ével — a webodal saját route-jai átkerültek egy (frontend) route groupba; (2) a kézzel írt importMap.js stub nem volt elég — tsx 4.22.4→4.23.13 (Node 25 kompatibilitás) után legenerálva a valódit. Mindkettő valós böngészőben ellenőrizve (curl nem buktatta fel korábban). `npm run migrate:content` script + `npm test`/lint/build zöld.
|
||||||
|
- **2026-09-10**: MITHOME-86 (Payload alapinstalláció) kész: Next.js 15.5→16.3.4 upgrade (Payload peer dep miatt), payload.config.ts + mongooseAdapter + minimális Users collection + admin/API/GraphQL route-ok. Élesben ellenőrizve valódi MongoDB-vel. Ismert nyitott advisory a payload@3.88.0-ban (GHSA-jg8r-5jh2-v2xj), nyomon követve MITHOME-90 alatt. Branch: `feature/payload-cms-setup`.
|
||||||
|
- **2026-09-10**: Payload CMS migrációs EPIC (MITHOME-85) és 12 alfeladat (MITHOME-86–97) létrehozva Plane-ben — cél: JSON content + egyedi CMS lecserélése Payload-ra, ügyfél önálló admin szerkesztéshez.
|
||||||
- **2026-08-17**: Plane sync (`plane-sync.js`). Új MITHOME-27 (Production környezet) Backlog-ba; Custom CMS és Webmail bevéve a Plane-be (28/29, Done). `regenerate()` hiba javítva (szekció-elválasztó).
|
- **2026-08-17**: Plane sync (`plane-sync.js`). Új MITHOME-27 (Production környezet) Backlog-ba; Custom CMS és Webmail bevéve a Plane-be (28/29, Done). `regenerate()` hiba javítva (szekció-elválasztó).
|
||||||
- **2026-08-17**: Plane sync futtatása (`plane-sync.js`). MITHOME-15, MITHOME-18 visszaminősítve Backlog-ba (Plane szerint), MITHOME-27/28 megtartva.
|
- **2026-08-17**: Plane sync futtatása (`plane-sync.js`). MITHOME-15, MITHOME-18 visszaminősítve Backlog-ba (Plane szerint), MITHOME-27/28 megtartva.
|
||||||
- **2026-04-26**: Átállás Linear → Plane (MITHOME projekt). TODO.md teljes újraírva, 26 issue szinkronizálva.
|
- **2026-04-26**: Átállás Linear → Plane (MITHOME projekt). TODO.md teljes újraírva, 26 issue szinkronizálva.
|
||||||
|
|||||||
+9
-11
@@ -1,16 +1,14 @@
|
|||||||
import { dirname } from "path";
|
// NOTE (Next.js 16 / eslint-config-next 16): the FlatCompat("next/core-web-vitals")
|
||||||
import { fileURLToPath } from "url";
|
// bridge to the legacy .eslintrc-style config caused a circular-JSON crash in
|
||||||
import { FlatCompat } from "@eslint/eslintrc";
|
// ESLint 9 (the "react" plugin object closes a cycle when re-validated through
|
||||||
|
// FlatCompat). eslint-config-next now ships native flat-config arrays, so
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
// import those directly instead of going through the compat layer.
|
||||||
const __dirname = dirname(__filename);
|
import nextCoreWebVitals from "eslint-config-next/core-web-vitals";
|
||||||
|
import nextTypescript from "eslint-config-next/typescript";
|
||||||
const compat = new FlatCompat({
|
|
||||||
baseDirectory: __dirname,
|
|
||||||
});
|
|
||||||
|
|
||||||
const eslintConfig = [
|
const eslintConfig = [
|
||||||
...compat.extends("next/core-web-vitals", "next/typescript"),
|
...nextCoreWebVitals,
|
||||||
|
...nextTypescript,
|
||||||
{
|
{
|
||||||
ignores: [
|
ignores: [
|
||||||
"node_modules/**",
|
"node_modules/**",
|
||||||
|
|||||||
+17
-7
@@ -1,14 +1,20 @@
|
|||||||
import type { NextConfig } from "next";
|
import type { NextConfig } from "next";
|
||||||
|
import { withPayload } from "@payloadcms/next/withPayload";
|
||||||
|
|
||||||
const nextConfig: NextConfig = {
|
const nextConfig: NextConfig = {
|
||||||
// Enable standalone output for Docker deployment
|
// Enable standalone output for Docker deployment
|
||||||
output: 'standalone',
|
output: 'standalone',
|
||||||
|
|
||||||
// Skip linting during build for faster Docker builds
|
// NOTE (Next.js 16): `next dev` auto-generates AGENTS.md/CLAUDE.md stub
|
||||||
eslint: {
|
// files describing the framework to AI agents. This project already has
|
||||||
ignoreDuringBuilds: true,
|
// its own agent instruction system (root CLAUDE.md -> .agent/) — a second,
|
||||||
},
|
// unrelated proto/CLAUDE.md would conflict with it, so this is disabled.
|
||||||
|
agentRules: false,
|
||||||
|
|
||||||
|
// NOTE (Next.js 16): `eslint.ignoreDuringBuilds` was removed — `next build`
|
||||||
|
// no longer runs ESLint itself (lint is now only `next lint` / `npm run lint`),
|
||||||
|
// so there is nothing left to ignore here.
|
||||||
|
|
||||||
// Skip TypeScript checking during build (for faster Docker builds)
|
// Skip TypeScript checking during build (for faster Docker builds)
|
||||||
typescript: {
|
typescript: {
|
||||||
ignoreBuildErrors: true,
|
ignoreBuildErrors: true,
|
||||||
@@ -71,4 +77,8 @@ const nextConfig: NextConfig = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default nextConfig;
|
// MITHOME-86: bundles the admin UI's route handlers correctly under
|
||||||
|
// Turbopack/webpack. `@payload-config` itself resolves via the `paths`
|
||||||
|
// alias in tsconfig.json (./src/payload.config.ts) — this wrapper's
|
||||||
|
// installed version has no separate configPath option.
|
||||||
|
export default withPayload(nextConfig);
|
||||||
|
|||||||
Generated
+4216
-466
File diff suppressed because it is too large
Load Diff
+12
-4
@@ -27,14 +27,21 @@
|
|||||||
"docker:dev:down": "cd .. && docker-compose -f docker-compose.dev.yml down",
|
"docker:dev:down": "cd .. && docker-compose -f docker-compose.dev.yml down",
|
||||||
"docker:dev:logs": "cd .. && docker-compose -f docker-compose.dev.yml logs -f app",
|
"docker:dev:logs": "cd .. && docker-compose -f docker-compose.dev.yml logs -f app",
|
||||||
"docker:build": "docker build -t mozdit-app .",
|
"docker:build": "docker build -t mozdit-app .",
|
||||||
"docker:run": "docker run -p 3000:3000 --env-file .env.local mozdit-app"
|
"docker:run": "docker run -p 3000:3000 --env-file .env.local mozdit-app",
|
||||||
|
"migrate:content": "node --env-file=.env.local --import tsx scripts/migrate-content-to-payload.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@payloadcms/db-mongodb": "^3.88.0",
|
||||||
|
"@payloadcms/next": "^3.88.0",
|
||||||
|
"@payloadcms/richtext-lexical": "^3.88.0",
|
||||||
|
"graphql": "^16.14.2",
|
||||||
"mongodb": "^6.5",
|
"mongodb": "^6.5",
|
||||||
"mongoose": "^8.2",
|
"mongoose": "^8.2",
|
||||||
"next": "^15.5.23",
|
"next": "^16.3.4",
|
||||||
|
"payload": "^3.88.0",
|
||||||
"react": "19.1.0",
|
"react": "19.1.0",
|
||||||
"react-dom": "19.1.0"
|
"react-dom": "19.1.0",
|
||||||
|
"sharp": "^0.35.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3",
|
"@eslint/eslintrc": "^3",
|
||||||
@@ -49,10 +56,11 @@
|
|||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
"@types/winston": "^2.4",
|
"@types/winston": "^2.4",
|
||||||
"eslint": "^9",
|
"eslint": "^9",
|
||||||
"eslint-config-next": "15.5.2",
|
"eslint-config-next": "^16.3.4",
|
||||||
"jest": "^29.7",
|
"jest": "^29.7",
|
||||||
"jest-environment-jsdom": "^29.7",
|
"jest-environment-jsdom": "^29.7",
|
||||||
"tailwindcss": "^4",
|
"tailwindcss": "^4",
|
||||||
|
"tsx": "^4.23.13",
|
||||||
"typescript": "^5",
|
"typescript": "^5",
|
||||||
"undici": "^7.15.0",
|
"undici": "^7.15.0",
|
||||||
"winston": "^3.11",
|
"winston": "^3.11",
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
/**
|
||||||
|
* MITHOME-87: egyszeri migrációs script — a proto/src/content/pages/*.json
|
||||||
|
* + common.json tartalmát átemeli a Payload Globals-ekbe (Home, About,
|
||||||
|
* Services, Contact, Common) a Local API-n keresztül.
|
||||||
|
*
|
||||||
|
* Futtatás (proto/ mappából, futó MongoDB-vel és beállított env-ekkel):
|
||||||
|
* node --env-file=.env.local --import tsx scripts/migrate-content-to-payload.ts
|
||||||
|
*
|
||||||
|
* Idempotens: updateGlobal-t hív, tetszőlegesen többször futtatható —
|
||||||
|
* mindig a JSON az aktuális "forrás igazság", felülírja a Payload-ban
|
||||||
|
* lévő korábbi állapotot. NEM törli/nem érinti a JSON fájlokat.
|
||||||
|
*/
|
||||||
|
import { getPayload } from 'payload'
|
||||||
|
import config from '../src/payload.config'
|
||||||
|
|
||||||
|
import homeJson from '../src/content/pages/home.json'
|
||||||
|
import aboutJson from '../src/content/pages/about.json'
|
||||||
|
import servicesJson from '../src/content/pages/services.json'
|
||||||
|
import contactJson from '../src/content/pages/contact.json'
|
||||||
|
import commonJson from '../src/content/common.json'
|
||||||
|
|
||||||
|
/** string[] -> [{ value: string }] — lásd src/globals/fields/stringArray.ts */
|
||||||
|
function toStringArray(items: readonly string[]): { value: string }[] {
|
||||||
|
return items.map((value) => ({ value }))
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildHomeData(json: typeof homeJson) {
|
||||||
|
const { hero, about, services, cta, serviceFeatures } = json
|
||||||
|
return {
|
||||||
|
hero: {
|
||||||
|
...hero,
|
||||||
|
trustBullets: toStringArray(hero.trustBullets),
|
||||||
|
},
|
||||||
|
about,
|
||||||
|
services: {
|
||||||
|
...services,
|
||||||
|
items: services.items.map((item) => ({
|
||||||
|
...item,
|
||||||
|
features: toStringArray(item.features),
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
cta,
|
||||||
|
serviceFeatures,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildAboutData(json: typeof aboutJson) {
|
||||||
|
const { meta, hero, story, mission, team, cta } = json
|
||||||
|
return {
|
||||||
|
meta,
|
||||||
|
hero,
|
||||||
|
story: { ...story, paragraphs: toStringArray(story.paragraphs) },
|
||||||
|
mission,
|
||||||
|
team: { ...team, paragraphs: toStringArray(team.paragraphs) },
|
||||||
|
cta,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildServicesData(json: typeof servicesJson) {
|
||||||
|
const { meta, hero, details, support, cta } = json
|
||||||
|
return {
|
||||||
|
meta,
|
||||||
|
hero,
|
||||||
|
details: {
|
||||||
|
...details,
|
||||||
|
services: details.services.map((service) => ({
|
||||||
|
...service,
|
||||||
|
specs: {
|
||||||
|
...service.specs,
|
||||||
|
items: toStringArray(service.specs.items),
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
support,
|
||||||
|
cta,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
const payload = await getPayload({ config })
|
||||||
|
|
||||||
|
await payload.updateGlobal({ slug: 'home', data: buildHomeData(homeJson) })
|
||||||
|
payload.logger.info('Home global migrálva')
|
||||||
|
|
||||||
|
await payload.updateGlobal({ slug: 'about', data: buildAboutData(aboutJson) })
|
||||||
|
payload.logger.info('About global migrálva')
|
||||||
|
|
||||||
|
await payload.updateGlobal({ slug: 'services', data: buildServicesData(servicesJson) })
|
||||||
|
payload.logger.info('Services global migrálva')
|
||||||
|
|
||||||
|
await payload.updateGlobal({ slug: 'contact', data: contactJson })
|
||||||
|
payload.logger.info('Contact global migrálva')
|
||||||
|
|
||||||
|
await payload.updateGlobal({ slug: 'common', data: commonJson })
|
||||||
|
payload.logger.info('Common global migrálva')
|
||||||
|
|
||||||
|
payload.logger.info('MITHOME-87 migráció kész.')
|
||||||
|
process.exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
run().catch((error) => {
|
||||||
|
console.error('Migráció sikertelen:', error)
|
||||||
|
process.exit(1)
|
||||||
|
})
|
||||||
@@ -2,11 +2,11 @@ import type { Metadata, Viewport } from "next";
|
|||||||
import { Geist, Geist_Mono } from "next/font/google";
|
import { Geist, Geist_Mono } from "next/font/google";
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
|
|
||||||
import Header from "../components/Header";
|
import Header from "../../components/Header";
|
||||||
import Footer from "../components/Footer";
|
import Footer from "../../components/Footer";
|
||||||
import { ThemeProvider } from "../components/ThemeProvider";
|
import { ThemeProvider } from "../../components/ThemeProvider";
|
||||||
import { siteConfig } from "../config/site";
|
import { siteConfig } from "../../config/site";
|
||||||
import { common } from "../content";
|
import { common } from "../../content";
|
||||||
|
|
||||||
const geistSans = Geist({
|
const geistSans = Geist({
|
||||||
variable: "--font-geist-sans",
|
variable: "--font-geist-sans",
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import type { Metadata } from 'next'
|
||||||
|
import config from '@payload-config'
|
||||||
|
import { NotFoundPage, generatePageMetadata } from '@payloadcms/next/views'
|
||||||
|
import { importMap } from '../importMap'
|
||||||
|
|
||||||
|
type Args = {
|
||||||
|
params: Promise<{ segments: string[] }>
|
||||||
|
searchParams: Promise<{ [key: string]: string | string[] }>
|
||||||
|
}
|
||||||
|
|
||||||
|
export const generateMetadata = ({ params, searchParams }: Args): Promise<Metadata> =>
|
||||||
|
generatePageMetadata({ config, params, searchParams })
|
||||||
|
|
||||||
|
const NotFound = ({ params, searchParams }: Args) =>
|
||||||
|
NotFoundPage({ config, params, searchParams, importMap })
|
||||||
|
|
||||||
|
export default NotFound
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import type { Metadata } from 'next'
|
||||||
|
import config from '@payload-config'
|
||||||
|
import { RootPage, generatePageMetadata } from '@payloadcms/next/views'
|
||||||
|
import { importMap } from '../importMap'
|
||||||
|
|
||||||
|
type Args = {
|
||||||
|
params: Promise<{ segments: string[] }>
|
||||||
|
searchParams: Promise<{ [key: string]: string | string[] }>
|
||||||
|
}
|
||||||
|
|
||||||
|
export const generateMetadata = ({ params, searchParams }: Args): Promise<Metadata> =>
|
||||||
|
generatePageMetadata({ config, params, searchParams })
|
||||||
|
|
||||||
|
const Page = ({ params, searchParams }: Args) => RootPage({ config, params, searchParams, importMap })
|
||||||
|
|
||||||
|
export default Page
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { CollectionCards as CollectionCards_f9c02e79a4aed9a3924487c0cd4cafb1 } from '@payloadcms/next/rsc'
|
||||||
|
|
||||||
|
/** @type import('payload').ImportMap */
|
||||||
|
export const importMap = {
|
||||||
|
"@payloadcms/next/rsc#CollectionCards": CollectionCards_f9c02e79a4aed9a3924487c0cd4cafb1
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import config from '@payload-config'
|
||||||
|
import {
|
||||||
|
REST_DELETE,
|
||||||
|
REST_GET,
|
||||||
|
REST_OPTIONS,
|
||||||
|
REST_PATCH,
|
||||||
|
REST_POST,
|
||||||
|
REST_PUT,
|
||||||
|
} from '@payloadcms/next/routes'
|
||||||
|
|
||||||
|
export const GET = REST_GET(config)
|
||||||
|
export const POST = REST_POST(config)
|
||||||
|
export const DELETE = REST_DELETE(config)
|
||||||
|
export const PATCH = REST_PATCH(config)
|
||||||
|
export const PUT = REST_PUT(config)
|
||||||
|
export const OPTIONS = REST_OPTIONS(config)
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import config from '@payload-config'
|
||||||
|
import { GRAPHQL_PLAYGROUND_GET } from '@payloadcms/next/routes'
|
||||||
|
|
||||||
|
export const GET = GRAPHQL_PLAYGROUND_GET(config)
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import config from '@payload-config'
|
||||||
|
import { GRAPHQL_POST } from '@payloadcms/next/routes'
|
||||||
|
|
||||||
|
export const POST = GRAPHQL_POST(config)
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import type { ServerFunctionClient } from 'payload'
|
||||||
|
import config from '@payload-config'
|
||||||
|
import { handleServerFunctions, RootLayout } from '@payloadcms/next/layouts'
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
import { importMap } from './admin/importMap'
|
||||||
|
|
||||||
|
import '@payloadcms/next/css'
|
||||||
|
|
||||||
|
type Args = {
|
||||||
|
children: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
const serverFunction: ServerFunctionClient = async function (args) {
|
||||||
|
'use server'
|
||||||
|
return handleServerFunctions({
|
||||||
|
...args,
|
||||||
|
config,
|
||||||
|
importMap,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const Layout = ({ children }: Args) => (
|
||||||
|
<RootLayout config={config} importMap={importMap} serverFunction={serverFunction}>
|
||||||
|
{children}
|
||||||
|
</RootLayout>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default Layout
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import type { CollectionConfig } from 'payload'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Admin bejelentkezés (MITHOME-86 bootstrap). A teljes access control /
|
||||||
|
* jelszó-politika finomítása MITHOME-90 feladata — itt csak a Payload
|
||||||
|
* indulásához szükséges minimális auth collection.
|
||||||
|
*/
|
||||||
|
export const Users: CollectionConfig = {
|
||||||
|
slug: 'users',
|
||||||
|
auth: true,
|
||||||
|
admin: {
|
||||||
|
useAsTitle: 'email',
|
||||||
|
},
|
||||||
|
fields: [],
|
||||||
|
}
|
||||||
@@ -38,6 +38,13 @@ export function ThemeProvider({ children, defaultTheme = 'system' }: ThemeProvid
|
|||||||
const [mounted, setMounted] = useState(false)
|
const [mounted, setMounted] = useState(false)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// WHY: this effect synchronizes React state with two external systems —
|
||||||
|
// the DOM (hydration-safe mount flag) and localStorage (persisted theme
|
||||||
|
// preference) — read once on mount. There is no subscription to wrap the
|
||||||
|
// setState calls in, so the new react-hooks/set-state-in-effect rule
|
||||||
|
// (added with the Next.js 16 / eslint-config-next upgrade) is a false
|
||||||
|
// positive here; suppress rather than restructure a working component.
|
||||||
|
// eslint-disable-next-line react-hooks/set-state-in-effect
|
||||||
setMounted(true)
|
setMounted(true)
|
||||||
const savedTheme = localStorage.getItem('theme') as Theme | null
|
const savedTheme = localStorage.getItem('theme') as Theme | null
|
||||||
if (savedTheme) {
|
if (savedTheme) {
|
||||||
@@ -59,6 +66,8 @@ export function ThemeProvider({ children, defaultTheme = 'system' }: ThemeProvid
|
|||||||
root.setAttribute('data-theme', theme)
|
root.setAttribute('data-theme', theme)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WHY: syncs React state with the resolved DOM/OS theme — see note above.
|
||||||
|
// eslint-disable-next-line react-hooks/set-state-in-effect
|
||||||
setResolvedTheme(resolved)
|
setResolvedTheme(resolved)
|
||||||
}, [theme, mounted])
|
}, [theme, mounted])
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import type { GlobalConfig } from 'payload'
|
||||||
|
|
||||||
|
import { stringArrayField } from './fields/stringArray'
|
||||||
|
|
||||||
|
/** Mirrors AboutPageContent (proto/src/content/types.ts) — MITHOME-87. */
|
||||||
|
export const About: GlobalConfig = {
|
||||||
|
slug: 'about',
|
||||||
|
admin: {
|
||||||
|
group: 'Oldalak',
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'meta',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{ name: 'description', type: 'textarea', required: true },
|
||||||
|
{ name: 'ogDescription', type: 'textarea', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'hero',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{ name: 'subtitle', type: 'text', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'story',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
stringArrayField('paragraphs', 'Paragraphs'),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'mission',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{ name: 'subtitle', type: 'text', required: true },
|
||||||
|
{
|
||||||
|
name: 'values',
|
||||||
|
type: 'array',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{ name: 'description', type: 'textarea', required: true },
|
||||||
|
{ name: 'icon', type: 'text', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'team',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{ name: 'subtitle', type: 'text', required: true },
|
||||||
|
stringArrayField('paragraphs', 'Paragraphs'),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'cta',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{ name: 'subtitle', type: 'textarea', required: true },
|
||||||
|
{ name: 'button', type: 'text', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import type { GlobalConfig } from 'payload'
|
||||||
|
|
||||||
|
/** Mirrors CommonContent (proto/src/content/types.ts) — MITHOME-87. */
|
||||||
|
export const Common: GlobalConfig = {
|
||||||
|
slug: 'common',
|
||||||
|
admin: {
|
||||||
|
group: 'Oldalak',
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'buttons',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'contact', type: 'text', required: true },
|
||||||
|
{ name: 'learnMore', type: 'text', required: true },
|
||||||
|
{ name: 'webmail', type: 'text', required: true },
|
||||||
|
{ name: 'sendMessage', type: 'text', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'labels',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'required', type: 'text', required: true },
|
||||||
|
{ name: 'features', type: 'text', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'validation',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'required', type: 'text', required: true },
|
||||||
|
{ name: 'invalidEmail', type: 'text', required: true },
|
||||||
|
{
|
||||||
|
name: 'minLength',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
admin: {
|
||||||
|
description: 'A {min} placeholder futásidőben cserélődik ki.',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'staging',
|
||||||
|
type: 'group',
|
||||||
|
fields: [{ name: 'banner', type: 'text', required: true }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'footer',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'copyright',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
admin: {
|
||||||
|
description: 'A {year} placeholder futásidőben cserélődik ki.',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ name: 'address', type: 'text', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'a11y',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'openMenu', type: 'text', required: true },
|
||||||
|
{ name: 'closeMenu', type: 'text', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
import type { GlobalConfig } from 'payload'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mirrors ContactPageContent (proto/src/content/types.ts) — MITHOME-87.
|
||||||
|
*
|
||||||
|
* WHY `gdpr.label` textarea és nem richText: a JSON forrás egy kézzel
|
||||||
|
* beírt <a> taget tartalmazó HTML string (lásd contact.json). A lexical
|
||||||
|
* richText mező más (JSON node-fa) szerializációt használna, ami extra
|
||||||
|
* migrációs/render logikát igényelne — ezt itt, bootstrap szinten nem
|
||||||
|
* bontjuk ki, marad egyszerű (HTML-t tartalmazó) szöveg mező.
|
||||||
|
*/
|
||||||
|
export const Contact: GlobalConfig = {
|
||||||
|
slug: 'contact',
|
||||||
|
admin: {
|
||||||
|
group: 'Oldalak',
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'meta',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{ name: 'description', type: 'textarea', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'hero',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{ name: 'subtitle', type: 'text', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'form',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{ name: 'successMessage', type: 'text', required: true },
|
||||||
|
{ name: 'errorMessage', type: 'text', required: true },
|
||||||
|
{
|
||||||
|
name: 'fields',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'label', type: 'text', required: true },
|
||||||
|
{ name: 'placeholder', type: 'text', required: true },
|
||||||
|
{ name: 'error', type: 'text', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'email',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'label', type: 'text', required: true },
|
||||||
|
{ name: 'placeholder', type: 'text', required: true },
|
||||||
|
{ name: 'errorRequired', type: 'text', required: true },
|
||||||
|
{ name: 'errorInvalid', type: 'text', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'subject',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'label', type: 'text', required: true },
|
||||||
|
{ name: 'placeholder', type: 'text', required: true },
|
||||||
|
{ name: 'error', type: 'text', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'message',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'label', type: 'text', required: true },
|
||||||
|
{ name: 'placeholder', type: 'text', required: true },
|
||||||
|
{ name: 'errorRequired', type: 'text', required: true },
|
||||||
|
{ name: 'errorMinLength', type: 'text', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'gdpr',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'label', type: 'textarea', required: true },
|
||||||
|
{ name: 'error', type: 'text', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ name: 'submitButton', type: 'text', required: true },
|
||||||
|
{ name: 'submittingButton', type: 'text', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'info',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{
|
||||||
|
name: 'email',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{ name: 'responseTime', type: 'text', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'company',
|
||||||
|
type: 'group',
|
||||||
|
fields: [{ name: 'title', type: 'text', required: true }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'webmail',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{ name: 'linkText', type: 'text', required: true },
|
||||||
|
{ name: 'subtitle', type: 'text', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'faq',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{
|
||||||
|
name: 'items',
|
||||||
|
type: 'array',
|
||||||
|
fields: [
|
||||||
|
{ name: 'question', type: 'text', required: true },
|
||||||
|
{ name: 'answer', type: 'textarea', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
import type { GlobalConfig } from 'payload'
|
||||||
|
|
||||||
|
import { stringArrayField } from './fields/stringArray'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mirrors HomePageContent (proto/src/content/types.ts) — MITHOME-87.
|
||||||
|
*
|
||||||
|
* WHY nincs `partners` mező: a home.partners.items a JSON-ban ma egy
|
||||||
|
* beágyazott lista, de a Payload oldalon önálló `Partners` collection lesz
|
||||||
|
* (logó = Media upload reference) — lásd MITHOME-89. Itt szándékosan
|
||||||
|
* kihagyjuk, nehogy két, egymásnak ellentmondó forrás legyen.
|
||||||
|
*/
|
||||||
|
export const Home: GlobalConfig = {
|
||||||
|
slug: 'home',
|
||||||
|
admin: {
|
||||||
|
group: 'Oldalak',
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'hero',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{ name: 'subtitle', type: 'text', required: true },
|
||||||
|
{ name: 'description', type: 'textarea', required: true },
|
||||||
|
stringArrayField('trustBullets', 'Trust bullets'),
|
||||||
|
{
|
||||||
|
name: 'cta',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'primary',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'text', type: 'text', required: true },
|
||||||
|
{ name: 'href', type: 'text', required: true },
|
||||||
|
{ name: 'external', type: 'checkbox', defaultValue: false },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'secondary',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'text', type: 'text', required: true },
|
||||||
|
{ name: 'href', type: 'text', required: true },
|
||||||
|
{ name: 'external', type: 'checkbox', defaultValue: false },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'about',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{
|
||||||
|
name: 'usps',
|
||||||
|
type: 'array',
|
||||||
|
fields: [
|
||||||
|
{ name: 'id', type: 'text', required: true },
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{ name: 'description', type: 'textarea', required: true },
|
||||||
|
{ name: 'icon', type: 'text', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'services',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{ name: 'subtitle', type: 'text', required: true },
|
||||||
|
{
|
||||||
|
name: 'items',
|
||||||
|
type: 'array',
|
||||||
|
fields: [
|
||||||
|
{ name: 'id', type: 'text', required: true },
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{ name: 'description', type: 'textarea', required: true },
|
||||||
|
{ name: 'icon', type: 'text', required: true },
|
||||||
|
stringArrayField('features', 'Features'),
|
||||||
|
{ name: 'ctaText', type: 'text', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'cta',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{ name: 'subtitle', type: 'textarea', required: true },
|
||||||
|
{ name: 'button', type: 'text', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'serviceFeatures',
|
||||||
|
type: 'group',
|
||||||
|
fields: [{ name: 'title', type: 'text', required: true }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
import type { GlobalConfig } from 'payload'
|
||||||
|
|
||||||
|
import { stringArrayField } from './fields/stringArray'
|
||||||
|
|
||||||
|
/** Mirrors ServicesPageContent (proto/src/content/types.ts) — MITHOME-87. */
|
||||||
|
export const Services: GlobalConfig = {
|
||||||
|
slug: 'services',
|
||||||
|
admin: {
|
||||||
|
group: 'Oldalak',
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'meta',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{ name: 'description', type: 'textarea', required: true },
|
||||||
|
{ name: 'ogDescription', type: 'textarea', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'hero',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{ name: 'subtitle', type: 'text', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'details',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{ name: 'subtitle', type: 'text', required: true },
|
||||||
|
{
|
||||||
|
name: 'services',
|
||||||
|
type: 'array',
|
||||||
|
fields: [
|
||||||
|
{ name: 'icon', type: 'text', required: true },
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{ name: 'description', type: 'textarea', required: true },
|
||||||
|
{
|
||||||
|
name: 'specs',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
stringArrayField('items', 'Items'),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'support',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{ name: 'subtitle', type: 'text', required: true },
|
||||||
|
{
|
||||||
|
name: 'channels',
|
||||||
|
type: 'array',
|
||||||
|
fields: [
|
||||||
|
{ name: 'icon', type: 'text', required: true },
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{ name: 'description', type: 'text', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'cta',
|
||||||
|
type: 'group',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', required: true },
|
||||||
|
{ name: 'subtitle', type: 'textarea', required: true },
|
||||||
|
{ name: 'primaryButton', type: 'text', required: true },
|
||||||
|
{ name: 'secondaryButton', type: 'text', required: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import type { ArrayField } from 'payload'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Payload has no native "array of plain strings" field — the closest
|
||||||
|
* built-in shape is an array of one-field objects. Used for every
|
||||||
|
* string[] in the old content/types.ts (trustBullets, paragraphs,
|
||||||
|
* features, spec items, …) so the JSON -> Payload migration script has a
|
||||||
|
* single, consistent shape to transform into.
|
||||||
|
*/
|
||||||
|
export function stringArrayField(name: string, label?: string, required = false): ArrayField {
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
type: 'array',
|
||||||
|
label,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'value',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
required,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* Payload CMS configuration (MITHOME-86 — alapinstalláció).
|
||||||
|
*
|
||||||
|
* WHY a saját MongoDB kapcsolatot használjuk: a projekt már MongoDB-t futtat
|
||||||
|
* (proto/src/lib/mongodb.ts) — Payload a `mongooseAdapter`-en keresztül
|
||||||
|
* ugyanabba az adatbázisba ír, nincs szükség külön DB-re/szerverre.
|
||||||
|
*
|
||||||
|
* MITHOME-87: Home/About/Services/Contact/Common Globals hozzáadva — ezek
|
||||||
|
* tükrözik a proto/src/content/pages/*.json + common.json struktúráját.
|
||||||
|
* A LegalPages/Partners/Media collectionök a MITHOME-88..89-ben kerülnek be.
|
||||||
|
*/
|
||||||
|
import path from 'path'
|
||||||
|
import { fileURLToPath } from 'url'
|
||||||
|
import { buildConfig } from 'payload'
|
||||||
|
import { mongooseAdapter } from '@payloadcms/db-mongodb'
|
||||||
|
import { lexicalEditor } from '@payloadcms/richtext-lexical'
|
||||||
|
import sharp from 'sharp'
|
||||||
|
|
||||||
|
import { Users } from './collections/Users'
|
||||||
|
import { Home } from './globals/Home'
|
||||||
|
import { About } from './globals/About'
|
||||||
|
import { Services } from './globals/Services'
|
||||||
|
import { Contact } from './globals/Contact'
|
||||||
|
import { Common } from './globals/Common'
|
||||||
|
|
||||||
|
const filename = fileURLToPath(import.meta.url)
|
||||||
|
const dirname = path.dirname(filename)
|
||||||
|
|
||||||
|
export default buildConfig({
|
||||||
|
// Admin felület — bejelentkezés az Users collection-nel (MITHOME-90-ben
|
||||||
|
// finomodik: access control, jelszó-politika stb.)
|
||||||
|
admin: {
|
||||||
|
user: Users.slug,
|
||||||
|
},
|
||||||
|
|
||||||
|
editor: lexicalEditor(),
|
||||||
|
|
||||||
|
collections: [Users],
|
||||||
|
|
||||||
|
globals: [Home, About, Services, Contact, Common],
|
||||||
|
|
||||||
|
secret: process.env.PAYLOAD_SECRET || '',
|
||||||
|
|
||||||
|
typescript: {
|
||||||
|
outputFile: path.resolve(dirname, 'payload-types.ts'),
|
||||||
|
},
|
||||||
|
|
||||||
|
db: mongooseAdapter({
|
||||||
|
url: process.env.MONGODB_URI || '',
|
||||||
|
}),
|
||||||
|
|
||||||
|
sharp,
|
||||||
|
})
|
||||||
+22
-5
@@ -1,7 +1,11 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ES2017",
|
"target": "ES2017",
|
||||||
"lib": ["dom", "dom.iterable", "esnext"],
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"dom.iterable",
|
||||||
|
"esnext"
|
||||||
|
],
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
@@ -11,7 +15,7 @@
|
|||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"jsx": "preserve",
|
"jsx": "react-jsx",
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"plugins": [
|
"plugins": [
|
||||||
{
|
{
|
||||||
@@ -19,9 +23,22 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["./src/*"]
|
"@/*": [
|
||||||
|
"./src/*"
|
||||||
|
],
|
||||||
|
"@payload-config": [
|
||||||
|
"./src/payload.config.ts"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
"include": [
|
||||||
"exclude": ["node_modules"]
|
"next-env.d.ts",
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.tsx",
|
||||||
|
".next/types/**/*.ts",
|
||||||
|
".next/dev/types/**/*.ts"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user