ai-deadlines / src /utils /deadlineUtils.ts
nielsr's picture
nielsr HF Staff
Add support for multiple deadlines per conference
0fc7363
import { Conference, Deadline } from "@/types/conference";
import { getDeadlineInLocalTime } from './dateUtils';
import { isValid, isPast } from "date-fns";
/**
* Get all deadlines for a conference, including both new format and legacy format
*/
export function getAllDeadlines(conference: Conference): Deadline[] {
const deadlines: Deadline[] = [];
const seenTypes = new Set<string>();
// Add new format deadlines first (they take priority)
if (conference.deadlines && conference.deadlines.length > 0) {
conference.deadlines.forEach(deadline => {
deadlines.push(deadline);
seenTypes.add(deadline.type);
});
}
// Add legacy format deadlines for backward compatibility, but only if not already present
if (conference.abstract_deadline && !seenTypes.has('abstract')) {
deadlines.push({
type: 'abstract',
label: 'Abstract Submission',
date: conference.abstract_deadline,
timezone: conference.timezone
});
}
if (conference.deadline && !seenTypes.has('submission')) {
deadlines.push({
type: 'submission',
label: 'Paper Submission',
date: conference.deadline,
timezone: conference.timezone
});
}
if (conference.commitment_deadline && !seenTypes.has('commitment')) {
deadlines.push({
type: 'commitment',
label: 'Commitment',
date: conference.commitment_deadline,
timezone: conference.timezone
});
}
if (conference.review_release_date && !seenTypes.has('review_release')) {
deadlines.push({
type: 'review_release',
label: 'Reviews Released',
date: conference.review_release_date,
timezone: conference.timezone
});
}
if (conference.rebuttal_period_start && !seenTypes.has('rebuttal_start')) {
deadlines.push({
type: 'rebuttal_start',
label: 'Rebuttal Period Start',
date: conference.rebuttal_period_start,
timezone: conference.timezone
});
}
if (conference.rebuttal_period_end && !seenTypes.has('rebuttal_end')) {
deadlines.push({
type: 'rebuttal_end',
label: 'Rebuttal Period End',
date: conference.rebuttal_period_end,
timezone: conference.timezone
});
}
if (conference.final_decision_date && !seenTypes.has('final_decision')) {
deadlines.push({
type: 'final_decision',
label: 'Final Decision',
date: conference.final_decision_date,
timezone: conference.timezone
});
}
// Sort deadlines by date
deadlines.sort((a, b) => {
const aDate = getDeadlineInLocalTime(a.date, a.timezone || conference.timezone);
const bDate = getDeadlineInLocalTime(b.date, b.timezone || conference.timezone);
if (!aDate || !bDate) return 0;
return aDate.getTime() - bDate.getTime();
});
return deadlines;
}
/**
* Get the next upcoming deadline for a conference
*/
export function getNextUpcomingDeadline(conference: Conference): Deadline | null {
const allDeadlines = getAllDeadlines(conference);
if (allDeadlines.length === 0) {
return null;
}
// Filter out past deadlines and invalid dates
const upcomingDeadlines = allDeadlines.filter(deadline => {
const deadlineDate = getDeadlineInLocalTime(deadline.date, deadline.timezone || conference.timezone);
return deadlineDate && isValid(deadlineDate) && !isPast(deadlineDate);
});
if (upcomingDeadlines.length === 0) {
return null;
}
// Sort by date and return the earliest
upcomingDeadlines.sort((a, b) => {
const aDate = getDeadlineInLocalTime(a.date, a.timezone || conference.timezone);
const bDate = getDeadlineInLocalTime(b.date, b.timezone || conference.timezone);
if (!aDate || !bDate) return 0;
return aDate.getTime() - bDate.getTime();
});
return upcomingDeadlines[0];
}
/**
* Get the primary deadline for sorting purposes (next upcoming or most recent past)
*/
export function getPrimaryDeadline(conference: Conference): Deadline | null {
const nextDeadline = getNextUpcomingDeadline(conference);
if (nextDeadline) {
return nextDeadline;
}
// If no upcoming deadlines, return the most recent past deadline
const allDeadlines = getAllDeadlines(conference);
if (allDeadlines.length === 0) {
return null;
}
// Filter valid dates and sort by date (most recent first)
const validDeadlines = allDeadlines.filter(deadline => {
const deadlineDate = getDeadlineInLocalTime(deadline.date, deadline.timezone || conference.timezone);
return deadlineDate && isValid(deadlineDate);
});
if (validDeadlines.length === 0) {
return null;
}
validDeadlines.sort((a, b) => {
const aDate = getDeadlineInLocalTime(a.date, a.timezone || conference.timezone);
const bDate = getDeadlineInLocalTime(b.date, b.timezone || conference.timezone);
if (!aDate || !bDate) return 0;
return bDate.getTime() - aDate.getTime(); // Most recent first
});
return validDeadlines[0];
}
/**
* Check if a conference has any upcoming deadlines
*/
export function hasUpcomingDeadlines(conference: Conference): boolean {
return getNextUpcomingDeadline(conference) !== null;
}
/**
* Get all upcoming deadlines sorted by date
*/
export function getUpcomingDeadlines(conference: Conference): Deadline[] {
const allDeadlines = getAllDeadlines(conference);
// Filter out past deadlines and invalid dates
const upcomingDeadlines = allDeadlines.filter(deadline => {
const deadlineDate = getDeadlineInLocalTime(deadline.date, deadline.timezone || conference.timezone);
return deadlineDate && isValid(deadlineDate) && !isPast(deadlineDate);
});
// Sort by date
upcomingDeadlines.sort((a, b) => {
const aDate = getDeadlineInLocalTime(a.date, a.timezone || conference.timezone);
const bDate = getDeadlineInLocalTime(b.date, b.timezone || conference.timezone);
if (!aDate || !bDate) return 0;
return aDate.getTime() - bDate.getTime();
});
return upcomingDeadlines;
}