// React Imports import { useState, useEffect } from 'react' // MUI Imports import Button from '@mui/material/Button' import Drawer from '@mui/material/Drawer' import IconButton from '@mui/material/IconButton' import MenuItem from '@mui/material/MenuItem' import Typography from '@mui/material/Typography' import Box from '@mui/material/Box' import Switch from '@mui/material/Switch' import FormControlLabel from '@mui/material/FormControlLabel' // Third-party Imports import { useForm, Controller } from 'react-hook-form' // Component Imports import CustomTextField from '@core/components/mui/TextField' import ImageUpload from '@/components/ImageUpload' // Types import { Campaign, CampaignRequest, CampaignType } from '@/types/services/campaign' import { useCampaignsMutation } from '@/services/mutations/campaign' import { useFilesMutation } from '@/services/mutations/files' import { formatDateYYYYMMDD } from '@/utils/transform' type Props = { open: boolean handleClose: () => void data?: Campaign // Data campaign untuk edit (jika ada) } type FormValidateType = { name: string description: string type: CampaignType start_date: string end_date: string is_active: boolean show_on_app: boolean position: number banner_url: string } // Initial form data const initialData: FormValidateType = { name: '', description: '', type: 'POINTS', start_date: '', end_date: '', is_active: true, show_on_app: true, position: 1, banner_url: '' } const AddEditCampaignDrawer = (props: Props) => { // Props const { open, handleClose, data } = props // States const [showMore, setShowMore] = useState(false) const [isSubmitting, setIsSubmitting] = useState(false) const [bannerUrl, setBannerUrl] = useState('') const { createCampaign, updateCampaign } = useCampaignsMutation() const { mutate: uploadFile, isPending: isUploadPending } = useFilesMutation().uploadFile // Determine if this is edit mode const isEditMode = Boolean(data?.id) // Hooks const { control, reset: resetForm, handleSubmit, watch, setValue, formState: { errors } } = useForm({ defaultValues: initialData }) const watchedStartDate = watch('start_date') const watchedEndDate = watch('end_date') // Effect to populate form when editing useEffect(() => { if (isEditMode && data) { const formData: FormValidateType = { name: data.name || '', description: data.description || '', type: data.type || 'POINTS', start_date: data.start_date ? new Date(data.start_date).toISOString().split('T')[0] : '', end_date: data.end_date ? new Date(data.end_date).toISOString().split('T')[0] : '', is_active: data.is_active ?? true, show_on_app: data.show_on_app ?? true, position: data.position || 1, banner_url: data.metadata?.banner_url || '' } resetForm(formData) setBannerUrl(data.metadata?.banner_url || '') setShowMore(true) // Always show more for edit mode } else { // Reset to initial data for add mode resetForm(initialData) setBannerUrl('') setShowMore(false) } }, [data, isEditMode, resetForm]) const handleFormSubmit = async (formData: FormValidateType) => { try { setIsSubmitting(true) // Create metadata object const metadata: { banner_url?: string } = {} if (bannerUrl.trim()) { metadata.banner_url = bannerUrl.trim() } // Create CampaignRequest object const campaignRequest: CampaignRequest = { name: formData.name, description: formData.description || undefined, type: formData.type, start_date: formatDateYYYYMMDD(formData.start_date), end_date: formatDateYYYYMMDD(formData.end_date), is_active: formData.is_active, show_on_app: formData.show_on_app, position: formData.position, metadata: Object.keys(metadata).length > 0 ? metadata : undefined } if (isEditMode && data?.id) { // Update existing campaign updateCampaign.mutate( { id: data.id, payload: campaignRequest }, { onSuccess: () => { handleReset() handleClose() } } ) } else { // Create new campaign createCampaign.mutate(campaignRequest, { onSuccess: () => { handleReset() handleClose() } }) } } catch (error) { console.error('Error submitting campaign:', error) // Handle error (show toast, etc.) } finally { setIsSubmitting(false) } } const handleReset = () => { handleClose() resetForm(initialData) setBannerUrl('') setShowMore(false) } // Handle file upload const handleBannerUpload = async (file: File): Promise => { return new Promise((resolve, reject) => { const formData = new FormData() formData.append('file', file) formData.append('file_type', 'image') formData.append('description', 'campaign banner upload') uploadFile(formData, { onSuccess: r => { setBannerUrl(r.file_url) setValue('banner_url', r.file_url) // Update form value resolve(r.id) }, onError: er => { reject(er) } }) }) } return ( {/* Sticky Header */}
{isEditMode ? 'Edit Kampanye' : 'Tambah Kampanye Baru'}
{/* Scrollable Content */}
{/* Nama Kampanye */}
Nama Kampanye * ( )} />
{/* Jenis Kampanye */}
Jenis Kampanye * (
Points
Tokens
Reward
Mixed
)} />
{/* Tanggal Mulai */}
Tanggal Mulai * ( )} />
{/* Tanggal Berakhir */}
Tanggal Berakhir * { if (watchedStartDate && value) { return ( new Date(value) >= new Date(watchedStartDate) || 'Tanggal berakhir harus setelah tanggal mulai' ) } return true } }} render={({ field }) => ( )} />
{/* Status Aktif */}
( } label='Kampanye Aktif' /> )} />
{/* Show on App */}
( } label='Tampilkan di Aplikasi' /> )} />
{/* Tampilkan selengkapnya */} {!showMore && ( )} {/* Konten tambahan */} {showMore && ( <> {/* Description */}
Deskripsi Kampanye ( )} />
{/* Banner Upload */}
Banner Kampanye Format: JPG, PNG. Ukuran maksimal: 1MB
{/* Position */}
Posisi Kampanye ( field.onChange(Number(e.target.value))} /> )} />
{/* Sembunyikan */} )}
{/* Sticky Footer */}
) } export default AddEditCampaignDrawer