diff --git a/apps/landing/src/app/(frontend)/_components/features.tsx b/apps/landing/src/app/(frontend)/_components/features.tsx
index 40ed3e1..20c82e8 100644
--- a/apps/landing/src/app/(frontend)/_components/features.tsx
+++ b/apps/landing/src/app/(frontend)/_components/features.tsx
@@ -6,40 +6,22 @@ import {
LaptopIcon,
UsersIcon,
} from '@imphnen-frontend-service/shadcn-ui/atoms';
+import { FeaturesSection } from 'apps/landing/src/payload-types';
import { motion, useInView } from 'framer-motion';
import { useRef } from 'react';
-export function Features() {
+export function Features(props: FeaturesSection) {
+ const { heading, subheading, features } = props;
+
+ const featuresFormatted = features?.map((f) => ({
+ icon: IconMapper(String(f.icon)),
+ title: f.title,
+ description: f.description,
+ }));
+
const ref = useRef(null);
const isInView = useInView(ref, { once: true, amount: 0.2 });
- const features = [
- {
- icon: ,
- title: 'Belajar Tanpa Koding',
- description:
- 'Pelajari konsep programming dengan cara yang mudah dipahami tanpa harus menulis kode yang rumit.',
- },
- {
- icon: ,
- title: 'Komunitas Supportif',
- description:
- 'Bergabunglah dengan komunitas programmer Indonesia yang siap membantu dan berbagi pengalaman.',
- },
- {
- icon: ,
- title: 'Tutorial Interaktif',
- description:
- 'Akses tutorial interaktif yang membuat konsep programming lebih mudah untuk dipahami.',
- },
- {
- icon: ,
- title: 'Proyek Praktis',
- description:
- 'Terapkan pengetahuan Anda dalam proyek nyata dengan panduan langkah demi langkah.',
- },
- ];
-
const containerVariants = {
hidden: { opacity: 0 },
visible: {
@@ -64,7 +46,6 @@ export function Features() {
id="fitur"
className="w-full py-20 md:py-32 relative overflow-hidden"
>
- {/* Background Elements */}
@@ -82,14 +63,10 @@ export function Features() {
Fitur Unggulan
- Belajar programming dengan{' '}
-
- cara yang lebih baik
-
+ {heading}
- IMPHNEN hadir dengan berbagai fitur untuk membantu kamu menjadi
- programmer handal tanpa harus pusing dengan coding.
+ {subheading}
@@ -100,7 +77,7 @@ export function Features() {
initial="hidden"
animate={isInView ? 'visible' : 'hidden'}
>
- {features.map((feature, index) => (
+ {featuresFormatted?.map((feature, index) => (
);
}
+
+function IconMapper(name: string) {
+ switch (name) {
+ case 'LaptopIcon':
+ return ;
+ case 'UsersIcon':
+ return ;
+ case 'BookOpenIcon':
+ return ;
+ case 'CodeIcon':
+ return ;
+ default:
+ return null;
+ }
+}
diff --git a/apps/landing/src/app/(frontend)/page.tsx b/apps/landing/src/app/(frontend)/page.tsx
index ef7edd4..c0f9dfa 100644
--- a/apps/landing/src/app/(frontend)/page.tsx
+++ b/apps/landing/src/app/(frontend)/page.tsx
@@ -1,3 +1,4 @@
+import { getGlobalsFeaturesSection } from '../../repositories/get-globals-features-section';
import { getGlobalsHeroSection } from '../../repositories/get-globals-hero-section';
import { CallToAction } from './_components/call-to-action';
import { Community } from './_components/community';
@@ -10,13 +11,14 @@ import { Testimonials } from './_components/testimonials';
export default async function Page() {
const heroData = await getGlobalsHeroSection();
+ const featuresData = await getGlobalsFeaturesSection();
return (
-
+
diff --git a/apps/landing/src/collections/FeaturesSection.ts b/apps/landing/src/collections/FeaturesSection.ts
new file mode 100644
index 0000000..8de4e31
--- /dev/null
+++ b/apps/landing/src/collections/FeaturesSection.ts
@@ -0,0 +1,72 @@
+import { GlobalConfig } from 'payload';
+
+export const FeaturesSection: GlobalConfig = {
+ slug: 'features-section',
+ label: 'Features Section',
+ access: {
+ read: (): boolean => true,
+ },
+ fields: [
+ {
+ name: 'heading',
+ type: 'text',
+ defaultValue: 'Belajar programming dengan cara yang lebih baik',
+ },
+ {
+ name: 'subheading',
+ type: 'text',
+ defaultValue:
+ 'IMPHNEN hadir dengan berbagai fitur untuk membantu kamu menjadi programmer handal tanpa harus pusing dengan coding.',
+ },
+ {
+ name: 'features',
+ type: 'array',
+ defaultValue: [
+ {
+ icon: 'LaptopIcon',
+ title: 'Belajar Tanpa Koding',
+ description:
+ 'Pelajari konsep programming dengan cara yang mudah dipahami tanpa harus menulis kode yang rumit.',
+ },
+ {
+ icon: 'UsersIcon',
+ title: 'Komunitas Supportif',
+ description:
+ 'Bergabunglah dengan komunitas programmer Indonesia yang siap membantu dan berbagi pengalaman.',
+ },
+ {
+ icon: 'BookOpenIcon',
+ title: 'Tutorial Interaktif',
+ description:
+ 'Akses tutorial interaktif yang membuat konsep programming lebih mudah untuk dipahami.',
+ },
+ {
+ icon: 'CodeIcon',
+ title: 'Proyek Praktis',
+ description:
+ 'Terapkan pengetahuan Anda dalam proyek nyata dengan panduan langkah demi langkah.',
+ },
+ ],
+ fields: [
+ {
+ name: 'icon',
+ type: 'select',
+ options: [
+ { label: 'LaptopIcon', value: 'LaptopIcon' },
+ { label: 'UsersIcon', value: 'UsersIcon' },
+ { label: 'BookOpenIcon', value: 'BookOpenIcon' },
+ { label: 'CodeIcon', value: 'CodeIcon' },
+ ],
+ },
+ {
+ name: 'title',
+ type: 'text',
+ },
+ {
+ name: 'description',
+ type: 'textarea',
+ },
+ ],
+ },
+ ],
+};
diff --git a/apps/landing/src/payload-types.ts b/apps/landing/src/payload-types.ts
index 865e21d..b1c50ce 100644
--- a/apps/landing/src/payload-types.ts
+++ b/apps/landing/src/payload-types.ts
@@ -86,9 +86,11 @@ export interface Config {
};
globals: {
'hero-section': HeroSection;
+ 'features-section': FeaturesSection;
};
globalsSelect: {
'hero-section': HeroSectionSelect | HeroSectionSelect;
+ 'features-section': FeaturesSectionSelect | FeaturesSectionSelect;
};
locale: null;
user: User & {
@@ -301,6 +303,25 @@ export interface HeroSection {
updatedAt?: string | null;
createdAt?: string | null;
}
+/**
+ * This interface was referenced by `Config`'s JSON-Schema
+ * via the `definition` "features-section".
+ */
+export interface FeaturesSection {
+ id: number;
+ heading?: string | null;
+ subheading?: string | null;
+ features?:
+ | {
+ icon?: ('LaptopIcon' | 'UsersIcon' | 'BookOpenIcon' | 'CodeIcon') | null;
+ title?: string | null;
+ description?: string | null;
+ id?: string | null;
+ }[]
+ | null;
+ updatedAt?: string | null;
+ createdAt?: string | null;
+}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "hero-section_select".
@@ -329,6 +350,25 @@ export interface HeroSectionSelect {
createdAt?: T;
globalType?: T;
}
+/**
+ * This interface was referenced by `Config`'s JSON-Schema
+ * via the `definition` "features-section_select".
+ */
+export interface FeaturesSectionSelect {
+ heading?: T;
+ subheading?: T;
+ features?:
+ | T
+ | {
+ icon?: T;
+ title?: T;
+ description?: T;
+ id?: T;
+ };
+ updatedAt?: T;
+ createdAt?: T;
+ globalType?: T;
+}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "auth".
diff --git a/apps/landing/src/payload.config.ts b/apps/landing/src/payload.config.ts
index 48bc574..b63dcd5 100644
--- a/apps/landing/src/payload.config.ts
+++ b/apps/landing/src/payload.config.ts
@@ -5,6 +5,7 @@ import { buildConfig } from 'payload';
import sharp from 'sharp';
import { fileURLToPath } from 'url';
+import { FeaturesSection } from './collections/FeaturesSection';
import { HeroSection } from './collections/HeroSection';
import { Media } from './collections/Media';
import { Users } from './collections/Users';
@@ -26,7 +27,7 @@ export default buildConfig({
},
},
collections: [Users, Media],
- globals: [HeroSection],
+ globals: [HeroSection, FeaturesSection],
editor: lexicalEditor(),
secret: process.env.CMS_SECRET || '',
typescript: {
diff --git a/apps/landing/src/repositories/get-globals-features-section.ts b/apps/landing/src/repositories/get-globals-features-section.ts
new file mode 100644
index 0000000..d22574d
--- /dev/null
+++ b/apps/landing/src/repositories/get-globals-features-section.ts
@@ -0,0 +1,7 @@
+import { payload } from '../lib/payload';
+
+export async function getGlobalsFeaturesSection() {
+ return await payload.findGlobal({
+ slug: 'features-section',
+ });
+}