diff --git a/apps/backend/src/app/(frontend)/posts/[slug]/page.tsx b/apps/backend/src/app/(frontend)/posts/[slug]/page.tsx index 04c3344..d508cee 100644 --- a/apps/backend/src/app/(frontend)/posts/[slug]/page.tsx +++ b/apps/backend/src/app/(frontend)/posts/[slug]/page.tsx @@ -16,25 +16,9 @@ import { generateMeta } from '@/utilities/generateMeta' import PageClient from './page.client' import { LivePreviewListener } from '@/components/LivePreviewListener' -export async function generateStaticParams() { - const payload = await getPayload({ config: configPromise }) - const posts = await payload.find({ - collection: 'posts', - draft: false, - limit: 1000, - overrideAccess: false, - pagination: false, - select: { - slug: true, - }, - }) - - const params = posts.docs.map(({ slug }) => { - return { slug } - }) - - return params -} +// Use dynamic rendering instead of static generation +// This avoids the need for database connection during build time +export const dynamic = 'force-dynamic' type Args = { params: Promise<{ diff --git a/apps/backend/src/app/(frontend)/posts/page.tsx b/apps/backend/src/app/(frontend)/posts/page.tsx index 5cf1389..4007d93 100644 --- a/apps/backend/src/app/(frontend)/posts/page.tsx +++ b/apps/backend/src/app/(frontend)/posts/page.tsx @@ -8,7 +8,8 @@ import { getPayload } from 'payload' import React from 'react' import PageClient from './page.client' -export const dynamic = 'force-static' +// Use dynamic rendering to avoid database connection during build +export const dynamic = 'force-dynamic' export const revalidate = 600 export default async function Page() { diff --git a/apps/backend/src/app/(frontend)/posts/page/[pageNumber]/page.tsx b/apps/backend/src/app/(frontend)/posts/page/[pageNumber]/page.tsx index e55131d..3aec936 100644 --- a/apps/backend/src/app/(frontend)/posts/page/[pageNumber]/page.tsx +++ b/apps/backend/src/app/(frontend)/posts/page/[pageNumber]/page.tsx @@ -9,6 +9,8 @@ import React from 'react' import PageClient from './page.client' import { notFound } from 'next/navigation' +// Use dynamic rendering to avoid database connection during build +export const dynamic = 'force-dynamic' export const revalidate = 600 type Args = { diff --git a/apps/backend/src/blocks/ServicesList/config.ts b/apps/backend/src/blocks/ServicesList/config.ts new file mode 100644 index 0000000..6fc4ccd --- /dev/null +++ b/apps/backend/src/blocks/ServicesList/config.ts @@ -0,0 +1,86 @@ +import type { Block } from 'payload' + +export const ServicesList: Block = { + slug: 'servicesList', + interfaceName: 'ServicesListBlock', + fields: [ + { + name: 'services', + type: 'array', + required: true, + admin: { + initCollapsed: true, + }, + fields: [ + { + name: 'title', + type: 'text', + required: true, + }, + { + name: 'description', + type: 'textarea', + required: true, + }, + { + name: 'category', + type: 'text', + required: true, + }, + { + name: 'iconType', + type: 'select', + defaultValue: 'preset', + options: [ + { label: 'Preset Icon', value: 'preset' }, + { label: 'Custom SVG', value: 'svg' }, + { label: 'Upload Image', value: 'upload' }, + ], + }, + { + name: 'icon', + type: 'text', + admin: { + description: 'Preset icon name: facebook, google, ads, news, youtube, forum, web, video', + condition: (_, siblingData) => siblingData?.iconType === 'preset', + }, + }, + { + name: 'iconSvg', + type: 'textarea', + admin: { + description: 'Paste SVG code directly (e.g., ...)', + condition: (_, siblingData) => siblingData?.iconType === 'svg', + }, + }, + { + name: 'iconImage', + type: 'upload', + relationTo: 'media', + admin: { + description: 'Upload an icon image (SVG, PNG)', + condition: (_, siblingData) => siblingData?.iconType === 'upload', + }, + }, + { + name: 'isHot', + type: 'checkbox', + defaultValue: false, + }, + { + name: 'image', + type: 'upload', + relationTo: 'media', + }, + { + name: 'link', + type: 'text', + }, + ], + }, + ], + labels: { + singular: 'Services List', + plural: 'Services Lists', + }, +} diff --git a/apps/backend/src/collections/Pages/index.ts b/apps/backend/src/collections/Pages/index.ts index a320dc8..0b7e4e0 100644 --- a/apps/backend/src/collections/Pages/index.ts +++ b/apps/backend/src/collections/Pages/index.ts @@ -8,6 +8,7 @@ import { Archive } from '../../blocks/ArchiveBlock/config' import { CallToAction } from '../../blocks/CallToAction/config' import { Content } from '../../blocks/Content/config' import { MediaBlock } from '../../blocks/MediaBlock/config' +import { ServicesList } from '../../blocks/ServicesList/config' import { hero } from '@/heros/config' import { slugField } from '@/fields/slug' import { populatePublishedAt } from '../../hooks/populatePublishedAt' @@ -76,7 +77,7 @@ export const Pages: CollectionConfig<'pages'> = { { name: 'layout', type: 'blocks', - blocks: [CallToAction, Content, MediaBlock, Archive], + blocks: [CallToAction, Content, MediaBlock, Archive, ServicesList], required: true, admin: { initCollapsed: true, diff --git a/apps/backend/src/payload-types.ts b/apps/backend/src/payload-types.ts index bc187aa..d887ced 100644 --- a/apps/backend/src/payload-types.ts +++ b/apps/backend/src/payload-types.ts @@ -194,7 +194,7 @@ export interface Page { | null; media?: (string | null) | Media; }; - layout: (CallToActionBlock | ContentBlock | MediaBlock | ArchiveBlock)[]; + layout: (CallToActionBlock | ContentBlock | MediaBlock | ArchiveBlock | ServicesListBlock)[]; meta?: { title?: string | null; /** @@ -564,6 +564,37 @@ export interface ArchiveBlock { blockName?: string | null; blockType: 'archive'; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "ServicesListBlock". + */ +export interface ServicesListBlock { + services: { + title: string; + description: string; + category: string; + iconType?: ('preset' | 'svg' | 'upload') | null; + /** + * Preset icon name: facebook, google, ads, news, youtube, forum, web, video + */ + icon?: string | null; + /** + * Paste SVG code directly (e.g., ...) + */ + iconSvg?: string | null; + /** + * Upload an icon image (SVG, PNG) + */ + iconImage?: (string | null) | Media; + isHot?: boolean | null; + image?: (string | null) | Media; + link?: string | null; + id?: string | null; + }[]; + id?: string | null; + blockName?: string | null; + blockType: 'servicesList'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "portfolio". @@ -923,6 +954,7 @@ export interface PagesSelect { content?: T | ContentBlockSelect; mediaBlock?: T | MediaBlockSelect; archive?: T | ArchiveBlockSelect; + servicesList?: T | ServicesListBlockSelect; }; meta?: | T @@ -1011,6 +1043,29 @@ export interface ArchiveBlockSelect { id?: T; blockName?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "ServicesListBlock_select". + */ +export interface ServicesListBlockSelect { + services?: + | T + | { + title?: T; + description?: T; + category?: T; + iconType?: T; + icon?: T; + iconSvg?: T; + iconImage?: T; + isHot?: T; + image?: T; + link?: T; + id?: T; + }; + id?: T; + blockName?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "posts_select". diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 9217836..52b5a6f 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -17,8 +17,9 @@ "@tailwindcss/vite": "^4.1.14", "agentation": "^2.1.1", "agentation-mcp": "^1.1.0", - "astro": "6.0.0-beta.1", - "better-auth": "^1.3.13" + "astro": "6.0.0-beta.17", + "better-auth": "^1.3.13", + "isomorphic-dompurify": "^3.0.0" }, "devDependencies": { "@astrojs/check": "^0.9.6", diff --git a/apps/frontend/src/components/Footer.astro b/apps/frontend/src/components/Footer.astro index 79e3ca1..b21df78 100644 --- a/apps/frontend/src/components/Footer.astro +++ b/apps/frontend/src/components/Footer.astro @@ -42,8 +42,8 @@ try { const currentYear = new Date().getFullYear(); --- -
-
+
+

