pogdark-app/app/StatusPage.tsx

146 lines
6.6 KiB
TypeScript

import React, { useEffect, useState } from "react";
import useWebSocket from "react-use-websocket";
import axios from "axios";
import { StyleSheet, View } from "react-native";
import { Avatar, List, Button, useTheme, } from "react-native-paper";
interface Message {
Id: string;
Name: string;
Image: string;
Status: string;
Timestamp: string;
}
const styles = StyleSheet.create({
container: { flex: 1, alignItems: "stretch" },
listContainer: { flex: 1, width: "100%" },
listSubheader: {
fontSize: 18, // Larger text
textAlign: "center", // Center the text
fontWeight: "bold", // Make it more distinct
marginBottom: 10, // Add spacing below
},
listWrapper: { flex: 1, padding: 5 },
listRow: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "flex-start", // Aligns subheaders properly
paddingHorizontal: 10, // Adds some spacing
},
listColumn: { flex: 1, paddingHorizontal: 5 },
buttonContainer: {
flexDirection: "row",
justifyContent: "space-between",
alignSelf: "stretch",
paddingHorizontal: 10,
paddingBottom: 20,
},
actionButton: {
flex: 1,
marginHorizontal: 5,
},
card: {
marginVertical: 5,
elevation: 4, // Android shadow
shadowColor: "#000", // iOS shadow
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.2,
shadowRadius: 4,
borderRadius: 10
},
});
const StatusPage = ({ id, name, image, isProfileActive }: { id: string; name: string; image: string; isProfileActive: boolean }) => {
const theme = useTheme();
const [messages, setMessages] = useState<Message[]>([]);
const { lastMessage } = useWebSocket("ws://localhost:8080/ws", {
shouldReconnect: () => true,
});
useEffect(() => {
if (lastMessage?.data) {
try {
const newMessage: Message = JSON.parse(lastMessage.data);
setMessages((prev) => {
if (newMessage.Status === "removed") {
return prev.filter((msg) => msg.Id !== newMessage.Id);
}
return prev.filter((msg) => msg.Id !== newMessage.Id).concat(newMessage);
});
} catch (error) {
console.error("Error parsing WebSocket message:", error);
}
}
}, [lastMessage]);
const sendStatus = async (status: string) => {
try {
const message: Message = { Id: id, Name: name, Image: image, Status: status, Timestamp: new Date().toISOString() };
await axios.post("http://localhost:8080/set", message);
} catch (error) {
console.error("Error sending status:", error);
}
};
return (
<View style={[styles.container, { backgroundColor: theme.colors.background }, isProfileActive && { display: 'none' }]}>
<View style={[styles.listContainer, { backgroundColor: theme.colors.surface }]}>
<View style={styles.listRow}>
<View style={styles.listColumn}>
<List.Section>
<List.Subheader style={[styles.listSubheader, { color: theme.colors.onSurface }]}>On the Way</List.Subheader>
{messages.filter(msg => msg.Status === "On the Way")
.sort((a, b) => new Date(a.Timestamp).getTime() - new Date(b.Timestamp).getTime())
.map(item => (
<View key={item.Id} style={[styles.card, { backgroundColor: theme.colors.primaryContainer }]}>
<List.Item
key={item.Id}
title={item.Name}
titleStyle={{ color: theme.colors.onSurface }}
description={new Date(item.Timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', hour12: true })}
descriptionStyle={{ color: theme.colors.onSurface }}
left={(props) => <Avatar.Image {...props} size={40} source={{ uri: `data:image/png;base64,${item.Image}` }} />}
/>
</View>
))}
</List.Section>
</View>
<View style={styles.listColumn}>
<List.Section>
<List.Subheader style={[styles.listSubheader, { color: theme.colors.onSurface }]}>Arrived</List.Subheader>
{messages.filter(msg => msg.Status === "Arrived")
.sort((a, b) => new Date(a.Timestamp).getTime() - new Date(b.Timestamp).getTime())
.map(item => (
<View key={item.Id} style={[styles.card, { backgroundColor: theme.colors.primaryContainer }]}>
<List.Item
key={item.Id}
title={item.Name}
titleStyle={{ color: theme.colors.onSurface }}
description={new Date(item.Timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', hour12: true })}
descriptionStyle={{ color: theme.colors.onSurface }}
left={(props) => <Avatar.Image {...props} size={40} source={{ uri: `data:image/png;base64,${item.Image}` }} />}
/>
</View>
))}
</List.Section>
</View>
</View>
</View>
<View style={styles.buttonContainer}>
<Button mode="contained" onPress={() => sendStatus("On the Way")}
style={[styles.actionButton, { backgroundColor: theme.colors.primary }]}
labelStyle={{ color: theme.colors.onPrimary }}>On the Way</Button>
<Button mode="contained" onPress={() => sendStatus("Arrived")}
style={[styles.actionButton, { backgroundColor: theme.colors.primary }]}
labelStyle={{ color: theme.colors.onPrimary }} >Arrived</Button>
</View>
</View>
);
};
export default StatusPage;