gbclient/src/mail/components/mail-display.tsx

343 lines
9.1 KiB
TypeScript
Raw Normal View History

import React, { useState } from 'react';
import { View, Text, TouchableOpacity, TextInput, StyleSheet, ScrollView, Modal } from 'react-native';
import Icon from 'react-native-vector-icons/Feather';
import { Switch } from 'react-native';
// Simple Avatar component
const Avatar = ({ name }: { name: string }) => (
<View style={styles.avatar}>
<Text style={styles.avatarText}>{name[0]}</Text>
</View>
);
const formatDistanceToNow = (date: Date) => {
const now = new Date();
const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);
if (diffInSeconds < 60) return 'just now';
if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)} minutes ago`;
if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)} hours ago`;
if (diffInSeconds < 2592000) return `${Math.floor(diffInSeconds / 86400)} days ago`;
if (diffInSeconds < 31536000) return `${Math.floor(diffInSeconds / 2592000)} months ago`;
return `${Math.floor(diffInSeconds / 31536000)} years ago`;
};
// Simple Separator component
const Separator = () => <View style={styles.separator} />;
// Simple Tooltip component (placeholder)
const Tooltip = ({ content, children }: { content: string; children: React.ReactNode }) => (
<View>
{children}
{/* Implement tooltip logic here */}
</View>
);
// Simple Calendar component (placeholder)
const Calendar = () => (
<View>
<Text>Calendar Placeholder</Text>
</View>
);
// Helper function to format date
const formatDate = (date: Date) => {
return date.toLocaleString('en-US', {
weekday: 'short',
month: 'short',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
hour12: true,
});
};
// Helper function to add hours to a date
const addHours = (date: Date, hours: number) => {
const newDate = new Date(date);
newDate.setHours(date.getHours() + hours);
return newDate;
};
// Helper function to add days to a date
const addDays = (date: Date, days: number) => {
const newDate = new Date(date);
newDate.setDate(date.getDate() + days);
return newDate;
};
// Helper function to get next Saturday
const nextSaturday = (date: Date) => {
const newDate = new Date(date);
newDate.setDate(date.getDate() + ((6 - date.getDay() + 7) % 7));
return newDate;
};
// Define Mail type
interface Mail {
name: string;
subject: string;
email: string;
date: string;
text: string;
}
interface MailDisplayProps {
mail: Mail | null;
}
export function MailDisplay({ mail }: MailDisplayProps) {
const [isPopoverVisible, setIsPopoverVisible] = useState(false);
const today = new Date();
const renderToolbarButton = (icon: string, label: string, onPress: () => void) => (
<Tooltip content={label}>
<TouchableOpacity style={styles.toolbarButton} onPress={onPress} disabled={!mail}>
<Icon name={icon} size={16} color="#000" />
</TouchableOpacity>
</Tooltip>
);
return (
<View style={styles.container}>
<View style={styles.toolbar}>
<View style={styles.toolbarGroup}>
{renderToolbarButton('archive', 'Archive', () => {})}
{renderToolbarButton('x-square', 'Move to junk', () => {})}
{renderToolbarButton('trash-2', 'Move to trash', () => {})}
<Separator />
<TouchableOpacity
style={styles.toolbarButton}
onPress={() => setIsPopoverVisible(true)}
disabled={!mail}
>
<Icon name="clock" size={16} color="#000" />
</TouchableOpacity>
</View>
<View style={styles.toolbarGroup}>
{renderToolbarButton('reply', 'Reply', () => {})}
{renderToolbarButton('reply-all', 'Reply all', () => {})}
{renderToolbarButton('corner-up-right', 'Forward', () => {})}
</View>
<Separator />
<TouchableOpacity style={styles.toolbarButton} disabled={!mail}>
<Icon name="more-vertical" size={16} color="#000" />
</TouchableOpacity>
</View>
<Separator />
{mail ? (
<ScrollView style={styles.mailContent}>
<View style={styles.mailHeader}>
<View style={styles.mailSender}>
<Avatar name={mail.name} />
<View style={styles.mailSenderInfo}>
<Text style={styles.mailSenderName}>{mail.name}</Text>
<Text style={styles.mailSubject}>{mail.subject}</Text>
<Text style={styles.mailReplyTo}>
<Text style={styles.mailReplyToLabel}>Reply-To:</Text> {mail.email}
</Text>
</View>
</View>
{mail.date && (
<Text style={styles.mailDate}>
{formatDate(new Date(mail.date))}
</Text>
)}
</View>
<Separator />
<Text style={styles.mailBody}>{mail.text}</Text>
<Separator />
<View style={styles.replyForm}>
<TextInput
style={styles.replyInput}
multiline
placeholder={`Reply ${mail.name}...`}
/>
<View style={styles.replyFormFooter}>
<View style={styles.muteThreadContainer}>
<Switch />
<Text style={styles.muteThreadLabel}>Mute this thread</Text>
</View>
<TouchableOpacity style={styles.sendButton}>
<Text style={styles.sendButtonText}>Send</Text>
</TouchableOpacity>
</View>
</View>
</ScrollView>
) : (
<View style={styles.noMailSelected}>
<Text>No message selected</Text>
</View>
)}
<Modal
visible={isPopoverVisible}
transparent
animationType="slide"
onRequestClose={() => setIsPopoverVisible(false)}
>
<View style={styles.modalOverlay}>
<View style={styles.modalContent}>
<Text style={styles.modalTitle}>Snooze until</Text>
<TouchableOpacity style={styles.snoozeOption}>
<Text>Later today</Text>
<Text style={styles.snoozeTime}>
{formatDate(addHours(today, 4))}
</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.snoozeOption}>
<Text>Tomorrow</Text>
<Text style={styles.snoozeTime}>
{formatDate(addDays(today, 1))}
</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.snoozeOption}>
<Text>This weekend</Text>
<Text style={styles.snoozeTime}>
{formatDate(nextSaturday(today))}
</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.snoozeOption}>
<Text>Next week</Text>
<Text style={styles.snoozeTime}>
{formatDate(addDays(today, 7))}
</Text>
</TouchableOpacity>
<Calendar />
</View>
</View>
</Modal>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
toolbar: {
flexDirection: 'row',
justifyContent: 'space-between',
padding: 8,
},
toolbarGroup: {
flexDirection: 'row',
},
toolbarButton: {
padding: 8,
},
mailContent: {
flex: 1,
},
mailHeader: {
flexDirection: 'row',
justifyContent: 'space-between',
padding: 16,
},
mailSender: {
flexDirection: 'row',
},
mailSenderInfo: {
marginLeft: 16,
},
mailSenderName: {
fontWeight: 'bold',
},
mailSubject: {
fontSize: 12,
},
mailReplyTo: {
fontSize: 12,
},
mailReplyToLabel: {
fontWeight: 'bold',
},
mailDate: {
fontSize: 12,
color: '#666',
},
mailBody: {
padding: 16,
fontSize: 14,
},
replyForm: {
padding: 16,
},
replyInput: {
borderWidth: 1,
borderColor: '#ccc',
borderRadius: 4,
padding: 8,
minHeight: 100,
},
replyFormFooter: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginTop: 8,
},
muteThreadContainer: {
flexDirection: 'row',
alignItems: 'center',
},
muteThreadLabel: {
marginLeft: 8,
fontSize: 12,
},
sendButton: {
backgroundColor: '#007AFF',
padding: 8,
borderRadius: 4,
},
sendButtonText: {
color: '#fff',
},
noMailSelected: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
modalOverlay: {
flex: 1,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
justifyContent: 'center',
alignItems: 'center',
},
modalContent: {
backgroundColor: '#fff',
padding: 16,
borderRadius: 8,
width: '80%',
},
modalTitle: {
fontSize: 18,
fontWeight: 'bold',
marginBottom: 16,
},
snoozeOption: {
flexDirection: 'row',
justifyContent: 'space-between',
paddingVertical: 8,
},
snoozeTime: {
color: '#666',
},
avatar: {
width: 40,
height: 40,
borderRadius: 20,
backgroundColor: '#ccc',
justifyContent: 'center',
alignItems: 'center',
},
avatarText: {
fontSize: 18,
color: '#fff',
},
separator: {
height: 1,
backgroundColor: '#e0e0e0',
marginVertical: 8,
},
});