恩群數位累積多年廣告行銷操作經驗,擁有全方位行銷人才,讓我們可以為客戶精準的規劃每一分廣告預算,讓你的品牌深入人心。更重要的是恩群的存在,為了成為每家公司最佳數位夥伴,作為彼此最堅強的後盾,你會知道有我們的陪伴 你並不孤單。 @@ -72,7 +72,7 @@ const currentYear = new Date().getFullYear(); href="https://www.facebook.com/EnChun-Taiwan-100979265112420" target="_blank" rel="noopener noreferrer" - class="flex items-center mb-2" + class="flex items-center mb-2 no-underline hover:underline transition-colors" > -

+

諮詢電話:
02 5570 0527

enchuntaiwan@gmail.com
@@ -99,16 +99,28 @@ const currentYear = new Date().getFullYear(); > 行銷方案 -
    - {footerNavItems.length > 0 && footerNavItems[0]?.childNavItems - ? footerNavItems[0].childNavItems.map((item: any) => ( +
@@ -118,40 +130,35 @@ const currentYear = new Date().getFullYear(); > 行銷放大鏡 -
    - {categories.length > 0 - ? categories.map((cat: any) => ( +
-
-

- copyright © Enchun digital 2018 - {currentYear} -

-
+ +
+

+ copyright © Enchun digital 2018 - {currentYear} +

- - diff --git a/apps/frontend/src/components/Header.astro b/apps/frontend/src/components/Header.astro index d0232a5..36e3bbb 100644 --- a/apps/frontend/src/components/Header.astro +++ b/apps/frontend/src/components/Header.astro @@ -62,10 +62,10 @@ function isLinkActive(url: string): boolean { ---
-