diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/matadors-rn-medica.iml b/.idea/matadors-rn-medica.iml new file mode 100644 index 0000000..d6ebd48 --- /dev/null +++ b/.idea/matadors-rn-medica.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..639900d --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..45338b1 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/other.xml b/.idea/other.xml new file mode 100644 index 0000000..0d3a1fb --- /dev/null +++ b/.idea/other.xml @@ -0,0 +1,263 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app.json b/app.json index ab01d79..b7b2fad 100644 --- a/app.json +++ b/app.json @@ -8,8 +8,9 @@ "icon": "./assets/images/icon.png", "splash": { "image": "./assets/images/splash.png", - "resizeMode": "contain", - "backgroundColor": "#000000" + "resizeMode": "cover", + "backgroundColor": "#ffffff", + "textAlign": "center" }, "assetBundlePatterns": [ "**/*" diff --git a/app/(app)/ActionMenu/AllDoctorScreen.tsx b/app/(app)/ActionMenu/AllDoctorScreen.tsx index 30791c8..c770746 100644 --- a/app/(app)/ActionMenu/AllDoctorScreen.tsx +++ b/app/(app)/ActionMenu/AllDoctorScreen.tsx @@ -1,34 +1,46 @@ -import React,{ReactElement, useEffect, useState} from 'react'; -import { StyleSheet, Text, Image, View, TouchableHighlight, SafeAreaView, Button, Alert, Platform, Dimensions,TextInput, ScrollView, Pressable} from 'react-native' -import { Feather } from '@expo/vector-icons'; -import { AntDesign } from '@expo/vector-icons'; -import { Ionicons } from '@expo/vector-icons'; -import DoctorComponent from '@/components/DoctorComponent'; -import { FontAwesome } from '@expo/vector-icons'; -import { SvgXml } from "react-native-svg" -import { whiteHeart } from '@/assets/icons/whiteHeart'; -import { blueheart } from '@/assets/icons/blueHeart'; -import { star } from '@/assets/icons/star'; -import { search } from '@/assets/icons/search'; -import { more } from '@/assets/icons/more'; -import { LightleftArrow } from '@/assets/icons/left'; -import HeaderComponent from '@/components/HeaderComponent'; -import SearchComponent from '@/components/SearchComponent'; -import FoundDoctorCount from '@/components/FoundDoctorCount'; -import NofoundComponent from '@/components/NofoundComponent'; -import RemovefavoritePopup from '@/components/RemovefavoritePopup'; -import FilterPopup from '@/components/FilterSearchComponent'; -import { StatusBar } from 'expo-status-bar'; -import NotFoundScreen from '@/app/+not-found'; -import { ThemeContext } from '@/ctx/ThemeContext'; -import { useContext } from 'react'; -import { supabase } from '@/lib/supabase'; -import { router } from 'expo-router'; - - +import React, { ReactElement, useEffect, useState } from "react"; +import { + StyleSheet, + Text, + Image, + View, + TouchableHighlight, + SafeAreaView, + Button, + Alert, + Platform, + Dimensions, + TextInput, + ScrollView, + Pressable, +} from "react-native"; +import { Feather } from "@expo/vector-icons"; +import { AntDesign } from "@expo/vector-icons"; +import { Ionicons } from "@expo/vector-icons"; +import DoctorComponent from "@/components/DoctorComponent"; +import { FontAwesome } from "@expo/vector-icons"; +import { SvgXml } from "react-native-svg"; +import { whiteHeart } from "@/assets/icons/whiteHeart"; +import { blueheart } from "@/assets/icons/blueHeart"; +import { star } from "@/assets/icons/star"; +import { search } from "@/assets/icons/search"; +import { more } from "@/assets/icons/more"; +import { LightleftArrow } from "@/assets/icons/left"; +import HeaderComponent from "@/components/HeaderComponent"; +import SearchComponent from "@/components/SearchComponent"; +import FoundDoctorCount from "@/components/FoundDoctorCount"; +import NofoundComponent from "@/components/NofoundComponent"; +import RemovefavoritePopup from "@/components/RemovefavoritePopup"; +import FilterPopup from "@/components/FilterSearchComponent"; +import { StatusBar } from "expo-status-bar"; +import NotFoundScreen from "@/app/+not-found"; +import { ThemeContext } from "@/ctx/ThemeContext"; +import { useContext } from "react"; +import { supabase } from "@/lib/supabase"; +import { router } from "expo-router"; const tableName = "doctors"; -const favoriteTable="favorite_doctors" +const favoriteTable = "favorite_doctors"; interface imageMapProp { [key: string]: ReturnType; @@ -37,15 +49,15 @@ interface imageMapProp { interface iconMappingProp { [key: string]: ReactElement; } -interface Doctor{ - id: number, - first_name: string, - last_name: string, - hospital: string, - rate: string, - review: string, - specialization: string, - about:string +interface Doctor { + id: number; + first_name: string; + last_name: string; + hospital: string; + rate: string; + review: string; + specialization: string; + about: string; } export const iconMapping: iconMappingProp = { @@ -61,141 +73,149 @@ function DoctorScreen() { const [showFilter, setShowfilter] = useState(false); const [doctors, setDoctors] = useState([]); const { theme, changeTheme } = useContext(ThemeContext); - const [selectedSpecilization, setSelectedSpecilization] = useState("All") - const [specialization, setSpecialization] = useState([]) - const [isloading, setIsLoading] = useState(false) - const [favoriteDoctors,setFavoriteDoctors]=useState([]) + const [selectedSpecilization, setSelectedSpecilization] = + useState("All"); + const [specialization, setSpecialization] = useState([]); + const [isloading, setIsLoading] = useState(false); + const [favoriteDoctors, setFavoriteDoctors] = useState([]); const containerStyle = theme === "dark" ? styles.outerDark : styles.outerLight; const scrollbackColor = theme === "dark" ? styles.scrollDark : styles.scrollLight; - const [loggeduser, setLoggedUser] = useState() - const [profile, setProfile] = useState(null) - const [patient_id,setPatient_id]=useState() + const [loggeduser, setLoggedUser] = useState(); + const [profile, setProfile] = useState(null); + const [patient_id, setPatient_id] = useState(); useEffect(() => { const fetchUser = async () => { - - const { data: { user },error } = await supabase.auth.getUser() + const { + data: { user }, + error, + } = await supabase.auth.getUser(); if (error) { - console.error("error fetching user") + console.error("error fetching user"); } else { - setLoggedUser(user?.id) + setLoggedUser(user?.id); } - } - fetchUser() - - }, [loggeduser]) + }; + fetchUser(); + }, [loggeduser]); useEffect(() => { const fetchUserProfile = async () => { if (loggeduser) { const { data, error } = await supabase .from("patients") .select("*") - .eq('auth_id', loggeduser) - .single() + .eq("auth_id", loggeduser) + .single(); if (error) { - console.error("error while retrieving profile",error) + console.error("error while retrieving profile", error); } else { - setProfile(data) - setPatient_id(data.id) - console.log(data) - + setProfile(data); + setPatient_id(data.id); + // console.log(data) } - - } - } - fetchUserProfile() - }, [loggeduser]) - - useEffect(() => { - async function fetchData() { - setIsLoading(true); - - const { data: doctorData, error: doctorError } = await supabase.from('doctors').select('*'); - if (doctorError) { - setIsLoading(false); - throw new Error('Error fetching data:' + doctorError.message); - } - - const uniqueSpecialization = Array.from(new Set(doctorData.map((doctor) => doctor.specialization))); - setSpecialization(['All', ...uniqueSpecialization]); - - const docIds = doctorData.map(doc => doc.id); - - const { data: reviewData, error: reviewError } = await supabase - .from('reviews') - .select('*') - .in('doctor_id', docIds); - - if (reviewError) { - setIsLoading(false); - console.error('Error fetching reviews:', reviewError); - return; - } - - const mergedData = doctorData.map(doctor => { - const reviews = reviewData.filter(review => review.doctor_id === doctor.id); - - - const totalStars = reviews.reduce((sum, review) => sum + parseFloat(review.stars), 0); - const result= reviews.length === 0 ? 0 :(totalStars / reviews.length).toFixed(1); - - return { ...doctor, reviews ,result }; - }); - - setDoctors(mergedData); + }; + fetchUserProfile(); + }, [loggeduser]); + + useEffect(() => { + async function fetchData() { + setIsLoading(true); + + const { data: doctorData, error: doctorError } = await supabase + .from("doctors") + .select("*"); + if (doctorError) { setIsLoading(false); + throw new Error("Error fetching data:" + doctorError.message); } - - fetchData(); - }, []); - console.log("this is retrived specilization:", specialization) - useEffect(() => { - const fetchFavoritesDoctor = async () => { - if (patient_id) { - const { data, error } = await supabase - .from(favoriteTable) - .select("*") - .eq("patient", patient_id) - if (error) { - console.error("error while fetching ",error) - } - - setFavoriteDoctors(data?.map((item:any)=>item.favorite_doctor)||[]) - } - - } - fetchFavoritesDoctor() - - },[patient_id]) - const handleSearchPressed = () => { - setShowSearch(true) - } - const handleSearchSubmit = (text: string) => { - setSearchTerm(text.toLowerCase()) - } - - const handleFilter = () => { - setShowfilter(true) + + const uniqueSpecialization = Array.from( + new Set(doctorData.map((doctor) => doctor.specialization)) + ); + setSpecialization(["All", ...uniqueSpecialization]); + + const docIds = doctorData.map((doc) => doc.id); + + const { data: reviewData, error: reviewError } = await supabase + .from("reviews") + .select("*") + .in("doctor_id", docIds); + + if (reviewError) { + setIsLoading(false); + console.error("Error fetching reviews:", reviewError); + return; + } + + const mergedData = doctorData.map((doctor) => { + const reviews = reviewData.filter( + (review) => review.doctor_id === doctor.id + ); + + const totalStars = reviews.reduce( + (sum, review) => sum + parseFloat(review.stars), + 0 + ); + const result = + reviews.length === 0 ? 0 : (totalStars / reviews.length).toFixed(1); + + return { ...doctor, reviews, result }; + }); + + setDoctors(mergedData); + setIsLoading(false); } - + + fetchData(); + }, []); + // console.log("this is retrived specilization:", specialization) + useEffect(() => { + const fetchFavoritesDoctor = async () => { + if (patient_id) { + const { data, error } = await supabase + .from(favoriteTable) + .select("*") + .eq("patient", patient_id); + if (error) { + console.error("error while fetching ", error); + } + + setFavoriteDoctors( + data?.map((item: any) => item.favorite_doctor) || [] + ); + } + }; + fetchFavoritesDoctor(); + }, [patient_id]); + const handleSearchPressed = () => { + setShowSearch(true); + }; + const handleSearchSubmit = (text: string) => { + setSearchTerm(text.toLowerCase()); + }; + + const handleFilter = () => { + setShowfilter(true); + }; + const handleSpecializationChange = (specialization: string) => { - setSelectedSpecilization(specialization) - setSearchTerm('') - - } + setSelectedSpecilization(specialization); + setSearchTerm(""); + }; const handleAddfovorite = async (doctorId: number) => { - const patientId = patient_id - const { error } = await supabase.from(favoriteTable).insert({ patient: patientId, favorite_doctor: doctorId }) + const patientId = patient_id; + const { error } = await supabase + .from(favoriteTable) + .insert({ patient: patientId, favorite_doctor: doctorId }); if (error) { - console.error("error while adding doctor to favorite", error) + console.error("error while adding doctor to favorite", error); return; } - setFavoriteDoctors(prev=>[...prev,doctorId]) - - } + setFavoriteDoctors((prev) => [...prev, doctorId]); + }; const updateFavoriteDoctors = async () => { const { data, error } = await supabase .from("favorite_doctors") @@ -204,10 +224,12 @@ function DoctorScreen() { if (error) { console.error("Error fetching favorite doctors:", error); } else { - setFavoriteDoctors(data.map((item: { favorite_doctor: number }) => item.favorite_doctor)); + setFavoriteDoctors( + data.map((item: { favorite_doctor: number }) => item.favorite_doctor) + ); } }; - const handleIconClick = (doctor: Doctor,doctorId:number) => { + const handleIconClick = (doctor: Doctor, doctorId: number) => { if (favoriteDoctors.includes(doctor.id)) { setSelectedDoctor(doctor); setShowPopup(true); @@ -215,145 +237,139 @@ function DoctorScreen() { handleAddfovorite(doctorId); } }; - - - const filteredDoctors = doctors.filter(doctor => { - const matchSearchTerm = searchTerm.length > 0 ? doctor.last_name.toLowerCase().includes(searchTerm.toLowerCase())||doctor.first_name.toLowerCase().includes(searchTerm.toLowerCase()) : true - const matchSpecialization = selectedSpecilization === 'All' || doctor.specialization === selectedSpecilization - return matchSearchTerm&&matchSpecialization - - }) + const filteredDoctors = doctors.filter((doctor) => { + const matchSearchTerm = + searchTerm.length > 0 + ? doctor.last_name.toLowerCase().includes(searchTerm.toLowerCase()) || + doctor.first_name.toLowerCase().includes(searchTerm.toLowerCase()) + : true; + const matchSpecialization = + selectedSpecilization === "All" || + doctor.specialization === selectedSpecilization; + return matchSearchTerm && matchSpecialization; + }); - return ( - - - - - - { - !showSearch ? ( - - ) : ( - - - ) - } - - - + + + + {!showSearch ? ( + + ) : ( + + )} + + + + {specialization.map((specialization, index) => ( + handleSpecializationChange(specialization)} + style={[ + styles.categoryBtn, + selectedSpecilization === specialization + ? styles.firstCategoryBtn + : {}, + ]} + > + + {specialization} + + + ))} + + + + {showSearch && } + + + - - {specialization.map((specialization, index) => - handleSpecializationChange(specialization)} style={[styles.categoryBtn, - selectedSpecilization === specialization ? styles.firstCategoryBtn : {}, - ]}> - - {specialization} - - - )} - - - - - {showSearch && ( - - )} - - - - {filteredDoctors.length > 0 ? ( - - filteredDoctors.map((doctor: any, index: number) => { - - - return( - + paddingBottom: 150, + paddingTop: 20, + }} + > + {filteredDoctors.length > 0 ? ( + filteredDoctors.map((doctor: any, index: number) => { + return ( + router.push({ pathname: "/ActionMenu/Booking/Doctor_details", params: { id: doctor.id } })} + path={() => + router.push({ + pathname: "/ActionMenu/Booking/Doctor_details", + params: { id: doctor.id }, + }) + } imageSource={{ uri: doctor.image }} name={`${doctor.first_name} ${doctor.last_name}`} - iconComponent={favoriteDoctors.includes(doctor.id) ? ( - - ) : ( - - )} + iconComponent={ + favoriteDoctors.includes(doctor.id) ? ( + + ) : ( + + ) + } professionalTitle={doctor.specialization} hospital={doctor.hospital_name} star={} review={doctor.reviews.length} rate={doctor.result} - addRemoveFavorite={() => handleIconClick(doctor,doctor.id) } - - + addRemoveFavorite={() => + handleIconClick(doctor, doctor.id) + } /> - - )}) - - ) : ( - - )} - - - - - - - - - - setShowPopup(false)} - visible={showpopUp} - onClose={() => setShowPopup(false)} - doctor={selectedDoctor} - updateFavoriteDoctors={updateFavoriteDoctors} - - - /> - setShowfilter(false)} - visible={showFilter} - onClose={() => setShowfilter(false)} - - - - /> - - - - - - ); + ); + }) + ) : ( + + )} + + + + setShowPopup(false)} + visible={showpopUp} + onClose={() => setShowPopup(false)} + doctor={selectedDoctor} + updateFavoriteDoctors={updateFavoriteDoctors} + /> + setShowfilter(false)} + visible={showFilter} + onClose={() => setShowfilter(false)} + /> + + ); } export default DoctorScreen; diff --git a/app/(app)/ActionMenu/Booking/EnterYourPin.tsx b/app/(app)/ActionMenu/Booking/EnterYourPin.tsx index 21c1a21..f690703 100644 --- a/app/(app)/ActionMenu/Booking/EnterYourPin.tsx +++ b/app/(app)/ActionMenu/Booking/EnterYourPin.tsx @@ -22,26 +22,51 @@ import { supabase } from "@/lib/supabase"; export default function EnterYourPin() { const [isDark, setIsDark] = useState(false); const modal = useModal(); - const {doctor_id,hour,date,packageTitle,packagePrice,problem,user_id,patient_id,duration} = useLocalSearchParams() + const { + doctor_id, + hour, + date, + packageTitle, + packagePrice, + problem, + user_id, + patient_id, + duration, + } = useLocalSearchParams(); const { theme, changeTheme } = useContext(ThemeContext); async function bookAppointment() { const { error } = await supabase - .from('appointment') - .insert({ doctor_id: doctor_id, time:hour,date:date, package: packageTitle, price: packagePrice, illness_descr: problem,user_id:patient_id,duration:duration}); + .from("appointment") + .insert({ + doctor_id: doctor_id, + time: hour, + date: date, + package: packageTitle, + price: packagePrice, + illness_descr: problem, + user_id: patient_id, + duration: duration, + }); if (error) { console.error("Error booking appointment:", error); } } - console.log("this is from lastpage",doctor_id,hour,packageTitle,packagePrice,problem) + console.log( + "this is from lastpage", + doctor_id, + hour, + packageTitle, + packagePrice, + problem + ); function successBooking() { - router.push("ActionMenu");; + router.push("ActionMenu"); modal.hide(); } async function handlePIN() { - - await bookAppointment() + await bookAppointment(); modal.show({ children: ( -