solve mail backend 12

This commit is contained in:
alma 2025-04-17 14:32:49 +02:00
parent a2ef35aa29
commit 9f8c28238b
6 changed files with 1401 additions and 83 deletions

File diff suppressed because it is too large Load Diff

14
app/types/mail.ts Normal file
View File

@ -0,0 +1,14 @@
export interface Mail {
id: string;
from: string;
subject: string;
body: string;
date: string;
read: boolean;
starred: boolean;
attachments?: {
filename: string;
size: number;
type: string;
}[];
}

View File

@ -1,11 +1,13 @@
import { Mail } from '@/hooks/use-mail'; import { Mail } from "@/types/mail";
import { Star, StarOff, Paperclip } from "lucide-react";
import { format } from "date-fns";
interface MailListProps { interface MailListProps {
mails: Mail[]; mails: Mail[];
onMailClick?: (mail: Mail) => void; onMailClick: (mail: Mail) => void;
} }
export const MailList = ({ mails = [], onMailClick }: MailListProps) => { export function MailList({ mails, onMailClick }: MailListProps) {
if (!mails || mails.length === 0) { if (!mails || mails.length === 0) {
return ( return (
<div className="flex items-center justify-center h-64"> <div className="flex items-center justify-center h-64">
@ -15,30 +17,43 @@ export const MailList = ({ mails = [], onMailClick }: MailListProps) => {
} }
return ( return (
<div className="flex flex-col space-y-2"> <div className="flex-1 overflow-auto">
{mails.map((mail) => ( {mails.map((mail) => (
<div <div
key={mail.id} key={mail.id}
className={`p-4 border rounded-lg cursor-pointer hover:bg-gray-50 ${ className={`p-4 border-b cursor-pointer hover:bg-muted ${
!mail.read ? 'font-semibold' : '' !mail.read ? "bg-muted/50" : ""
}`} }`}
onClick={() => onMailClick?.(mail)} onClick={() => onMailClick(mail)}
> >
<div className="flex justify-between items-start"> <div className="flex items-center justify-between">
<div className="flex-1">
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
<span className="text-sm text-gray-600">{mail.from}</span> {mail.starred ? (
{mail.starred && ( <Star className="h-4 w-4 text-yellow-400" />
<span className="text-yellow-400"></span> ) : (
<StarOff className="h-4 w-4 text-muted-foreground" />
)} )}
<span className="font-medium">{mail.from}</span>
</div> </div>
<h3 className="text-lg font-medium">{mail.subject}</h3> <span className="text-sm text-muted-foreground">
<p className="text-sm text-gray-500 truncate">{mail.body}</p> {format(new Date(mail.date), "MMM d, yyyy")}
</span>
</div> </div>
<span className="text-sm text-gray-400">{new Date(mail.date).toLocaleDateString()}</span> <div className="mt-2">
<h3 className="font-medium">{mail.subject}</h3>
<p className="text-sm text-muted-foreground line-clamp-2">
{mail.body}
</p>
</div> </div>
{mail.attachments && mail.attachments.length > 0 && (
<div className="mt-2 flex items-center text-sm text-muted-foreground">
<Paperclip className="h-3 w-3 mr-1" />
{mail.attachments.length} attachment
{mail.attachments.length > 1 ? "s" : ""}
</div>
)}
</div> </div>
))} ))}
</div> </div>
); );
}; }

View File

@ -1,6 +1,6 @@
import { Search } from "lucide-react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { RefreshCw, Plus, Search } from "lucide-react";
interface MailToolbarProps { interface MailToolbarProps {
onRefresh: () => void; onRefresh: () => void;
@ -11,15 +11,16 @@ interface MailToolbarProps {
export function MailToolbar({ onRefresh, onCompose, onSearch }: MailToolbarProps) { export function MailToolbar({ onRefresh, onCompose, onSearch }: MailToolbarProps) {
return ( return (
<div className="flex items-center justify-between p-4 border-b"> <div className="flex items-center justify-between p-4 border-b">
<div className="flex items-center space-x-4"> <div className="flex items-center space-x-2">
<Button variant="outline" onClick={onRefresh}> <Button variant="ghost" size="icon" onClick={onRefresh}>
Refresh <RefreshCw className="h-4 w-4" />
</Button> </Button>
<Button variant="outline" onClick={onCompose}> <Button onClick={onCompose}>
<Plus className="h-4 w-4 mr-2" />
Compose Compose
</Button> </Button>
</div> </div>
<div className="flex-1 max-w-md"> <div className="flex-1 max-w-md mx-4">
<div className="relative"> <div className="relative">
<Search className="absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" /> <Search className="absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" />
<Input <Input

View File

@ -1,19 +1,7 @@
import { useState, useCallback } from 'react'; import { useState, useCallback } from 'react';
import type { Mail } from '@/types/mail';
export interface Mail { export type { Mail };
id: string;
from: string;
to: string;
subject: string;
body: string;
date: string;
read: boolean;
starred: boolean;
folder: string;
cc?: string[];
bcc?: string[];
flags?: string[];
}
export const useMail = () => { export const useMail = () => {
const [mails, setMails] = useState<Mail[]>([]); const [mails, setMails] = useState<Mail[]>([]);

14
types/mail.ts Normal file
View File

@ -0,0 +1,14 @@
export interface Mail {
id: string;
from: string;
to: string;
subject: string;
body: string;
date: string;
read: boolean;
starred: boolean;
folder: string;
cc?: string[];
bcc?: string[];
flags?: string[];
}