163 lines
No EOL
4.6 KiB
TypeScript
163 lines
No EOL
4.6 KiB
TypeScript
import React, { useState, useEffect } from 'react';
|
|
import { View, TouchableOpacity, Alert } from 'react-native';
|
|
import { AppContainer, MyText, tw } from 'common-ui';
|
|
import MaterialIcons from '@expo/vector-icons/MaterialIcons';
|
|
import { useRouter, useLocalSearchParams } from 'expo-router';
|
|
import { FormikHelpers } from 'formik';
|
|
import BannerForm, { BannerFormData } from '@/components/BannerForm';
|
|
import { trpc } from '../../../../src/trpc-client';
|
|
|
|
interface Banner {
|
|
id: number;
|
|
name: string;
|
|
imageUrl: string;
|
|
description?: string;
|
|
productIds?: number[];
|
|
redirectUrl?: string;
|
|
serialNum: number;
|
|
isActive: boolean;
|
|
createdAt: string;
|
|
lastUpdated: string;
|
|
}
|
|
|
|
export default function EditBanner() {
|
|
const router = useRouter();
|
|
const { id } = useLocalSearchParams();
|
|
const bannerId = id as string;
|
|
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
// Load real banner data from API
|
|
const {data: bannerData } = trpc.admin.banner.getBanner.useQuery({
|
|
id: parseInt(bannerId)
|
|
});
|
|
const [banner, setBanner] = useState<typeof bannerData>(undefined);
|
|
|
|
|
|
useEffect(() => {
|
|
const loadBanner = async () => {
|
|
try {
|
|
setIsLoading(true);
|
|
|
|
|
|
|
|
if (bannerData) {
|
|
// Handle data format compatibility (productId -> productIds migration)
|
|
const processedBanner = {
|
|
...bannerData,
|
|
productIds: Array.isArray(bannerData.productIds)
|
|
? bannerData.productIds
|
|
: (bannerData.productIds ? [bannerData.productIds] : [])
|
|
};
|
|
|
|
setBanner(processedBanner);
|
|
} else {
|
|
Alert.alert('Error', 'Banner not found');
|
|
router.back();
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to load banner:', error);
|
|
Alert.alert('Error', 'Failed to load banner data');
|
|
router.back();
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
loadBanner();
|
|
}, [bannerId, bannerData]);
|
|
|
|
const initialValues: BannerFormData = banner ? {
|
|
name: banner.name,
|
|
imageUrl: banner.imageUrl,
|
|
description: banner.description || '',
|
|
productIds: banner.productIds || [],
|
|
redirectUrl: banner.redirectUrl || '',
|
|
// serialNum removed - handled automatically by backend
|
|
} : {
|
|
name: '',
|
|
imageUrl: '',
|
|
description: '',
|
|
productIds: [],
|
|
redirectUrl: '',
|
|
// serialNum removed - handled automatically by backend
|
|
};
|
|
|
|
const updateBannerMutation = trpc.admin.banner.updateBanner.useMutation();
|
|
|
|
const handleSubmit = async (values: BannerFormData, imageUrl?: string) => {
|
|
if (!banner) return;
|
|
|
|
setIsSubmitting(true);
|
|
|
|
try {
|
|
await updateBannerMutation.mutateAsync({
|
|
id: banner.id,
|
|
name: values.name,
|
|
imageUrl: imageUrl || banner.imageUrl,
|
|
description: values.description || undefined,
|
|
productIds: values.productIds.length > 0 ? values.productIds : [],
|
|
redirectUrl: values.redirectUrl || undefined,
|
|
});
|
|
|
|
Alert.alert('Success', 'Banner updated successfully', [
|
|
{
|
|
text: 'OK',
|
|
onPress: () => router.back(),
|
|
}
|
|
]);
|
|
} catch (error) {
|
|
Alert.alert('Error', 'Failed to update banner. Please try again.');
|
|
} finally {
|
|
setIsSubmitting(false);
|
|
}
|
|
};
|
|
|
|
const handleCancel = () => {
|
|
router.back();
|
|
};
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<AppContainer>
|
|
<View style={tw`flex-1 justify-center items-center bg-white`}>
|
|
<MyText style={tw`text-gray-600`}>Loading banner...</MyText>
|
|
</View>
|
|
</AppContainer>
|
|
);
|
|
}
|
|
|
|
if (!banner) {
|
|
return (
|
|
<AppContainer>
|
|
<View style={tw`flex-1 justify-center items-center bg-white`}>
|
|
<MyText style={tw`text-red-600`}>Banner not found</MyText>
|
|
</View>
|
|
</AppContainer>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<AppContainer>
|
|
<View style={tw`flex-1 bg-white`}>
|
|
{/* Header */}
|
|
<View style={tw`flex-row items-center justify-between px-6 py-4 border-b border-gray-200`}>
|
|
<TouchableOpacity onPress={handleCancel} style={tw`p-2`}>
|
|
<MaterialIcons name="arrow-back" size={24} color="#374151" />
|
|
</TouchableOpacity>
|
|
<MyText style={tw`text-xl font-bold text-gray-900`}>Edit Banner</MyText>
|
|
<View style={tw`w-10`} />
|
|
</View>
|
|
|
|
<BannerForm
|
|
initialValues={initialValues}
|
|
onSubmit={handleSubmit}
|
|
onCancel={handleCancel}
|
|
submitButtonText="Update Banner"
|
|
isSubmitting={isSubmitting}
|
|
existingImageUrl={banner.imageUrl}
|
|
/>
|
|
</View>
|
|
</AppContainer>
|
|
);
|
|
} |