import React, { useState } from 'react';
import { View, ScrollView, Alert, FlatList, TouchableOpacity } from 'react-native';
import {
theme,
AppContainer,
MyText,
tw,
useManualRefresh,
useMarkDataFetchers,
MyTouchableOpacity,
RawBottomDialog,
BottomDialog,
} from 'common-ui';
import { trpc } from '../../../src/trpc-client';
import MaterialIcons from '@expo/vector-icons/MaterialIcons';
import { Ionicons, Entypo } from '@expo/vector-icons';
import { LinearGradient } from 'expo-linear-gradient';
import AvailabilityScheduleForm from '../../../components/AvailabilityScheduleForm';
interface Schedule {
id: number;
scheduleName: string;
time: string;
action: 'in' | 'out';
createdAt: string;
lastUpdated: string;
productIds: number[];
groupIds: number[];
productCount: number;
groupCount: number;
}
const ScheduleItem = ({
schedule,
onDelete,
index,
onViewProducts,
onViewGroups,
onReplicate,
}: {
schedule: Schedule;
onDelete: (id: number) => void;
index: number;
onViewProducts: (productIds: number[]) => void;
onViewGroups: (groupIds: number[]) => void;
onReplicate: (schedule: Schedule) => void;
}) => {
const isIn = schedule.action === 'in';
const [menuOpen, setMenuOpen] = useState(false);
return (
{/* Top Header: Name & Action Badge */}
Schedule Name
{schedule.scheduleName}
{isIn ? 'In Stock' : 'Out of Stock'}
setMenuOpen(true)}
style={tw`p-1`}
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
>
{/* Menu Dialog */}
setMenuOpen(false)}>
{schedule.scheduleName}
{
setMenuOpen(false);
onReplicate(schedule);
}}
style={tw`py-4 border-b border-gray-200`}
>
Replicate items
{
setMenuOpen(false);
Alert.alert('Coming Soon', 'Edit functionality will be available soon');
}}
style={tw`py-4 border-b border-gray-200`}
>
Edit
{
setMenuOpen(false);
onDelete(schedule.id);
}}
style={tw`py-4 border-b border-gray-200`}
>
Delete
setMenuOpen(false)}
style={tw`py-4 mt-2`}
>
Cancel
{/* Middle: Time Banner */}
{schedule.time}
Daily at this time
{/* Stats & Actions */}
onViewProducts(schedule.productIds)}
style={tw`flex-row items-center mr-4`}
>
{schedule.productCount} Products
{schedule.groupCount > 0 && (
onViewGroups(schedule.groupIds)}
style={tw`flex-row items-center`}
>
{schedule.groupCount} Groups
)}
);
};
export default function StockingSchedules() {
const {
data: schedules,
isLoading,
error,
refetch,
} = trpc.admin.productAvailabilitySchedules.getAll.useQuery();
const { data: productsData } = trpc.common.product.getAllProductsSummary.useQuery({});
const { data: groupsData } = trpc.admin.product.getGroups.useQuery();
const deleteSchedule = trpc.admin.productAvailabilitySchedules.delete.useMutation();
const [showCreateForm, setShowCreateForm] = useState(false);
// Dialog state
const [dialogOpen, setDialogOpen] = useState(false);
const [dialogType, setDialogType] = useState<'products' | 'groups'>('products');
const [selectedIds, setSelectedIds] = useState([]);
// Replication state
const [replicatingSchedule, setReplicatingSchedule] = useState(null);
useManualRefresh(refetch);
useMarkDataFetchers(() => {
refetch();
});
const handleCreate = () => {
setShowCreateForm(true);
};
const handleDelete = (id: number) => {
Alert.alert(
'Delete Schedule',
'Are you sure you want to delete this schedule? This action cannot be undone.',
[
{ text: 'Cancel', style: 'cancel' },
{
text: 'Delete',
style: 'destructive',
onPress: () => {
deleteSchedule.mutate(
{ id },
{
onSuccess: () => {
refetch();
},
onError: (error: any) => {
Alert.alert('Error', error.message || 'Failed to delete schedule');
},
},
);
},
},
],
);
};
const handleViewProducts = (productIds: number[]) => {
setDialogType('products');
setSelectedIds(productIds);
setDialogOpen(true);
};
const handleViewGroups = (groupIds: number[]) => {
setDialogType('groups');
setSelectedIds(groupIds);
setDialogOpen(true);
};
const handleReplicate = (schedule: Schedule) => {
setReplicatingSchedule(schedule);
setShowCreateForm(true);
};
const handleCloseForm = () => {
setShowCreateForm(false);
setReplicatingSchedule(null);
};
// Get product/group names from IDs
const getProductNames = () => {
const allProducts = productsData?.products || [];
return selectedIds.map(id => {
const product = allProducts.find(p => p.id === id);
return product?.name || `Product #${id}`;
});
};
const getGroupNames = () => {
const allGroups = groupsData?.groups || [];
return selectedIds.map(id => {
const group = allGroups.find(g => g.id === id);
return group?.groupName || `Group #${id}`;
});
};
if (showCreateForm) {
return (
{
refetch();
handleCloseForm();
}}
initialProductIds={replicatingSchedule?.productIds}
initialGroupIds={replicatingSchedule?.groupIds}
/>
);
}
if (isLoading) {
return (
Loading schedules...
);
}
if (error) {
return (
Error loading schedules
);
}
return (
<>
{schedules && schedules.length === 0 ? (
No Schedules Yet
Start by creating your first availability schedule using the
button below.
) : (
schedules?.map((schedule, index) => (
{index < schedules.length - 1 && (
)}
))
)}
{/* Products/Groups Dialog */}
setDialogOpen(false)}>
{dialogType === 'products' ? 'Products' : 'Groups'}
index.toString()}
renderItem={({ item }) => (
{item}
)}
showsVerticalScrollIndicator={false}
style={tw`max-h-80`}
ListEmptyComponent={
No {dialogType} found
}
/>
>
);
}