feat(email): consolidate correspondence routes
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useNavigate, useSearchParams } from "react-router-dom";
|
||||
import {
|
||||
Box,
|
||||
Chip,
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
import MailOutlineIcon from "@mui/icons-material/MailOutline";
|
||||
import { api, getApiErrorMessage } from "../api";
|
||||
import { useToast } from "../toast";
|
||||
import GmailReviewPage from "./GmailReviewPage";
|
||||
|
||||
export type CorrespondenceInboxItem = {
|
||||
id: number;
|
||||
@@ -38,6 +39,8 @@ export type CorrespondenceInboxItem = {
|
||||
|
||||
export default function CorrespondenceInboxPage() {
|
||||
const navigate = useNavigate();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const view = searchParams.get("view") === "review" ? "review" : "inbox";
|
||||
const { toast } = useToast();
|
||||
const [items, setItems] = useState<CorrespondenceInboxItem[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
@@ -64,8 +67,8 @@ export default function CorrespondenceInboxPage() {
|
||||
}, [direction, linkState, query, toast]);
|
||||
|
||||
useEffect(() => {
|
||||
void load();
|
||||
}, [load]);
|
||||
if (view === "inbox") void load();
|
||||
}, [load, view]);
|
||||
|
||||
const filteredSummary = useMemo(() => {
|
||||
const linked = items.filter((item) => item.externalThreadId).length;
|
||||
@@ -85,20 +88,22 @@ export default function CorrespondenceInboxPage() {
|
||||
>
|
||||
<Box sx={{ display: "flex", justifyContent: "space-between", gap: 2, alignItems: "center", flexWrap: "wrap", mb: 2 }}>
|
||||
<Box>
|
||||
<Typography variant="h5" sx={{ fontWeight: 900 }}>Correspondence inbox</Typography>
|
||||
<Typography component="h1" variant="h5" sx={{ fontWeight: 900 }}>Job email</Typography>
|
||||
<Typography variant="body2" sx={{ color: "text.secondary" }}>
|
||||
Cross-job view of imported correspondence and Gmail-linked history.
|
||||
Review linked correspondence and suggested recruitment messages in one place.
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", gap: 1, flexWrap: "wrap", alignItems: "center" }}>
|
||||
<Chip icon={<MailOutlineIcon />} label={`${items.length} items`} variant="outlined" />
|
||||
<Chip label={`${filteredSummary.linked} linked`} variant="outlined" color={filteredSummary.linked > 0 ? "success" : "default"} />
|
||||
<Chip label={`${filteredSummary.inbound} inbound`} variant="outlined" />
|
||||
<Button variant="outlined" size="small" onClick={() => navigate("/correspondence/review")}>Review Gmail queue</Button>
|
||||
{view === "inbox" ? <Chip icon={<MailOutlineIcon />} label={`${items.length} items`} variant="outlined" /> : null}
|
||||
{view === "inbox" ? <Chip label={`${filteredSummary.linked} linked`} variant="outlined" color={filteredSummary.linked > 0 ? "success" : "default"} /> : null}
|
||||
{view === "inbox" ? <Chip label={`${filteredSummary.inbound} inbound`} variant="outlined" /> : null}
|
||||
<Button variant={view === "inbox" ? "contained" : "text"} size="small" onClick={() => setSearchParams({})}>Linked messages</Button>
|
||||
<Button variant={view === "review" ? "contained" : "text"} size="small" onClick={() => setSearchParams({ view: "review" })}>Review suggestions</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ display: "grid", gridTemplateColumns: { xs: "1fr", md: "2fr 1fr 1fr auto" }, gap: 1.25, mb: 2 }}>
|
||||
{view === "review" ? <GmailReviewPage embedded /> : <>
|
||||
<Box sx={{ display: "grid", gridTemplateColumns: { xs: "1fr", md: "2fr 1fr 1fr auto" }, gap: 1.25, mb: 2 }}>
|
||||
<TextField label="Search" value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Company, role, recruiter, subject" />
|
||||
<FormControl fullWidth>
|
||||
<InputLabel>Direction</InputLabel>
|
||||
@@ -118,7 +123,7 @@ export default function CorrespondenceInboxPage() {
|
||||
</Select>
|
||||
</FormControl>
|
||||
<Button variant="contained" onClick={() => void load()} disabled={loading}>{loading ? "Loading..." : "Refresh"}</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{loading ? <Box sx={{ py: 6, display: "flex", justifyContent: "center" }}><CircularProgress size={28} /></Box> : null}
|
||||
|
||||
@@ -148,6 +153,7 @@ export default function CorrespondenceInboxPage() {
|
||||
</Paper>
|
||||
))}
|
||||
</Stack>
|
||||
</>}
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { CreatedSuggestedGmailJobResult, GmailManualSyncResult, GmailReviewQueue
|
||||
import { useToast } from "../toast";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
export default function GmailReviewPage() {
|
||||
export default function GmailReviewPage({ embedded = false }: { embedded?: boolean }) {
|
||||
const { toast } = useToast();
|
||||
const navigate = useNavigate();
|
||||
const [data, setData] = useState<GmailReviewQueueResponse | null>(null);
|
||||
@@ -134,7 +134,7 @@ export default function GmailReviewPage() {
|
||||
>
|
||||
<Box sx={{ display: "flex", justifyContent: "space-between", gap: 2, alignItems: "center", flexWrap: "wrap", mb: 2 }}>
|
||||
<Box>
|
||||
<Typography variant="h5" sx={{ fontWeight: 900 }}>Gmail review queue</Typography>
|
||||
<Typography component={embedded ? "h2" : "h1"} variant="h5" sx={{ fontWeight: 900 }}>{embedded ? "Recruitment message review" : "Gmail review queue"}</Typography>
|
||||
<Typography variant="body2" sx={{ color: "text.secondary" }}>
|
||||
Manual sync, high-confidence auto-linking, medium-confidence review, and suggested jobs from unmatched Gmail threads.
|
||||
</Typography>
|
||||
@@ -146,7 +146,7 @@ export default function GmailReviewPage() {
|
||||
<Button variant="outlined" onClick={() => void load()} disabled={loading || syncing}>
|
||||
{loading ? "Loading..." : "Refresh"}
|
||||
</Button>
|
||||
<Button variant="text" onClick={() => navigate("/correspondence")}>Back to inbox</Button>
|
||||
{!embedded ? <Button variant="text" onClick={() => navigate("/correspondence")}>Back to inbox</Button> : null}
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user