Skip to content

Commit

Permalink
fix:(changing sending message icon when you're typing)
Browse files Browse the repository at this point in the history
  • Loading branch information
Emmyfrank committed Jul 7, 2024
1 parent f0b39e1 commit 9d094ba
Show file tree
Hide file tree
Showing 8 changed files with 246 additions and 176 deletions.
3 changes: 2 additions & 1 deletion app/Appointments/details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ const VideoCallAppointment = ({ route }: any) => {
const { typecall } = useLocalSearchParams<{
typecall: "Voice call" | "Messaging" | "Video call";
}>();

const appointment = useSelector((state: RootState) => state.appointment.selectedAppointment);
console.log("selected appointment ... here ...", appointment)

return (
<View className={`flex-1 pt-[${insets.top}px] bg-white`}>
<View className="px-6 mt-8">
Expand Down
318 changes: 173 additions & 145 deletions app/messagingAppointment/messaging.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import Recording from "@/components/recording";
import moment from "moment";
import { router, useGlobalSearchParams } from "expo-router";
import {
Image,
KeyboardAvoidingView,
Modal,
ScrollView,
Text,
TouchableOpacity,
TouchableWithoutFeedback,
View,
Image,
KeyboardAvoidingView,
Modal,
ScrollView,
Text,
TouchableOpacity,
TouchableWithoutFeedback,
View,
} from "react-native";

import { useEffect, useState } from "react";
Expand All @@ -24,150 +24,178 @@ import { useDispatch, useSelector } from "react-redux";
import { RootState } from "@/redux/store/store";
import { supabase } from "../supabase";
import { getMessages } from "@/redux/reducers/appointment";
import { SendMessageButton } from "@/components/SendMessageButton";
export default function messagingAppointment() {
const [visible, setVisible] = useState(false);
const [isSession, setIsSession] = useState(true);
const [textMessage, setTextMessage] = useState("")
const [userId, setUserId] = useState("")
const appointment = useSelector((state: RootState) => state.appointment.selectedAppointment);
const messages = useSelector((state: RootState) => state.appointment.messages);
const dispatch = useDispatch();
const toggleModal = () => {
setVisible(!visible);
};
const [visible, setVisible] = useState(false);
const [isSession, setIsSession] = useState(true);
const [textMessage, setTextMessage] = useState("");
const [userId, setUserId] = useState("");
const appointment = useSelector(
(state: RootState) => state.appointment.selectedAppointment
);
const messages = useSelector(
(state: RootState) => state.appointment.messages
);
const dispatch = useDispatch();
const toggleModal = () => {
setVisible(!visible);
};

const fetchMessages=async()=>{
try{
const { data: userData, error: userError } = await supabase.auth.getUser();
if (userError) throw userError;
setUserId(userData?.user?.id);
const{data, error}=await supabase
.from("messages")
.select(`
const fetchMessages = async () => {
try {
const { data: userData, error: userError } =
await supabase.auth.getUser();
if (userError) throw userError;
setUserId(userData?.user?.id);
const { data, error } = await supabase
.from("messages")
.select(
`
*
`)
.eq("appointment_id", appointment.id);

if(error){
console.log("Error occured while fetching appointments", error)
}else{
console.log("messages",data)
dispatch(getMessages(data))
}}
catch(error){
console.log(error);
}
}
`
)
.eq("appointment_id", appointment.id);

if (error) {
console.log("Error occured while fetching appointments", error);
} else {
console.log("messages", data);
dispatch(getMessages(data));
}
} catch (error) {
console.log(error);
}
};

const channels = supabase.channel('custom-all-channel')
.on(
'postgres_changes',
{ event: '*', schema: 'public', table: 'messages', filter: `appointment_id=eq.${appointment.id}`},
(payload) => {
console.log('Change received!', payload)
dispatch(getMessages([...messages,payload.new]))
}
)
.subscribe()


useEffect(() => {
fetchMessages()
}, [dispatch]);
const channels = supabase
.channel("custom-all-channel")
.on(
"postgres_changes",
{
event: "*",
schema: "public",
table: "messages",
filter: `appointment_id=eq.${appointment.id}`,
},
(payload) => {
console.log("Change received!", payload);
dispatch(getMessages([...messages, payload.new]));
}
)
.subscribe();

const handleSendMessage =async ()=>{
useEffect(() => {
fetchMessages();
}, [dispatch]);

const { data, error } = await supabase
.from('messages')
.insert([
{ message:textMessage, sender_id: userId,appointment_id:appointment.id,type:"message" },
])
.select()
async function handleSendMessage() {
const { data, error } = await supabase
.from("messages")
.insert([
{
message: textMessage,
sender_id: userId,
appointment_id: appointment.id,
type: "message",
},
])
.select();

if(data){
console.log('data inserted well')
}else{
console.log('data note inserted well',error)
}
}



return (
<View className="flex-1 bg-white py-10 px-6">
<NavigationHeader title={appointment.doctor.name} onBack={router.back}>
<TouchableOpacity>
<Image
source={require("@/assets/icons/search.png")}
className="w-6 h-6 mr-3"
/>
</TouchableOpacity>
<TouchableOpacity onPress={toggleModal}>
<SvgXml xml={Menu} />
</TouchableOpacity>
<Modal
visible={visible}
animationType="fade"
transparent={true}
onRequestClose={toggleModal}>
<TouchableWithoutFeedback onPress={() => setVisible(false)}>
<View className={` absolute w-[100%] right-0 z-[0] top-[5px]`}>
<View className="w-[100%]">
<View className="w-[37%] relative top-[50px] left-[59%] p-4 right-0 bg-white rounded-xl">
<TouchableOpacity className="flex-row gap-2 py-2">
<SvgXml xml={deleteBtn} />
<Text className="font-UrbanistSemiBold">Clear chat</Text>
</TouchableOpacity>
<View className="w-[85%] ml-3 pt-2 border-b-[1px] border-grey opacity-40" />
<TouchableOpacity className="flex-row gap-2 pb-2 pt-4 ">
<SvgXml xml={download} />
<Text className="font-UrbanistSemiBold">Export chat</Text>
</TouchableOpacity>
</View>
</View>
</View>
</TouchableWithoutFeedback>
</Modal>
</NavigationHeader>
<KeyboardAvoidingView
behavior="padding"
className="flex-1"
keyboardVerticalOffset={20}>
<ScrollView
showsVerticalScrollIndicator={false}
className="flex-1 mb-4">
{
messages&&messages.map((message:any, index:any) => (
<Chat
key={index}
direction={message.sender_id===userId?"end":"start"}
message={message.message}
time={moment(`${message.created_at}`).calendar()}
color={message.sender_id===userId?"lightblue":"lightgrey"}
/>
))
}
if (data) {
console.log("data inserted well");
if (textMessage.trim().length > 0) {
console.log("Message sent:", textMessage);
setTextMessage(""); // Clear the input field
}
} else {
console.log("data note inserted well", error);
}
}

</ScrollView>
{isSession && (
<View className="flex-row justify-center items-center gap-2">
<View className="flex-1">
<ChatInput onChangeText={(text)=>setTextMessage(text)} onKeyPress={()=>handleSendMessage()} autoFocus={true} />
</View>
<Recording />
</View>
)}
{!isSession && (
<View className="flex-row justify-center items-center my-3">
<View className="bg-[#75757512] justify-center items-center rounded-lg px-6 py-1.5">
<Text className="text-sm text-[#757575] font-UrbanistSemiBold">
Session End
</Text>
</View>
</View>
)}
</KeyboardAvoidingView>
</View>
);
return (
<View className="flex-1 bg-white py-10 px-6">
<NavigationHeader title={appointment.doctor.name} onBack={router.back}>
<TouchableOpacity>
<Image
source={require("@/assets/icons/search.png")}
className="w-6 h-6 mr-3"
/>
</TouchableOpacity>
<TouchableOpacity onPress={toggleModal}>
<SvgXml xml={Menu} />
</TouchableOpacity>
<Modal
visible={visible}
animationType="fade"
transparent={true}
onRequestClose={toggleModal}
>
<TouchableWithoutFeedback onPress={() => setVisible(false)}>
<View className={` absolute w-[100%] right-0 z-[0] top-[5px]`}>
<View className="w-[100%]">
<View className="w-[37%] relative top-[50px] left-[59%] p-4 right-0 bg-white rounded-xl">
<TouchableOpacity className="flex-row gap-2 py-2">
<SvgXml xml={deleteBtn} />
<Text className="font-UrbanistSemiBold">Clear chat</Text>
</TouchableOpacity>
<View className="w-[85%] ml-3 pt-2 border-b-[1px] border-grey opacity-40" />
<TouchableOpacity className="flex-row gap-2 pb-2 pt-4 ">
<SvgXml xml={download} />
<Text className="font-UrbanistSemiBold">Export chat</Text>
</TouchableOpacity>
</View>
</View>
</View>
</TouchableWithoutFeedback>
</Modal>
</NavigationHeader>
<KeyboardAvoidingView
behavior="padding"
className="flex-1"
keyboardVerticalOffset={20}
>
<ScrollView
showsVerticalScrollIndicator={false}
className="flex-1 mb-4"
>
{messages &&
messages.map((message: any, index: any) => (
<Chat
key={index}
direction={message.sender_id === userId ? "end" : "start"}
message={message.message}
time={moment(`${message.created_at}`).calendar()}
color={message.sender_id === userId ? "lightblue" : "lightgrey"}
/>
))}
</ScrollView>
{isSession && (
<View className="flex-row justify-center items-center gap-2">
<View className="flex-1">
<ChatInput
onChangeText={(text) => setTextMessage(text)}
onKeyPress={() => handleSendMessage()}
autoFocus={true}
/>
</View>
{/* Replace recording icon onChangeText to send Icon */}
{textMessage.trim().length === 0 ? (
<Recording />
) : (
<SendMessageButton onPress={handleSendMessage} />
)}
</View>
)}
{!isSession && (
<View className="flex-row justify-center items-center my-3">
<View className="bg-[#75757512] justify-center items-center rounded-lg px-6 py-1.5">
<Text className="text-sm text-[#757575] font-UrbanistSemiBold">
Session End
</Text>
</View>
</View>
)}
</KeyboardAvoidingView>
</View>
);
}
1 change: 1 addition & 0 deletions app/supabase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ export const supabase = createClient(supabaseUrl, supabaseAnonKey, {
detectSessionInUrl: false,
},
});

6 changes: 6 additions & 0 deletions assets/icons/send.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const sendIcon = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Send">
<path id="Send_2" d="M15.8325 8.17463L10.109 13.9592L3.59944 9.88767C2.66675 9.30414 2.86077 7.88744 3.91572 7.57893L19.3712 3.05277C20.3373 2.76963 21.2326 3.67283 20.9456 4.642L16.3731 20.0868C16.0598 21.1432 14.6512 21.332 14.0732 20.3953L10.106 13.9602" stroke="#212121" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</svg>
`;
23 changes: 23 additions & 0 deletions components/SendMessageButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { TouchableOpacity, View } from "react-native";
import { SvgXml } from "react-native-svg";
import { supabase } from "@/app/supabase";
import { chatIcon } from "@/assets/icons/chat";
import { sendIcon } from "@/assets/icons/send";

interface Props {
onPress: () => void;
}

export const SendMessageButton: React.FC<Props> = ({ onPress }) => {
return (
<View className="relative ml-3 bottom-1">
<TouchableOpacity
activeOpacity={0.8}
className="bg-blue-500 p-4 rounded-full"
onPress={onPress}
>
<SvgXml className="text-white" xml={sendIcon} width={24} height={24} />
</TouchableOpacity>
</View>
);
};
Loading

0 comments on commit 9d094ba

Please sign in to comment.