Skip to content

Commit

Permalink
feat:notifications implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Latiah committed Jul 22, 2024
1 parent c09728f commit 82ccdd8
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 71 deletions.
204 changes: 140 additions & 64 deletions app/notifications/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,66 +2,102 @@ import { Icon } from "@/components/Icon";
import { Text } from "@/components/ThemedText";
import { Picker } from "@react-native-picker/picker";
import { router } from "expo-router";
import { useRef, useState } from "react";
import { useEffect, useRef, useState } from "react";
import {
ScrollView,
View
} from "react-native";
import NotificationComponent, {
Notification,
} from "../../components/notifications/notification";

import NotificationComponent from "../../components/notifications/notification";
import { supabase } from "../supabase";
import { UIActivityIndicator } from "react-native-indicators";
export default function NotificationsScreen() {
const [data, setData] = useState<any[]>([]);
const [cancelled, setCancelled] = useState<any[]>([]);
const [loading, setLoading] = useState(true);
const pickerRef = useRef<Picker<String>>(null);
const [notifications, setNotifications] = useState<Notification[]>([
{
title: "Appointment Cancelled!",
description:
"You have successfully cancelled your appointment with Dr. Alan Watson on December 24, 2024, 13:00 p.m. 80% of the funds will be returned to your account.",
date: "Today",
time: "15:36 PM",
type: "appointment",
state: "error",
new: true,
},
{
title: "Schedule Changed",
description:
"You have successfully changed your schedule with Dr. Alan Watson on December 24, 2024, 13:00 p.m. Don't forget to activate your reminder.",
date: "Yesterday",
time: "09:23 AM",
type: "schedule",
state: "success",
new: true,
},
{
title: "Appointment Success!",
description:
"You have successfully booked an appointment with Dr. Alan Watson on December 24, 2024, 13:00 p.m. Don't forget to activate your reminder.",
date: "19 Dec. 2022",
time: "18:35 PM",
type: "appointment",
state: "info",
},
{
title: "New Service Available!",
description:
"You can make multiple doctoral appointments at once. You can also cancel your appointment.",
date: "14 Dec. 2022",
time: "10:52 AM",
type: "service",
state: "warning",
},
{
title: "Credic Card Connected!",
description:
"Your credit card has been successfully linke with Medica. Enjoy our service.",
date: "12 Dec. 2022",
time: "14:36 PM",
type: "card",
state: "info",
},
]);

useEffect(() => {
const fetchAppointment = async () => {
try {
const { data: userData, error: userError } = await supabase.auth.getUser();
if (userError) throw userError;
const userId = userData?.user?.id;

const { data: appointments, error: appError } = await supabase
.from("appointment")
.select("*, doctor(name)")
.eq("patient_id", userId)
.eq("notification", "TRUE");
if (appError) throw appError;
setData(appointments);


const { data: cancelledAppointments, error: cancelError } = await supabase
.from("cancel-appointment")
.select("*")
.eq("patient_id", userId)
.eq("notification", "TRUE");
if (cancelError) throw cancelError;
setCancelled(cancelledAppointments);
} catch (error) {
console.error('Error fetching notifications:', error);
}
setLoading(false);
};

fetchAppointment();
}, []);

const formatDate = (datetime: any) => {
const date = new Date(datetime);
return date.toLocaleDateString();
};

const formatTime = (datetime: any) => {
const date = new Date(datetime);
return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
};

const clearNotification = async () => {
try {
const { data: userData, error } = await supabase.auth.getUser();
const userId = userData?.user?.id;
await supabase.from("appointment").update({ notification: false }).eq("patient_id", userId).eq("notification", "TRUE")
await supabase.from("cancel-appointment").update({ notification: false }).eq("patient_id", userId).eq("notification", "TRUE")
setData([])
setCancelled([])
} catch {
console.log("Error clearing notifications");
}
}

const deleteNotification = async (id: String, type: 'appointment' | 'cancel-appointment') => {
try {
const { data: userData, error: userError } = await supabase.auth.getUser();
if (userError) throw userError;
const userId = userData?.user?.id;

if (type === 'appointment') {
await supabase
.from('appointment')
.update({ notification: false })
.eq('patient_id', userId)
.eq('id', id);
setData(prev => prev.filter(notification => notification.id !== id));
} else {
await supabase
.from('cancel-appointment')
.update({ notification: false })
.eq('patient_id', userId)
.eq('id', id);
setCancelled(prev => prev.filter(notification => notification.id !== id));
}
} catch (error) {
console.error('Error deleting notification:', error);
}
};



return (
<>
Expand All @@ -74,26 +110,66 @@ export default function NotificationsScreen() {
size="lg"
onPress={() => {
pickerRef.current?.focus();

}}
/>
<View className="absolute top-10 right-10 pr-4 left-0 bottom-0 opacity-0">
<Picker ref={pickerRef} mode="dropdown" onValueChange={() => {}}>
<Picker ref={pickerRef} mode="dropdown" onValueChange={(value) => {
if (value === "clear")
clearNotification()
}}>
<Picker.Item label="Clear Notifications" value="clear" style={{
fontFamily: "UrbanistRegular",
}} />
</Picker>
</View>
</View>
</View>
<ScrollView
className="flex-1"
>
{notifications.map((notification, index) => {
return (
<NotificationComponent key={index} notification={notification} />
);
})}
</ScrollView>
{loading ? (
<UIActivityIndicator color={"#246BFD"} size={32} />
) : (
<ScrollView className="flex-1">
{data.length === 0 && cancelled.length === 0 ? (
<View className="flex-1 items-center justify-center mt-8">
<Text className="text-xl font-UrbanistRegular">No notifications found</Text>
</View>) : (
<>
{data.map((notification, index) => (
<NotificationComponent
key={index}
notification={{
id: notification.id,
title: "Appointment Success!",
description: `You have successfully booked an appointment with ${notification.doctor.name} on ${notification.appointment_date} at ${notification.appointment_time.slice(0, 5)}. Don't forget to activate your reminder.`,
date: formatDate(notification.created_at),
time: formatTime(notification.created_at),
type: "appointment",
state: "info",
delete: true,
}}
onDeletePress={(id) => deleteNotification(id, "appointment")}
/>
))}
{cancelled.map((notification, index) => (
<NotificationComponent
key={index}
notification={{
id: notification.id,
title: "Appointment Cancelled!",
description: `You have successfully cancelled your appointment with ${notification.doctorname} on ${notification.appointment_date} at ${notification.appointment_time.slice(0, 5)}.`,
date: formatDate(notification.created_at),
time: formatTime(notification.created_at),
type: "appointment",
state: "error",
delete: true,
}}
onDeletePress={(id) => deleteNotification(id, "cancel-appointment")}
/>
))}
</>
)}
</ScrollView>
)}
</>
);
}
16 changes: 9 additions & 7 deletions components/notifications/notification.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
import { Text } from "@/components/ThemedText";
import { Image, ImageSourcePropType, View } from "react-native";
import { Image, ImageSourcePropType, TouchableOpacity, View } from "react-native";

export type NotificationType = "appointment" | "schedule" | "service" | "card";
export type NotificationState = "error" | "success" | "warning" | "info";

export type Notification = {
id: String;
title: String;
description: String;
date: String;
time: String;
type: NotificationType;
state: NotificationState;
new?: boolean;
delete?:boolean;
};

type NotificationComponentProps = {
notification: Notification;
onDeletePress: (id: String) => void;
};

export default function NotificationComponent({
notification,
notification, onDeletePress
}: NotificationComponentProps) {
return (
<View className="py-3 px-4 my-3 gap-3">
Expand All @@ -33,10 +35,10 @@ export default function NotificationComponent({
{notification.date} | {notification.time}
</Text>
</View>
{notification.new && (
<View className="bg-primary-500 rounded-md px-[10px] py-[6px]">
<Text className="text-white text-xs">New</Text>
</View>
{notification.delete && (
<TouchableOpacity className="bg-red-400 rounded-md px-[10px] py-[6px]" onPress={()=> onDeletePress(notification.id)}>
<Text className="text-white text-xs">Clear</Text>
</TouchableOpacity>
)}
</View>
<Text className="text-gray-500 text-base opacity-90">
Expand Down

0 comments on commit 82ccdd8

Please sign in to comment.