fix(mail): search every owned job
Replace ineffective pageSize=100 selectors with a bounded owner-filtered search endpoint for composing and moving linked threads.
This commit is contained in:
@@ -3,6 +3,7 @@ import { useNavigate, useSearchParams } from "react-router-dom";
|
||||
import {
|
||||
Box,
|
||||
Alert,
|
||||
Autocomplete,
|
||||
Chip,
|
||||
CircularProgress,
|
||||
FormControl,
|
||||
@@ -53,7 +54,7 @@ type EmailProviderStatus = {
|
||||
type JobChoice = {
|
||||
id: number;
|
||||
jobTitle: string;
|
||||
company?: { name?: string | null } | null;
|
||||
companyName: string;
|
||||
};
|
||||
|
||||
export function emailProviderStatusLabel(provider: EmailProviderStatus) {
|
||||
@@ -119,6 +120,8 @@ export default function CorrespondenceInboxPage() {
|
||||
const [providerStatusLoaded, setProviderStatusLoaded] = useState(false);
|
||||
const [jobs, setJobs] = useState<JobChoice[]>([]);
|
||||
const [jobsLoaded, setJobsLoaded] = useState(false);
|
||||
const [jobsLoading, setJobsLoading] = useState(false);
|
||||
const [jobQuery, setJobQuery] = useState("");
|
||||
const [composeSetupOpen, setComposeSetupOpen] = useState(false);
|
||||
const [composeJobId, setComposeJobId] = useState<number | "">("");
|
||||
const [composeProvider, setComposeProvider] = useState("");
|
||||
@@ -178,11 +181,18 @@ export default function CorrespondenceInboxPage() {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
api.get<{ items?: JobChoice[] }>("/jobapplications", { params: { page: 1, pageSize: 100, sortBy: "dateApplied", sortDir: "desc" } })
|
||||
.then((response) => setJobs(Array.isArray(response.data?.items) ? response.data.items : []))
|
||||
.catch(() => setJobs([]))
|
||||
.finally(() => setJobsLoaded(true));
|
||||
}, []);
|
||||
const timer = window.setTimeout(() => {
|
||||
setJobsLoading(true);
|
||||
api.get<JobChoice[]>("/jobapplications/choices", { params: { q: jobQuery.trim() || undefined, limit: 20 } })
|
||||
.then((response) => setJobs(Array.isArray(response.data) ? response.data : []))
|
||||
.catch(() => setJobs([]))
|
||||
.finally(() => {
|
||||
setJobsLoaded(true);
|
||||
setJobsLoading(false);
|
||||
});
|
||||
}, jobQuery.trim() ? 250 : 0);
|
||||
return () => window.clearTimeout(timer);
|
||||
}, [jobQuery]);
|
||||
|
||||
const loadStoredDrafts = useCallback(async () => {
|
||||
try {
|
||||
@@ -312,7 +322,7 @@ export default function CorrespondenceInboxPage() {
|
||||
}))) return;
|
||||
setDraft({
|
||||
jobApplicationId: job.id,
|
||||
companyName: job.company?.name || "Unknown company",
|
||||
companyName: job.companyName || "Unknown company",
|
||||
jobTitle: job.jobTitle || "Unknown role",
|
||||
provider: provider.provider,
|
||||
providerName: provider.displayName,
|
||||
@@ -558,12 +568,18 @@ export default function CorrespondenceInboxPage() {
|
||||
<Paper component="section" aria-labelledby="compose-new-title" variant="outlined" sx={{ p: 2, borderRadius: 3, mb: 2 }}>
|
||||
<Typography id="compose-new-title" component="h2" variant="h6" sx={{ fontWeight: 900, mb: 1.5 }}>Compose new email</Typography>
|
||||
<Box sx={{ display: "grid", gridTemplateColumns: { xs: "1fr", md: "1fr 1fr auto" }, gap: 1.25, alignItems: "center" }}>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel id="compose-job-label">Job</InputLabel>
|
||||
<Select labelId="compose-job-label" value={composeJobId} label="Job" onChange={(event) => setComposeJobId(Number(event.target.value))}>
|
||||
{jobs.map((job) => <MenuItem key={job.id} value={job.id}>{job.company?.name || "Unknown company"} · {job.jobTitle}</MenuItem>)}
|
||||
</Select>
|
||||
</FormControl>
|
||||
<Autocomplete
|
||||
options={jobs}
|
||||
loading={jobsLoading}
|
||||
value={jobs.find((job) => job.id === composeJobId) ?? null}
|
||||
onInputChange={(_, value, reason) => {
|
||||
if (reason === "input" || reason === "clear") setJobQuery(value);
|
||||
}}
|
||||
onChange={(_, value) => setComposeJobId(value?.id ?? "")}
|
||||
isOptionEqualToValue={(option, value) => option.id === value.id}
|
||||
getOptionLabel={(job) => `${job.companyName || "Unknown company"} · ${job.jobTitle}`}
|
||||
renderInput={(params) => <TextField {...params} label="Job" placeholder="Search every job" />}
|
||||
/>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel id="compose-provider-label">Sending provider</InputLabel>
|
||||
<Select labelId="compose-provider-label" value={composeProvider} label="Sending provider" onChange={(event) => setComposeProvider(String(event.target.value))}>
|
||||
|
||||
Reference in New Issue
Block a user