diff --git a/apps/landing/src/app/(auth)/layout.tsx b/apps/landing/src/app/(auth)/layout.tsx index bfcbcb5..50fb487 100644 --- a/apps/landing/src/app/(auth)/layout.tsx +++ b/apps/landing/src/app/(auth)/layout.tsx @@ -1,17 +1,10 @@ -import { baiJamjureeFont } from '@/lib/fonts'; import { Card } from '@components'; -import { cn } from '@utils'; import { ReactNode } from 'react'; import { AnimatedBackground } from './_components/animated-background'; export default function Layout({ children }: { children: ReactNode }) { return ( -
+
diff --git a/apps/landing/src/app/(public)/roadmap/_components/projects-vote.tsx b/apps/landing/src/app/(public)/roadmap/_components/projects-vote.tsx index fdc015f..be7d219 100644 --- a/apps/landing/src/app/(public)/roadmap/_components/projects-vote.tsx +++ b/apps/landing/src/app/(public)/roadmap/_components/projects-vote.tsx @@ -32,21 +32,21 @@ export default function ProjectsVote() { title: 'IMPHNEN Certificate', description: 'Cetak sertifikat keren secara instan untuk anggota IMPHNEN', }, + { + title: 'IMPHNEN Roadmap by Vote', + description: 'Usulkan ide fitur seru dan ajak anggota lain buat voting', + }, ]; const completedItems = [ { - title: 'IMPHNEN List Event', + title: 'IMPHNEN Events Page', description: 'Koleksi daftar event dan kolaborasi seru yang bisa kamu ikuti', }, { - title: 'IMPHNEN Testimoni', - description: 'Berikan testimonial gokil buat komunitas IMPHNEN', - }, - { - title: 'IMPHNEN Roadmap by Vote', - description: 'Usulkan ide fitur seru dan ajak anggota lain buat voting', + title: 'IMPHNEN Testimoni Page', + description: 'Berikan testimonial buat komunitas IMPHNEN', }, ]; diff --git a/apps/landing/src/app/(public)/testimonials/_components/testimonials-popup.tsx b/apps/landing/src/app/(public)/testimonials/_components/testimonials-popup.tsx new file mode 100644 index 0000000..c35e34d --- /dev/null +++ b/apps/landing/src/app/(public)/testimonials/_components/testimonials-popup.tsx @@ -0,0 +1,365 @@ +'use client'; + +import { useMediaQuery } from '@/hooks/use-media-query'; +import { + Avatar, + AvatarFallback, + AvatarImage, + Button, + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogTrigger, + Drawer, + DrawerClose, + DrawerContent, + DrawerFooter, + DrawerHeader, + DrawerTitle, + DrawerTrigger, + Input, + Label, + Textarea, +} from '@components'; +import { cn } from '@utils'; +import * as React from 'react'; +import { useRef, useState } from 'react'; +import { LuArrowLeft, LuUpload, LuUser, LuX } from 'react-icons/lu'; + +export function TestimonialPopup() { + const [open, setOpen] = useState(false); + const isDesktop = useMediaQuery('(min-width: 768px)'); + + if (isDesktop) { + return ( + + + + + + + Tambah Testimoni + + + + + ); + } + + return ( + + + + + + + Tambah Testimoni + +
+ +
+ + + + + +
+
+ ); +} + +interface TestimonialFormProps extends React.ComponentProps<'div'> { + setOpen: (open: boolean) => void; +} + +function TestimonialForm({ className, setOpen }: TestimonialFormProps) { + const [step, setStep] = useState(1); + const [testimonialError, setTestimonialError] = useState(false); + const fileInputRef = useRef(null); + const [avatarPreview, setAvatarPreview] = useState(null); + + const [formData, setFormData] = useState({ + name: '', + email: '', + role: '', + company: '', + testimonial: '', + }); + + const handleInputChange = (field: string, value: string) => { + setFormData((prev) => ({ ...prev, [field]: value })); + }; + + const handleFileChange = (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + if (file) { + if (!file.type.startsWith('image/')) { + alert('Hanya file gambar yang diizinkan'); + return; + } + + const reader = new FileReader(); + reader.onload = (event) => { + if (event.target?.result) { + setAvatarPreview(event.target.result as string); + } + }; + reader.readAsDataURL(file); + } + }; + + const removeAvatar = (e: React.MouseEvent) => { + e.stopPropagation(); + setAvatarPreview(null); + if (fileInputRef.current) { + fileInputRef.current.value = ''; + } + }; + + const triggerFileInput = () => { + fileInputRef.current?.click(); + }; + + const validateStep1 = () => { + return formData.name.trim() !== '' && formData.email.trim() !== ''; + }; + + const handleNextStep = () => { + if (validateStep1()) setStep(2); + }; + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + + setTestimonialError(false); + + if (formData.testimonial.trim() === '') { + setTestimonialError(true); + return; + } + + console.log('Testimonial submitted:', formData); + setOpen(false); + resetForm(); + }; + + const resetForm = () => { + setStep(1); + setTestimonialError(false); + setAvatarPreview(null); + setFormData({ + name: '', + email: '', + role: '', + company: '', + testimonial: '', + }); + if (fileInputRef.current) fileInputRef.current.value = ''; + }; + + return ( +
+ {/* Progress Bar */} +
+
+ Langkah {step} dari 2 +
+
+
+
+
+ +
+
+ {step === 1 && ( +
+
+

Data Diri

+

1/2

+
+ +
+
+
+ + {avatarPreview ? ( + + ) : ( + + + + )} + + {avatarPreview && ( + + )} +
+ +
+ + +

+ Maks. 2MB (JPEG, PNG) +

+
+
+ +
+ {[ + { + id: 'name', + label: 'Nama', + placeholder: 'Nama lengkap', + required: true, + }, + { + id: 'email', + label: 'Email', + placeholder: 'email@contoh.com', + type: 'email', + required: true, + }, + { + id: 'role', + label: 'Role', + placeholder: 'Backend Developer', + required: true, + optional: false, + }, + { + id: 'company', + label: 'Perusahaan', + placeholder: 'Nama perusahaan', + required: false, + optional: true, + }, + ].map((field) => ( +
+ + + handleInputChange(field.id, e.target.value) + } + required={field.required} + className="py-2" + /> +
+ ))} +
+ +
+ +
+
+
+ )} + + {step === 2 && ( +
+
+

Ulasan

+

2/2

+
+ +
+
+
+ + + {formData.testimonial.length}/500 + +
+ +