From 671cfdbfd9e4cd14a9b9dc124c701b8c50aa4b4c Mon Sep 17 00:00:00 2001 From: SreelakshmiBiju Date: Mon, 6 Jan 2025 14:39:58 +0530 Subject: [PATCH 1/2] modified code --- app/(tabs)/facility.tsx | 496 +++++++++++++++++----------------------- app/(tabs)/help.tsx | 69 ++++-- package-lock.json | 28 ++- package.json | 4 +- 4 files changed, 298 insertions(+), 299 deletions(-) diff --git a/app/(tabs)/facility.tsx b/app/(tabs)/facility.tsx index baf9284..708e340 100644 --- a/app/(tabs)/facility.tsx +++ b/app/(tabs)/facility.tsx @@ -1,354 +1,288 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect } from "react"; import { View, Text, TouchableOpacity, - StyleSheet, - TextInput, FlatList, - ScrollView, + StyleSheet, Alert, -} from 'react-native'; -import { Picker } from '@react-native-picker/picker'; -import DateTimePicker from '@react-native-community/datetimepicker'; -import { db } from '../../scripts/firebase'; + ScrollView, + SafeAreaView, +} from "react-native"; +import { useNavigation } from "@react-navigation/native"; +import { Ionicons } from "@expo/vector-icons"; // Importing icons +import { db } from "../../scripts/firebase"; // Import Firebase config import { collection, - addDoc, - onSnapshot, - query, - orderBy, doc, + getDocs, + addDoc, + updateDoc, deleteDoc, -} from 'firebase/firestore'; -import tw from 'twrnc'; -import { ArrowLeft } from 'lucide-react-native'; -import { useNavigation } from '@react-navigation/native'; + getDoc, +} from "firebase/firestore"; -const FacilityBookingPage = () => { - const [facility, setFacility] = useState(''); - const [date, setDate] = useState(new Date()); - const [time, setTime] = useState(new Date()); - const [count, setCount] = useState(''); - const [showDatePicker, setShowDatePicker] = useState(false); - const [showTimePicker, setShowTimePicker] = useState(false); - const [passes, setPasses] = useState([]); +type Pass = { + id?: string; + facilityId: string; + facilityName: string; + date: string; + time: string; + expiresAt: string; + count: string; +}; + +const FacilitiesBooking = () => { const navigation = useNavigation(); + const [facilities, setFacilities] = useState([]); + const [selectedFacility, setSelectedFacility] = useState(null); + const [availableSlots, setAvailableSlots] = useState(0); + const [passes, setPasses] = useState([]); + const [currentDate, setCurrentDate] = useState( + new Date().toISOString().split("T")[0] + ); useEffect(() => { - const passesCollection = collection(db, 'passes'); - const q = query(passesCollection, orderBy('createdAt', 'desc')); - - const unsubscribe = onSnapshot(q, (querySnapshot) => { - const fetchedPasses = querySnapshot.docs.map((doc) => ({ + const fetchFacilities = async () => { + const facilitiesSnapshot = await getDocs(collection(db, "Facilities")); + const facilitiesData = facilitiesSnapshot.docs.map((doc) => ({ id: doc.id, ...doc.data(), })); - setPasses(fetchedPasses); - }); + setFacilities(facilitiesData); + }; - return () => unsubscribe(); + fetchFacilities(); }, []); - const generatePass = async () => { - if (!facility || !count) { - alert('Please select a facility and enter the number of people.'); + const bookSlot = async () => { + if (!selectedFacility) { + Alert.alert("Error", "Please select a facility."); return; } - - const selectedDateTime = new Date(date); - selectedDateTime.setHours(time.getHours()); - selectedDateTime.setMinutes(time.getMinutes()); - selectedDateTime.setSeconds(0); - selectedDateTime.setMilliseconds(0); - - const currentTime = new Date(); - const thirtyMinutesAhead = new Date(currentTime.getTime() + 30 * 60 * 1000); - - if (selectedDateTime <= thirtyMinutesAhead) { - alert('Pass can only be generated at least 30 minutes before the scheduled time.'); + + if (availableSlots <= 0) { + Alert.alert("Error", "No slots available for this facility."); return; } - - const expiration = new Date(selectedDateTime); - expiration.setHours(expiration.getHours() + 1); // Set the expiration time as 1 hour after the selected time - - const newPass = { - facility, - date: date.toDateString(), - time: time.toLocaleTimeString(), - count, - expiresAt: expiration.toISOString(), - createdAt: currentTime.toISOString(), + + const currentTime = new Date(); + const expirationTime = new Date( + currentTime.getTime() + 24 * 60 * 60 * 1000 + ); // Pass valid for 1 day + + const newPass: Omit = { + facilityId: selectedFacility, + facilityName: + facilities.find((f) => f.id === selectedFacility)?.name || "", + date: currentDate, + time: currentTime.toLocaleTimeString(), + expiresAt: expirationTime.toISOString(), + count: "1", }; - + try { - const passesCollection = collection(db, 'passes'); - await addDoc(passesCollection, newPass); - alert('Pass generated successfully!'); - } catch (error) { - console.error('Error adding pass: ', error); - alert('Failed to generate pass.'); - } - }; - + const passRef = await addDoc(collection(db, "Facilities", selectedFacility, "passes"), newPass); - const onChangeDate = (event, selectedDate) => { - const currentDate = selectedDate || date; - setShowDatePicker(false); - setDate(currentDate); - }; + const facilityRef = doc(db, "Facilities", selectedFacility); + await updateDoc(facilityRef, { + allocatedSlots: + facilities.find((f) => f.id === selectedFacility)?.allocatedSlots! + 1, + }); - const onChangeTime = (event, selectedTime) => { - const currentTime = selectedTime || time; - setShowTimePicker(false); - setTime(currentTime); - }; + Alert.alert("Success", "Slot booked successfully!"); - const cancelPass = async (id, scheduledTime) => { - const currentTime = new Date(); - const scheduledDateTime = new Date(scheduledTime); - const thirtyMinutesBeforeScheduled = new Date(scheduledDateTime.getTime() - 30 * 60 * 1000); // 30 minutes before the scheduled time - - if (currentTime >= thirtyMinutesBeforeScheduled) { - alert('You can only cancel the pass at least 30 minutes before the scheduled time.'); - return; + setPasses((prevPasses) => [ + ...prevPasses, + { id: passRef.id, ...newPass }, + ]); + } catch (error) { + console.error("Error booking slot: ", error); + Alert.alert("Error", "Failed to book slot. Please try again."); } - - Alert.alert( - "Confirm Cancellation", - "Are you sure you want to cancel this pass?", - [ - { text: "Cancel", style: "cancel" }, - { - text: "Yes", - onPress: async () => { - try { - const passDoc = doc(db, 'passes', id); - await deleteDoc(passDoc); - alert('Pass canceled successfully!'); - } catch (error) { - console.error('Error canceling pass: ', error); - alert('Failed to cancel pass.'); - } - }, - }, - ] - ); }; - - - const renderPass = ({ item }) => { - const currentTime = new Date(); - const expiresAt = new Date(item.expiresAt); - const isExpired = currentTime.getTime() >= expiresAt.getTime(); + const cancelPass = async (passId: string, facilityId: string) => { + try { + await deleteDoc(doc(db, "Facilities", facilityId, "passes", passId)); - if (isExpired) return null; // Don't render expired passes + const facilityRef = doc(db, "Facilities", facilityId); + const facilitySnapshot = await getDoc(facilityRef); + if (facilitySnapshot.exists()) { + const facilityData = facilitySnapshot.data(); + await updateDoc(facilityRef, { + allocatedSlots: (facilityData.allocatedSlots || 1) - 1, + + }); + } - return ( - - {item.facility} - Date: {item.date} - Time: {item.time} - People: {item.count} - Expires At: {expiresAt.toLocaleTimeString()} - cancelPass(item.id, item.expiresAt)} - > - Cancel - - - ); + setPasses((prevPasses) => prevPasses.filter((pass) => pass.id !== passId)); + Alert.alert("Success", "Pass cancelled successfully!"); + } catch (error) { + console.error("Error cancelling pass: ", error); + Alert.alert("Error", "Failed to cancel pass. Please try again."); + } }; return ( - - - navigation.navigate('home')} - style={tw`mr-4`} - > - - - Facilities - - - - - Select Facility: - setFacility(itemValue)} - style={styles.picker} - > - - - - - - - - - - setCount(text)} - /> - - setShowDatePicker(true)} - > - - Choose Date: {date.toDateString()} - - - + + + + {/* Back Button */} setShowTimePicker(true)} + style={styles.backButton} + onPress={() => navigation.goBack()} > - - Choose Time: {time.toLocaleTimeString()} - + - {showDatePicker && ( - - )} + Facilities Booking + - {showTimePicker && ( - + {/* Facility Selection */} + item.id} + renderItem={({ item }) => ( + { + setSelectedFacility(item.id); + setAvailableSlots(item.totalSlots - item.allocatedSlots); + }} + > + {item.name} + + Slots Available: {item.totalSlots - item.allocatedSlots} / {" "} + {item.totalSlots} + + )} + /> - - Generate Pass - - + {selectedFacility && ( + + + Selected Facility: {" "} + {facilities.find((f) => f.id === selectedFacility)?.name} + + + Book Slot + + + )} - - Your Passes - item.id} - renderItem={renderPass} - /> - - - + {/* Passes Section */} + Your Passes + item.id!} + renderItem={({ item }) => ( + + Facility: {item.facilityName} + Date: {item.date} + Time: {item.time} + Expires At: {new Date(item.expiresAt).toLocaleString()} + cancelPass(item.id!, item.facilityId)} + > + Cancel + + + )} + /> + + ); }; const styles = StyleSheet.create({ + safeArea: { + flex: 1, + backgroundColor: "#f8f9fa", + }, container: { flex: 1, - backgroundColor: '#f9f9f9', + backgroundColor: "#f8f9fa", }, - formContainer: { - backgroundColor: 'white', - borderRadius: 10, - padding: 20, - margin: 20, - shadowColor: '#000', - shadowOffset: { width: 0, height: 2 }, - shadowOpacity: 0.25, - shadowRadius: 3.84, - elevation: 5, + headerContainer: { + flexDirection: "row", + alignItems: "center", + backgroundColor: "#001f54", + paddingVertical: 30, + paddingHorizontal: 15, + }, - label: { - fontSize: 16, - marginBottom: 10, - color: '#333', + backButton: { + marginRight: 10, }, - picker: { - height: 50, - marginBottom: 20, - borderWidth: 1, - borderColor: '#ccc', - borderRadius: 5, - backgroundColor: '#f0f0f0', + header: { + fontSize: 24, + fontWeight: "bold", + color: "white", }, - textInput: { - borderWidth: 1, - borderColor: '#ccc', - borderRadius: 5, - padding: 10, - marginBottom: 20, - backgroundColor: '#f0f0f0', + facilitiesList: { + paddingTop: 20, // Added padding to separate from the header }, - button: { - backgroundColor: '#00215E', + facilityButton: { + backgroundColor: "#001f54", padding: 15, - borderRadius: 5, - alignItems: 'center', - marginTop: 10, + borderRadius: 10, + marginBottom: 10, + marginHorizontal: 20, }, - buttonText: { - color: 'white', - fontSize: 16, + facilityText: { + fontSize: 18, + color: "white", }, - passesContainer: { - marginHorizontal: 20, - marginBottom: 20, + facilitySlots: { + fontSize: 14, + color: "#d0e4ff", }, - sectionTitle: { + selectedFacility: { fontSize: 18, - fontWeight: 'bold', - marginBottom: 10, - color: '#333', + marginVertical: 10, + color: "#001f54", + textAlign: "center", }, - passCard: { - backgroundColor: 'white', - borderRadius: 10, - padding: 15, - marginBottom: 10, - shadowColor: '#000', - shadowOffset: { width: 0, height: 2 }, - shadowOpacity: 0.25, - shadowRadius: 3.84, - elevation: 5, + bookButton: { + backgroundColor: "#001f54", + padding: 10, + borderRadius: 5, + alignItems: "center", + margin: 20, }, - passCardTitle: { + bookText: { + color: "white", fontSize: 16, - fontWeight: 'bold', - color: '#00215E', - marginBottom: 5, }, - passCardDetail: { - fontSize: 14, - color: '#555', - marginBottom: 3, + passesHeader: { + fontSize: 20, + fontWeight: "bold", + marginVertical: 10, + color: "#001f54", + textAlign: "center", }, - cancelButton: { - backgroundColor: '#FFA500', + passItem: { + backgroundColor: "#d0e4ff", padding: 10, + borderRadius: 10, + marginBottom: 10, + marginHorizontal: 20, + }, + cancelButton: { + backgroundColor: "#ff4d4d", + padding: 5, borderRadius: 5, - alignItems: 'center', - marginTop: 10, + marginTop: 5, }, - cancelButtonText: { - color: 'white', + cancelText: { + color: "white", fontSize: 14, + textAlign: "center", }, }); -export default FacilityBookingPage; \ No newline at end of file +export default FacilitiesBooking; diff --git a/app/(tabs)/help.tsx b/app/(tabs)/help.tsx index d85b5e5..ed095c7 100644 --- a/app/(tabs)/help.tsx +++ b/app/(tabs)/help.tsx @@ -1,5 +1,5 @@ -import React from 'react'; -import { View, Text, TouchableOpacity, ScrollView, SafeAreaView, Linking } from 'react-native'; +import React, { useState } from 'react'; +import { View, Text, TouchableOpacity, ScrollView, SafeAreaView, Modal } from 'react-native'; import tw from 'twrnc'; import { Ionicons } from '@expo/vector-icons'; import { ArrowLeft } from 'lucide-react-native'; @@ -7,34 +7,54 @@ import { useNavigation } from '@react-navigation/native'; const HelpAndSupportPage = () => { const navigation = useNavigation(); + const [modalVisible, setModalVisible] = useState(false); + const [modalContent, setModalContent] = useState(''); const supportOptions = [ { id: 1, title: 'FAQ', icon: 'help-circle-outline', - onPress: () => Linking.openURL('https://www.example.com/faq'), + content: `Frequently Asked Questions +1. How do I book a facility? + - Go to the "Facilities" section, select a facility, and click "Book Slot." + +2. What is the duration of a booked slot? + - Slots are generally valid for a specific time, depending on the facility. + +3. How can I cancel a booking? + - Navigate to "My Bookings," select the booking, and click "Cancel." + +4. How do I reset my password? + - Go to the login page, click "Forgot Password," and follow the steps to reset your password. + +5. What should I do if I face an issue? + - Contact us via the "Contact Us" option in the Help & Support section.`, }, { id: 2, title: 'Contact Us', icon: 'mail-outline', - onPress: () => Linking.openURL('mailto:support@example.com'), + content: 'You can contact us via email at servelinkuser404@gmail.com.', }, { id: 3, title: 'User Guide', icon: 'book-outline', - onPress: () => Linking.openURL('https://www.example.com/user-guide'), - }, - { - id: 4, - title: 'Submit Feedback', - icon: 'chatbox-outline', - onPress: () => Linking.openURL('https://www.example.com/feedback'), + content: 'This is the user guide to help you navigate our app. 1. Home Page Access key features like notifications, announcements, and navigation options. 2. Facilities BookingView and book slots for amenities directly.Cancel bookings from "My Bookings."3. Guest Acces Add guest details to generate a QR code/OTP. Guests scan the QR code or enter the OTP at entry points.4. Parcel Management Track and confirm parcel deliveries.5. Maintenance RequestsSubmit and track maintenance requests (e.g., plumbing, electrical).6. Emergency AlertsnSend real-time emergency notifications with your location.7. Profile Management Update profile info and set app preferences.8. Notifications Stay updated on bookings, guests, and other alerts.9. Help & Support For assistance, visit the "Help & Support" section or contact us via email.', }, ]; + const openModal = (content) => { + setModalContent(content); + setModalVisible(true); + }; + + const closeModal = () => { + setModalVisible(false); + setModalContent(''); + }; + return ( {/* Header */} @@ -51,7 +71,7 @@ const HelpAndSupportPage = () => { openModal(option.content)} > {option.title} @@ -59,8 +79,31 @@ const HelpAndSupportPage = () => { ))} + + {/* Modal */} + + + + Help & Support + + {modalContent} + + + Close + + + + ); }; -export default HelpAndSupportPage; \ No newline at end of file +export default HelpAndSupportPage; diff --git a/package-lock.json b/package-lock.json index 1a2ae92..9630331 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,11 +14,12 @@ "@react-native-async-storage/async-storage": "^2.0.0", "@react-native-community/datetimepicker": "^8.2.0", "@react-native-firebase/messaging": "^21.6.1", - "@react-native-picker/picker": "^2.8.1", + "@react-native-picker/picker": "^2.10.2", "@react-navigation/native": "^6.1.18", "appwrite": "^16.1.0", "axios": "^1.7.9", "cloudinary-react-native": "^1.0.1", + "date-fns": "^4.1.0", "expo": "~51.0.28", "expo-av": "^14.0.7", "expo-blur": "^13.0.2", @@ -48,6 +49,7 @@ "react-native-animatable": "^1.4.0", "react-native-appwrite": "^0.5.0", "react-native-bcrypt": "^2.4.0", + "react-native-date-picker": "^5.0.8", "react-native-gesture-handler": "~2.16.1", "react-native-image-picker": "^7.2.2", "react-native-nfc-manager": "^3.16.0", @@ -7620,9 +7622,9 @@ } }, "node_modules/@react-native-picker/picker": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@react-native-picker/picker/-/picker-2.8.1.tgz", - "integrity": "sha512-iFhsKQzRh/z3GlmvJWSjJJ4333FdLE/PhXxlGlYllE7sFf+UTzziVY+ajatuJ+R5zDw2AxfJV4v/3tAzUJb0/A==", + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/@react-native-picker/picker/-/picker-2.10.2.tgz", + "integrity": "sha512-kr3OvCRwTYjR/OKlb52k4xmQVU7dPRIALqpyiihexdJxEgvc1smnepgqCeM9oXmNSG4YaV5/RSxFlLC5Z/T/Eg==", "peerDependencies": { "react": "*", "react-native": "*" @@ -13142,6 +13144,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, "node_modules/dayjs": { "version": "1.11.13", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", @@ -24827,6 +24838,15 @@ "resolved": "https://registry.npmjs.org/react-native-bcrypt/-/react-native-bcrypt-2.4.0.tgz", "integrity": "sha512-nC8SR/YCCLIluxd1YEkUX2/xjKELLkO0pgIZc1JGUw9o+wnsfpujm0J8NSPmPEqFUe1n2EkysHnAmuKInDusoQ==" }, + "node_modules/react-native-date-picker": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/react-native-date-picker/-/react-native-date-picker-5.0.8.tgz", + "integrity": "sha512-1l4w4+iLuhOZUSyQrt5DclXnNx3RwEyp+wUrSaBfaHr/3FWtRWjLjS0E9FL4FWuq6vn09Hy9hn8lZJ1DmPc9YQ==", + "peerDependencies": { + "react": ">= 17.0.1", + "react-native": ">= 0.64.3" + } + }, "node_modules/react-native-gesture-handler": { "version": "2.16.2", "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.16.2.tgz", diff --git a/package.json b/package.json index 8dae131..cb2f0eb 100644 --- a/package.json +++ b/package.json @@ -21,11 +21,12 @@ "@react-native-async-storage/async-storage": "^2.0.0", "@react-native-community/datetimepicker": "^8.2.0", "@react-native-firebase/messaging": "^21.6.1", - "@react-native-picker/picker": "^2.8.1", + "@react-native-picker/picker": "^2.10.2", "@react-navigation/native": "^6.1.18", "appwrite": "^16.1.0", "axios": "^1.7.9", "cloudinary-react-native": "^1.0.1", + "date-fns": "^4.1.0", "expo": "~51.0.28", "expo-av": "^14.0.7", "expo-blur": "^13.0.2", @@ -55,6 +56,7 @@ "react-native-animatable": "^1.4.0", "react-native-appwrite": "^0.5.0", "react-native-bcrypt": "^2.4.0", + "react-native-date-picker": "^5.0.8", "react-native-gesture-handler": "~2.16.1", "react-native-image-picker": "^7.2.2", "react-native-nfc-manager": "^3.16.0", From 9348f1571fd0048e3e8e6067d04b5df4d726aa2d Mon Sep 17 00:00:00 2001 From: SreelakshmiBiju Date: Fri, 31 Jan 2025 13:56:17 +0530 Subject: [PATCH 2/2] ticket --- app/(tabs)/facility.tsx | 88 ++++++++++++++++++++++------------------- app/(tabs)/help.tsx | 2 +- 2 files changed, 49 insertions(+), 41 deletions(-) diff --git a/app/(tabs)/facility.tsx b/app/(tabs)/facility.tsx index 708e340..249dcb7 100644 --- a/app/(tabs)/facility.tsx +++ b/app/(tabs)/facility.tsx @@ -6,12 +6,11 @@ import { FlatList, StyleSheet, Alert, - ScrollView, SafeAreaView, } from "react-native"; import { useNavigation } from "@react-navigation/native"; -import { Ionicons } from "@expo/vector-icons"; // Importing icons -import { db } from "../../scripts/firebase"; // Import Firebase config +import { Ionicons } from "@expo/vector-icons"; +import { db } from "../../scripts/firebase"; import { collection, doc, @@ -20,6 +19,9 @@ import { updateDoc, deleteDoc, getDoc, + query, + where, + onSnapshot, } from "firebase/firestore"; type Pass = { @@ -41,6 +43,7 @@ const FacilitiesBooking = () => { const [currentDate, setCurrentDate] = useState( new Date().toISOString().split("T")[0] ); + const userId = "currentUserId"; useEffect(() => { const fetchFacilities = async () => { @@ -52,7 +55,25 @@ const FacilitiesBooking = () => { setFacilities(facilitiesData); }; + const fetchPasses = () => { + const passesRef = collection(db, "passes"); + const q = query(passesRef, where("userId", "==", userId)); + + const unsubscribe = onSnapshot(q, (snapshot) => { + const passesData = snapshot.docs.map((doc) => ({ + id: doc.id, + ...doc.data(), + })) as Pass[]; + setPasses(passesData); + }); + + return unsubscribe; + }; + fetchFacilities(); + const unsubscribePasses = fetchPasses(); + + return () => unsubscribePasses(); }, []); const bookSlot = async () => { @@ -69,7 +90,7 @@ const FacilitiesBooking = () => { const currentTime = new Date(); const expirationTime = new Date( currentTime.getTime() + 24 * 60 * 60 * 1000 - ); // Pass valid for 1 day + ); const newPass: Omit = { facilityId: selectedFacility, @@ -79,23 +100,17 @@ const FacilitiesBooking = () => { time: currentTime.toLocaleTimeString(), expiresAt: expirationTime.toISOString(), count: "1", + userId, }; try { - const passRef = await addDoc(collection(db, "Facilities", selectedFacility, "passes"), newPass); - + await addDoc(collection(db, "passes"), newPass); const facilityRef = doc(db, "Facilities", selectedFacility); await updateDoc(facilityRef, { allocatedSlots: facilities.find((f) => f.id === selectedFacility)?.allocatedSlots! + 1, }); - Alert.alert("Success", "Slot booked successfully!"); - - setPasses((prevPasses) => [ - ...prevPasses, - { id: passRef.id, ...newPass }, - ]); } catch (error) { console.error("Error booking slot: ", error); Alert.alert("Error", "Failed to book slot. Please try again."); @@ -104,20 +119,17 @@ const FacilitiesBooking = () => { const cancelPass = async (passId: string, facilityId: string) => { try { - await deleteDoc(doc(db, "Facilities", facilityId, "passes", passId)); - + await deleteDoc(doc(db, "passes", passId)); const facilityRef = doc(db, "Facilities", facilityId); const facilitySnapshot = await getDoc(facilityRef); + if (facilitySnapshot.exists()) { const facilityData = facilitySnapshot.data(); await updateDoc(facilityRef, { allocatedSlots: (facilityData.allocatedSlots || 1) - 1, - }); + Alert.alert("Success", "Pass cancelled successfully!"); } - - setPasses((prevPasses) => prevPasses.filter((pass) => pass.id !== passId)); - Alert.alert("Success", "Pass cancelled successfully!"); } catch (error) { console.error("Error cancelling pass: ", error); Alert.alert("Error", "Failed to cancel pass. Please try again."); @@ -128,18 +140,15 @@ const FacilitiesBooking = () => { - {/* Back Button */} navigation.goBack()} > - + - Facilities Booking - {/* Facility Selection */} { > {item.name} - Slots Available: {item.totalSlots - item.allocatedSlots} / {" "} - {item.totalSlots} + Slots Available: {item.totalSlots - item.allocatedSlots} / {item.totalSlots} )} @@ -164,8 +172,7 @@ const FacilitiesBooking = () => { {selectedFacility && ( - Selected Facility: {" "} - {facilities.find((f) => f.id === selectedFacility)?.name} + Selected Facility: {facilities.find((f) => f.id === selectedFacility)?.name} Book Slot @@ -173,17 +180,18 @@ const FacilitiesBooking = () => { )} - {/* Passes Section */} Your Passes item.id!} renderItem={({ item }) => ( - Facility: {item.facilityName} - Date: {item.date} - Time: {item.time} - Expires At: {new Date(item.expiresAt).toLocaleString()} + Facility: {item.facilityName} + Date: {item.date} + Time: {item.time} + + Expires At: {new Date(item.expiresAt).toLocaleString()} + cancelPass(item.id!, item.facilityId)} @@ -201,19 +209,18 @@ const FacilitiesBooking = () => { const styles = StyleSheet.create({ safeArea: { flex: 1, - backgroundColor: "#f8f9fa", + backgroundColor: "white", }, container: { flex: 1, - backgroundColor: "#f8f9fa", + backgroundColor: "white", }, headerContainer: { flexDirection: "row", alignItems: "center", - backgroundColor: "#001f54", + backgroundColor: "#000066", paddingVertical: 30, paddingHorizontal: 15, - }, backButton: { marginRight: 10, @@ -224,10 +231,10 @@ const styles = StyleSheet.create({ color: "white", }, facilitiesList: { - paddingTop: 20, // Added padding to separate from the header + paddingTop: 20, }, facilityButton: { - backgroundColor: "#001f54", + backgroundColor: "#000066", padding: 15, borderRadius: 10, marginBottom: 10, @@ -244,11 +251,11 @@ const styles = StyleSheet.create({ selectedFacility: { fontSize: 18, marginVertical: 10, - color: "#001f54", + color: "#000066", textAlign: "center", }, bookButton: { - backgroundColor: "#001f54", + backgroundColor: "#000066", padding: 10, borderRadius: 5, alignItems: "center", @@ -262,7 +269,7 @@ const styles = StyleSheet.create({ fontSize: 20, fontWeight: "bold", marginVertical: 10, - color: "#001f54", + color: "##000066", textAlign: "center", }, passItem: { @@ -285,4 +292,5 @@ const styles = StyleSheet.create({ }, }); + export default FacilitiesBooking; diff --git a/app/(tabs)/help.tsx b/app/(tabs)/help.tsx index ed095c7..f3e3716 100644 --- a/app/(tabs)/help.tsx +++ b/app/(tabs)/help.tsx @@ -20,7 +20,7 @@ const HelpAndSupportPage = () => { - Go to the "Facilities" section, select a facility, and click "Book Slot." 2. What is the duration of a booked slot? - - Slots are generally valid for a specific time, depending on the facility. + - Slots are generally valid for 1 day. 3. How can I cancel a booking? - Navigate to "My Bookings," select the booking, and click "Cancel."