Spaces:
Running
Running
gpt-engineer-app[bot]
commited on
Commit
·
bfd3ad3
1
Parent(s):
38de65f
Add countdown and rename title
Browse filesAdds a countdown timer to each conference card. Renames the page title to "AI Conference Deadlines".
src/components/ConferenceCard.tsx
CHANGED
@@ -1,6 +1,7 @@
|
|
1 |
-
|
|
|
2 |
import { Conference } from "@/types/conference";
|
3 |
-
import { formatDistanceToNow, parseISO } from "date-fns";
|
4 |
|
5 |
const ConferenceCard = ({
|
6 |
title,
|
@@ -15,8 +16,17 @@ const ConferenceCard = ({
|
|
15 |
abstract_deadline,
|
16 |
}: Conference) => {
|
17 |
const deadlineDate = deadline && deadline !== 'TBD' ? parseISO(deadline) : null;
|
18 |
-
const daysLeft = deadlineDate ? formatDistanceToNow(deadlineDate, { addSuffix: true }) : 'TBD';
|
19 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
return (
|
21 |
<div className="conference-card">
|
22 |
<div className="flex justify-between items-start mb-4">
|
@@ -56,6 +66,12 @@ const ConferenceCard = ({
|
|
56 |
</span>
|
57 |
)}
|
58 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
</div>
|
60 |
|
61 |
{Array.isArray(tags) && tags.length > 0 && (
|
|
|
1 |
+
|
2 |
+
import { CalendarDays, Globe, Tag, Clock, AlarmClock } from "lucide-react";
|
3 |
import { Conference } from "@/types/conference";
|
4 |
+
import { formatDistanceToNow, parseISO, isValid } from "date-fns";
|
5 |
|
6 |
const ConferenceCard = ({
|
7 |
title,
|
|
|
16 |
abstract_deadline,
|
17 |
}: Conference) => {
|
18 |
const deadlineDate = deadline && deadline !== 'TBD' ? parseISO(deadline) : null;
|
19 |
+
const daysLeft = deadlineDate && isValid(deadlineDate) ? formatDistanceToNow(deadlineDate, { addSuffix: true }) : 'TBD';
|
20 |
|
21 |
+
// Determine countdown color based on days remaining
|
22 |
+
const getCountdownColor = () => {
|
23 |
+
if (!deadlineDate || !isValid(deadlineDate)) return "text-neutral-600";
|
24 |
+
const daysRemaining = Math.ceil((deadlineDate.getTime() - new Date().getTime()) / (1000 * 60 * 60 * 24));
|
25 |
+
if (daysRemaining <= 7) return "text-red-600";
|
26 |
+
if (daysRemaining <= 30) return "text-orange-600";
|
27 |
+
return "text-green-600";
|
28 |
+
};
|
29 |
+
|
30 |
return (
|
31 |
<div className="conference-card">
|
32 |
<div className="flex justify-between items-start mb-4">
|
|
|
66 |
</span>
|
67 |
)}
|
68 |
</div>
|
69 |
+
<div className="flex items-center">
|
70 |
+
<AlarmClock className={`h-4 w-4 mr-2 ${getCountdownColor()}`} />
|
71 |
+
<span className={`text-sm font-medium ${getCountdownColor()}`}>
|
72 |
+
{daysLeft}
|
73 |
+
</span>
|
74 |
+
</div>
|
75 |
</div>
|
76 |
|
77 |
{Array.isArray(tags) && tags.length > 0 && (
|
src/components/Header.tsx
CHANGED
@@ -1,10 +1,7 @@
|
|
1 |
-
import { Search } from "lucide-react";
|
2 |
|
3 |
-
|
4 |
-
onSearch: (query: string) => void;
|
5 |
-
}
|
6 |
|
7 |
-
const Header = (
|
8 |
return (
|
9 |
<header className="w-full py-6 px-4 sm:px-6 lg:px-8 bg-white shadow-sm animate-fade-in">
|
10 |
<div className="max-w-7xl mx-auto">
|
@@ -16,13 +13,12 @@ const Header = ({ onSearch }: HeaderProps) => {
|
|
16 |
className="h-8 w-auto"
|
17 |
/>
|
18 |
<div className="h-6 w-px bg-neutral-200 mx-2" />
|
19 |
-
<h1 className="text-2xl font-bold text-neutral-dark">AI Deadlines</h1>
|
20 |
</div>
|
21 |
<div className="relative w-full max-w-md ml-4">
|
22 |
<input
|
23 |
type="text"
|
24 |
placeholder="Search conferences..."
|
25 |
-
onChange={(e) => onSearch(e.target.value)}
|
26 |
className="w-full pl-10 pr-4 py-2 border border-neutral-200 rounded-lg focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary bg-neutral-50"
|
27 |
/>
|
28 |
<Search className="absolute left-3 top-2.5 h-5 w-5 text-neutral" />
|
|
|
|
|
1 |
|
2 |
+
import { Search } from "lucide-react";
|
|
|
|
|
3 |
|
4 |
+
const Header = () => {
|
5 |
return (
|
6 |
<header className="w-full py-6 px-4 sm:px-6 lg:px-8 bg-white shadow-sm animate-fade-in">
|
7 |
<div className="max-w-7xl mx-auto">
|
|
|
13 |
className="h-8 w-auto"
|
14 |
/>
|
15 |
<div className="h-6 w-px bg-neutral-200 mx-2" />
|
16 |
+
<h1 className="text-2xl font-bold text-neutral-dark">AI Conference Deadlines</h1>
|
17 |
</div>
|
18 |
<div className="relative w-full max-w-md ml-4">
|
19 |
<input
|
20 |
type="text"
|
21 |
placeholder="Search conferences..."
|
|
|
22 |
className="w-full pl-10 pr-4 py-2 border border-neutral-200 rounded-lg focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary bg-neutral-50"
|
23 |
/>
|
24 |
<Search className="absolute left-3 top-2.5 h-5 w-5 text-neutral" />
|