diff --git a/app/Appointments/index.tsx b/app/Appointments/index.tsx index 8b432497..19860bad 100644 --- a/app/Appointments/index.tsx +++ b/app/Appointments/index.tsx @@ -21,6 +21,7 @@ function Screen() { const [notupcome, setNotupcome] = useState(false); const [isModalVisible, setIsModalVisible] = useState(false); const[appointmentData, setAppointmentData]=useState([]); + const[completedAppointment, setCompletedAppointment]=useState([]); const { doctorId } = useLocalSearchParams<{ doctorId: string }>(); const handleUpcoming = () => { @@ -54,7 +55,7 @@ function Screen() { } }; - const fetchAppointment=async()=>{ +const fetchAppointment=async()=>{ try{ const { data: userData, error: userError } = await supabase.auth.getUser(); if (userError) throw userError; @@ -71,16 +72,13 @@ const{data, error}=await supabase hospital ) `) -.eq("patient_id", userId); +.eq("patient_id", userId).eq("status", "Booked").order("appointment_date", { ascending: false }) +.order("appointment_time", { ascending: false }) if(error){ console.log("Error occured while fetching appointments", error) }else{ setAppointmentData(data); - console.log("fetched data:"); - setTimeout(()=>{ - router.push("/(tabs)/appointment") - },0) }} catch(error){ console.log(error); @@ -91,6 +89,43 @@ useEffect(()=>{ fetchAppointment(); },[]) +const fetchCompletedAppointment=async()=>{ + try{ + const { data: userData, error: userError } = await supabase.auth.getUser(); + if (userError) throw userError; + const userId = userData?.user?.id; +const{data, error}=await supabase +.from("appointment") +.select(` +*, +doctor( + id, + name, + role, + image, + hospital +) +`) +.eq("patient_id", userId) +.eq("status", "Completed").order("appointment_date", { ascending: false }) +.order("appointment_time", { ascending: false }) + +if(error){ +console.log("Error occured while fetching appointments", error) +}else{ +setCompletedAppointment(data); + +}} +catch(error){ +console.log(error); +} +} +useEffect(()=>{ + +fetchCompletedAppointment(); +},[]) + + const getPackageIcon = (typecall:any) => { switch (typecall) { case 'Voice Call': @@ -219,60 +254,6 @@ const getPackageIcon = (typecall:any) => { contentContainerStyle={styles.scrollViewContent} showsVerticalScrollIndicator={false} > - {/* {cancels && ( - - - - - - - - )} */} {upcoming && ( {appointmentData.map((appointment:any, index:any) => ( @@ -289,74 +270,35 @@ const getPackageIcon = (typecall:any) => { backcad="bg-white rounded-xl flex-row p-4 w-400 items-center gap-7" chance="Cancel Appointment" cantchance="Reschedule" - // fact={() => router.push("/Appointments/reschedul")} - // cancle={() => setIsModalVisible(true)} + fact={() => router.push("/Appointments/reschedul")} + cancle={() => setIsModalVisible(true)} /> ))} )} - {/* {complete && ( + {complete && ( + {completedAppointment.map((appointment:any, index:any) => ( router.push("/Appointments/voice-call/writeReview")} - /> - router.push("/Appointments/voice-call/writeReview")} - - /> - router.push("/Appointments/voice-call/writeReview")} - /> - router.push("/Appointments/voice-call/writeReview")} + fact={() => router.push({pathname:"/Appointments/voice-call/writeReview", + params:{appointmentId:appointment.doctor.id}})} /> + ))} - )} */} + )} {notupcome && ( diff --git a/app/Appointments/voice-call/writeReview.tsx b/app/Appointments/voice-call/writeReview.tsx index 1539b5dd..4d606fad 100644 --- a/app/Appointments/voice-call/writeReview.tsx +++ b/app/Appointments/voice-call/writeReview.tsx @@ -1,8 +1,9 @@ import React, { useState, useEffect } from "react"; import { View, Text, TouchableOpacity, Image, TextInput, StyleSheet, Modal, ScrollView, SafeAreaView, Pressable } from "react-native"; -import { router } from "expo-router"; +import { router, useLocalSearchParams } from "expo-router"; import { useFonts } from 'expo-font'; import FiveStarRating from "../doctorcard/star"; +import { supabase } from "@/app/supabase"; interface CustomCheckBoxProps { selected: boolean; @@ -21,12 +22,9 @@ export default function Writereview() { const [isModalVisible, setIsModalVisible] = useState(false); const [isoption, setIsoption] = useState(""); const [text, setText] = useState(''); - const [fontLoaded] = useFonts({ - 'UrbanistBold': require('../../../assets/fonts/Urbanist-Bold.ttf'), - 'UrbanistRegular': require("../../../assets/fonts/Urbanist-Regular.ttf"), - 'Urbanist-SemiBold': require("../../../assets/fonts/Urbanist-SemiBold.ttf"), - 'UrbanistMedium': require("../../../assets/fonts/Urbanist-Medium.ttf") - }); + const [name, setName]=useState(""); + const [image, setImage]=useState(""); + const {appointmentId}=useLocalSearchParams(); const handleChangeText = (value: string) => { setText(value); @@ -34,12 +32,20 @@ export default function Writereview() { const isSubmitEnabled = text.trim().length > 0 && isoption.length > 0; - if (!fontLoaded) { - return null; - } + const Options = ["Yes", "No"]; + useEffect(()=>{ + const fetchDoctor=async()=>{ + const {data, error}=await supabase.from("doctor").select("*").eq("id",appointmentId).single(); + if(data){ + setName(data.name); + console.log(data.name); + setImage(data.image) + } + if (error) throw error} + fetchDoctor()},[]) return ( <> Write a Review - + How was your experience - with Dr. Drake Boeson? + with {name}? @@ -92,7 +98,7 @@ export default function Writereview() { placeholder="Your review here..." style={styles.textInput} /> - Would you recommend Dr. Drake Boeson to your friends? + Would you recommend {name} to your friends? {Options.map((option, index) => ( @@ -184,4 +190,10 @@ const styles = StyleSheet.create({ width: '100%', minHeight: 100, }, + doctorImage: { + width: 120, + height: 120, + borderRadius: 60, + marginBottom: 10, + }, }); diff --git a/app/chat-history/VideoCall.tsx b/app/chat-history/VideoCall.tsx index bca03a5b..a8e720cc 100644 --- a/app/chat-history/VideoCall.tsx +++ b/app/chat-history/VideoCall.tsx @@ -1,64 +1,45 @@ -import React from "react"; +import React, {useState, useEffect} from "react"; import { View, ScrollView } from "react-native"; import DoctorVideo from "@/components/cards/DoctorVideo"; import { useRouter } from "expo-router"; -import { DoctorCard } from "./types"; // Import the types - +import { DoctorCard } from "./types"; +import { supabase } from "../supabase"; const VideoCall = () => { const router = useRouter(); + const [appointment, setAppointment]=useState([]); - const docCards: DoctorCard[] = [ - { - name: "Dr. Randy Wigham", - callDay: "Wednesday", - callTime: "1:00 PM", - images: require("../../assets/doctors/doc2.png"), - }, - { - name: "Dr. Jenny Watson", - callDay: "Wednesday", - callTime: "1:00 PM", - images: require("../../assets/doctors/doc3.png"), - }, - { - name: "Dr. Raul Zirkind", - callDay: "Wednesday", - callTime: "1:00 PM", - images: require("../../assets/doctors/doc1.png"), - }, - { - name: "Dr. Elijah Baranick", - callDay: "Wednesday", - callTime: "1:00 PM", - images: require("../../assets/doctors/doc2.png"), - }, - { - name: "Dr. Stephen Shute", - callDay: "Wednesday", - callTime: "1:00 PM", - images: require("../../assets/doctors/doc5.png"), - }, - ]; - - const handlePress = (doctor: DoctorCard) => { + useEffect(()=>{ + const fetchAppointments=async()=>{ + const {data, error}=await supabase.auth.getUser(); + if(error) throw error; + const userId=data?.user?.id; + const {data:AppointmentData, error:Error}=await supabase.from("appointment").select("*, doctor(name,image)").eq("patient_id", userId).eq("package","Video Call").eq("status", "Completed") + if(Error) throw Error + if(AppointmentData){ + setAppointment(AppointmentData); + } + } + fetchAppointments(); + },[]) + + const handlePress = (appointmentId:any) => { router.push({ pathname: "/chat-history/VideoRecord", - params: { doctor: JSON.stringify(doctor) }, + params: {appointmentId}, }); }; - return ( - {docCards.map((doctor, index) => ( + {appointment.map((appointments, index) => ( handlePress(doctor)} - doctorName={doctor.name} - doctorImage={doctor.images} - callType="Video Call" - callDay={doctor.callDay} - callTime={doctor.callTime} + onPress={() => handlePress(appointments.id)} + doctorName={appointments.doctor.name} + doctorImage={appointments.doctor.image} + callType={appointments.package} + callDay={appointments.appointment_date} + callTime={appointments.appointment_time.slice(0,5)} isVideoCallScreen={false} /> ))} diff --git a/app/chat-history/VideoRecord.tsx b/app/chat-history/VideoRecord.tsx index a11bc7ce..f6317a02 100644 --- a/app/chat-history/VideoRecord.tsx +++ b/app/chat-history/VideoRecord.tsx @@ -14,20 +14,22 @@ import PlayButton from "@/components/cards/PlayButton"; import { useRouter, useLocalSearchParams } from "expo-router"; import { SvgXml } from "react-native-svg"; import AsyncStorage from "@react-native-async-storage/async-storage"; - -import { DoctorCard } from "./types"; import { moreTransparent } from "@/assets/icons/more"; import { back } from "@/assets/icons/userprofile/icons"; +import { supabase } from "../supabase"; const VideoRecord: React.FC = () => { const router = useRouter(); - const { doctor: doctorString } = useLocalSearchParams(); - const doctor: DoctorCard = doctorString - ? JSON.parse(doctorString as string) - : null; - + + +const {appointmentId}=useLocalSearchParams(); const [modalVisible, setModalVisible] = useState(false); const [videoDuration, setVideoDuration] = useState(0); + const[ name, setName]=useState(""); + const[date, setDate]=useState(""); + const[time, setTime]=useState(""); + const[packageType, setPackage]=useState(""); + const[image, setImage]=useState(""); useEffect(() => { const fetchDuration = async () => { @@ -40,9 +42,7 @@ const VideoRecord: React.FC = () => { fetchDuration(); }, []); - if (!doctor) { - return null; - } + const handlePress = () => { router.push("/chat-history/PlayRecord"); @@ -64,7 +64,7 @@ const VideoRecord: React.FC = () => { setModalVisible(false); }; - const { name, images, callDay, callTime } = doctor; + const formatTime = (timeInSeconds: number) => { const hours = Math.floor(timeInSeconds / 3600); @@ -79,6 +79,21 @@ const VideoRecord: React.FC = () => { return `${minutes}:${String(seconds).padStart(2, "0")} minutes`; } }; + useEffect(()=>{ + const fetchAppointments=async()=>{ + const {data:AppointmentData, error:Error}=await supabase.from("appointment").select("*, doctor(name,image)").eq("id",appointmentId).single(); + if(Error) throw Error + if(AppointmentData){ + setName(AppointmentData.doctor.name); + setPackage(AppointmentData.package); + setImage(AppointmentData.doctor.image); + setTime(AppointmentData.appointment_time); + setDate(AppointmentData.appointment_date); + + } + } + fetchAppointments(); + },[appointmentId]) return ( @@ -89,12 +104,12 @@ const VideoRecord: React.FC = () => { - { + const [messages, setMessage]=useState([]); + const [userId, setUserId] = useState(""); + const [appointment, setAppointment]=useState([]); + const [selectedAppointmentId, setSelectedAppointmentId] = useState(null); + + const handleDocName = (doc: string, appointmentId: string) => { setDocname(doc); + setSelectedAppointmentId(appointmentId); setIsModalVisible(true); }; - const renderItems = ({ item }: { item: MessagesType }) => { + + useEffect(()=>{ +const fetchAppointments=async()=>{ +const {data, error}=await supabase.auth.getUser(); +if(error) throw error; +const userId=data?.user?.id; +setUserId(userId); +const {data:AppointmentData, error:Error}=await supabase.from("appointment").select("*, doctor(name,image)").eq("patient_id", userId).eq("package","Messaging").eq("status", "Completed") +if(Error) throw Error +if(AppointmentData){ +setAppointment(AppointmentData); +} +const{data:MessageData, error:MessageError}=await supabase.from("messages").select("*") +if(MessageData){ + setMessage(MessageData); +} +if(MessageError)throw MessageError; + +} +fetchAppointments(); + },[]) + + + const renderHistory = (appointment: any, index:number) => { return ( - + - + handleDocName(item.name)} + onPress={() => handleDocName(appointment.doctor.name, appointment.id)} > - {item.name} + {appointment.doctor.name} - {item.message} + ... - {item.date} + {appointment.appointment_date} - {item.time} + {appointment.appointment_time.slice(0,5)} @@ -124,58 +154,28 @@ export default function Chathistory() { - - - - - - - + {messages + .filter((message: any) => message.appointment_id === selectedAppointmentId) + .map((message: any, index: any) => ( + + ))} + + + + Session Ended + + + + - - - - - {/* - 16:03 PM - - */} @@ -249,16 +249,12 @@ export default function Chathistory() { - {selected === "Messages" && ( - + + {appointment.map((appointmentItem,index) => renderHistory(appointmentItem,index))} + )} - +{selected==="Calls"&&} {selected === "Videos" && } diff --git a/app/chat-history/singleCall.tsx b/app/chat-history/singleCall.tsx index 10cf37da..e9e68204 100644 --- a/app/chat-history/singleCall.tsx +++ b/app/chat-history/singleCall.tsx @@ -9,9 +9,10 @@ import { useCallback, useEffect, useRef, useState } from 'react'; import { play } from "@/assets/icons/playBtn"; import { download } from '@/assets/icons/download'; import { deleteRed } from '@/assets/icons/delete'; -import { router } from 'expo-router'; +import { router, useLocalSearchParams } from 'expo-router'; import { AVPlaybackSource, AVPlaybackStatus, AVPlaybackStatusSuccess, Audio } from "expo-av"; import { Sound } from 'expo-av/build/Audio'; +import { supabase } from '../supabase'; const { width } = Dimensions.get('window'); const WAVEFORM_ELEMENTS_COUNT = 50; @@ -23,18 +24,26 @@ export default function SingleCall() { const [duration, setDuration] = useState(1); const [sound, setSound] = useState(null); const progressAnim = useRef(new Animated.Value(0)).current; + const { appointmentId } = useLocalSearchParams(); const intervalRef = useRef(null); const [waveformHeights, setWaveformHeights] = useState([]); - + const [appointment, setAppointment] = useState([]); + const [name, setName] = useState(""); + const [date, setDate] = useState(""); + const [time, setTime] = useState(""); + const [packageType, setPackage] = useState(""); + const [image, setImage] = useState(""); const generateWaveformHeights = () => { + return Array.from({ length: WAVEFORM_ELEMENTS_COUNT }, () => Math.random() * 50 + 10); }; - const handleLoad= async()=>{ + const handleLoad = async () => { const { sound } = await Audio.Sound.createAsync(require('@/assets/Travis-Mafia.mp3')); + setSound(sound); await sound.loadAsync(require('@/assets/Travis-Mafia.mp3')); const status = await sound.getStatusAsync(); - if (status.isLoaded){ + if (status.isLoaded) { setDuration(status.durationMillis); } } @@ -80,12 +89,12 @@ export default function SingleCall() { const formatTime = (millis: number) => { const minutes = Math.floor(millis / 60 / 1000); - const seconds= Math.round(((millis/60/1000)-minutes)*60); - return seconds<10? `${minutes} minutes and 0${seconds} seconds`:`${minutes} minutes and ${seconds} seconds`;; + const seconds = Math.round(((millis / 60 / 1000) - minutes) * 60); + return seconds < 10 ? `${minutes} minutes and 0${seconds} seconds` : `${minutes} minutes and ${seconds} seconds`;; } - useEffect(()=>{ + useEffect(() => { handleLoad(); - },[]) + }, []) useEffect(() => { intervalRef.current = setInterval(() => { handleProgress(); @@ -111,6 +120,20 @@ export default function SingleCall() { setWaveformHeights(generateWaveformHeights()); }, [sound]); + useEffect(() => { + const fetchAppointments = async () => { + const { data: AppointmentData, error: Error } = await supabase.from("appointment").select("*, doctor(name,image)").eq("id", appointmentId).single() + if (AppointmentData) { + setName(AppointmentData.doctor.name); + setPackage(AppointmentData.package); + setImage(AppointmentData.doctor.image); + setTime(AppointmentData.appointment_time); + setDate(AppointmentData.appointment_date); + } + } + fetchAppointments(); + }, [appointmentId]) + return ( <> @@ -138,13 +161,12 @@ export default function SingleCall() { setVisible(!visible)} /> - @@ -160,13 +182,13 @@ export default function SingleCall() { {waveformHeights.map((height, index) => { const barWidth = width * 0.75 / WAVEFORM_ELEMENTS_COUNT; const barProgress = progressAnim.interpolate({ - inputRange: [0, (index ) / WAVEFORM_ELEMENTS_COUNT * width], + inputRange: [0, (index) / WAVEFORM_ELEMENTS_COUNT * width], outputRange: [0, 1], extrapolate: 'clamp', }); const backgroundColor = barProgress.interpolate({ inputRange: [0, 1], - outputRange: ['#E9F0FF','#246BFD'] + outputRange: ['#E9F0FF', '#246BFD'] }); return ( { +export default function VoiceCalls() { + const[appointment, setAppointment]=useState([]); + + useEffect(()=>{ + const fetchAppointments=async()=>{ + const {data, error}=await supabase.auth.getUser(); + if(error) throw error; + const userId=data?.user?.id; + const {data:AppointmentData, error:Error}=await supabase.from("appointment").select("*, doctor(name,image)").eq("patient_id", userId).eq("package","Voice Call").eq("status", "Completed") + if(Error) throw Error + if(AppointmentData){ + setAppointment(AppointmentData); + } + } + fetchAppointments(); + },[]) + const renderItems = (appointment: any, index:any) => { return ( <> router.push('chat-history/singleCall')} + key={index} + name={appointment.doctor.name} + type={appointment.package} + date={appointment.appointment_date} + time={appointment.appointment_time.slice(0,5)} + image={appointment.doctor.image} + onPress={()=>router.push({pathname:'chat-history/singleCall', params:{appointmentId:appointment.id}})} /> ) } - const image = require('@/assets/doctors/doc1.png'); return ( <> - + {appointment.map((appointmentItem,index) => renderItems(appointmentItem,index))} ) } \ No newline at end of file diff --git a/components/cards/DoctorVideo.tsx b/components/cards/DoctorVideo.tsx index 086bd55e..409257ef 100644 --- a/components/cards/DoctorVideo.tsx +++ b/components/cards/DoctorVideo.tsx @@ -23,7 +23,7 @@ export default function DoctorCard(props: DocCardProps) { - + {props.doctorName} diff --git a/components/chats/voiceCard.tsx b/components/chats/voiceCard.tsx index ad2fc2af..7f25a80f 100644 --- a/components/chats/voiceCard.tsx +++ b/components/chats/voiceCard.tsx @@ -1,5 +1,4 @@ import { leftArrowBlue, leftFilledArrowIcon } from "@/assets/icons/arrow"; -import { heart, heartFilledIcon } from "@/assets/icons/heart"; import { Image, ImageSourcePropType, @@ -16,7 +15,7 @@ export type CallsType = { time: string; date: string; icon?: any; - image: ImageSourcePropType; + image: any; onPress?: () => void; }; @@ -25,7 +24,7 @@ export default function CallsCard(props: CallsType) { - +