gpt-engineer-app[bot] commited on
Commit
2782f86
·
1 Parent(s): 1b6ad1f

Improve calendar overview

Browse files

Updated calendar display to be larger and centrally positioned. Added color-coded display of conferences and submission deadlines.

Files changed (1) hide show
  1. src/pages/Calendar.tsx +79 -50
src/pages/Calendar.tsx CHANGED
@@ -2,7 +2,7 @@
2
  import { useState } from "react";
3
  import conferencesData from "@/data/conferences.yml";
4
  import { Conference } from "@/types/conference";
5
- import { Calendar as CalendarIcon, Tag } from "lucide-react";
6
  import { Calendar } from "@/components/ui/calendar";
7
  import { parseISO, format, isValid } from "date-fns";
8
 
@@ -31,19 +31,27 @@ const CalendarPage = () => {
31
 
32
  // Get all unique dates (deadlines and conference dates)
33
  const getDatesWithEvents = () => {
34
- const dates = new Set<string>();
 
 
 
 
35
  conferencesData.forEach((conf: Conference) => {
36
  const deadlineDate = safeParseISO(conf.deadline);
37
  const startDate = safeParseISO(conf.start);
38
 
39
  if (deadlineDate) {
40
- dates.add(format(deadlineDate, 'yyyy-MM-dd'));
41
  }
42
  if (startDate) {
43
- dates.add(format(startDate, 'yyyy-MM-dd'));
44
  }
45
  });
46
- return Array.from(dates).map(date => parseISO(date));
 
 
 
 
47
  };
48
 
49
  // Get conferences for selected date
@@ -61,67 +69,88 @@ const CalendarPage = () => {
61
  };
62
 
63
  const selectedDateConferences = selectedDate ? getConferencesForDate(selectedDate) : [];
 
64
 
65
  return (
66
  <div className="min-h-screen bg-neutral-light p-6">
67
  <div className="max-w-7xl mx-auto">
68
- <h1 className="text-3xl font-bold mb-8">Calendar Overview</h1>
69
- <div className="grid md:grid-cols-2 gap-8">
70
- <div>
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  <Calendar
72
  mode="single"
73
  selected={selectedDate}
74
  onSelect={setSelectedDate}
75
- className="bg-white rounded-lg p-4 shadow-sm"
 
 
 
 
 
 
 
76
  modifiers={{
77
- event: getDatesWithEvents()
 
78
  }}
79
  modifiersStyles={{
80
- event: {
81
- fontWeight: 'bold',
82
- color: '#0284C7',
83
- textDecoration: 'underline'
 
 
 
84
  }
85
  }}
86
  />
87
  </div>
88
- <div className="space-y-4">
89
- {selectedDate && (
90
- <>
91
- <h2 className="text-xl font-semibold flex items-center gap-2">
92
- <CalendarIcon className="h-5 w-5" />
93
- Events on {format(selectedDate, 'MMMM d, yyyy')}
94
- </h2>
95
- {selectedDateConferences.length === 0 ? (
96
- <p className="text-neutral-600">No events on this date.</p>
97
- ) : (
98
- <div className="space-y-4">
99
- {selectedDateConferences.map((conf: Conference) => (
100
- <div key={conf.id} className="bg-white p-4 rounded-lg shadow-sm">
101
- <h3 className="font-semibold text-lg">{conf.title}</h3>
102
- {conf.deadline && safeParseISO(conf.deadline) &&
103
- format(safeParseISO(conf.deadline)!, 'yyyy-MM-dd') === format(selectedDate, 'yyyy-MM-dd') && (
104
- <p className="text-red-600">Submission Deadline</p>
105
- )}
106
- {conf.start && safeParseISO(conf.start) &&
107
- format(safeParseISO(conf.start)!, 'yyyy-MM-dd') === format(selectedDate, 'yyyy-MM-dd') && (
108
- <p className="text-green-600">Conference Start Date</p>
109
- )}
110
- <div className="mt-2 flex flex-wrap gap-2">
111
- {conf.tags.map((tag) => (
112
- <span key={tag} className="tag text-sm">
113
- <Tag className="h-3 w-3 mr-1" />
114
- {tag}
115
- </span>
116
- ))}
117
- </div>
118
- </div>
119
- ))}
120
  </div>
121
- )}
122
- </>
123
- )}
124
- </div>
125
  </div>
126
  </div>
127
  </div>
 
2
  import { useState } from "react";
3
  import conferencesData from "@/data/conferences.yml";
4
  import { Conference } from "@/types/conference";
5
+ import { Calendar as CalendarIcon, Tag, CircleDot } from "lucide-react";
6
  import { Calendar } from "@/components/ui/calendar";
7
  import { parseISO, format, isValid } from "date-fns";
8
 
 
31
 
32
  // Get all unique dates (deadlines and conference dates)
33
  const getDatesWithEvents = () => {
34
+ const dates = {
35
+ conferences: new Set<string>(),
36
+ deadlines: new Set<string>()
37
+ };
38
+
39
  conferencesData.forEach((conf: Conference) => {
40
  const deadlineDate = safeParseISO(conf.deadline);
41
  const startDate = safeParseISO(conf.start);
42
 
43
  if (deadlineDate) {
44
+ dates.deadlines.add(format(deadlineDate, 'yyyy-MM-dd'));
45
  }
46
  if (startDate) {
47
+ dates.conferences.add(format(startDate, 'yyyy-MM-dd'));
48
  }
49
  });
50
+
51
+ return {
52
+ conferences: Array.from(dates.conferences).map(date => parseISO(date)),
53
+ deadlines: Array.from(dates.deadlines).map(date => parseISO(date))
54
+ };
55
  };
56
 
57
  // Get conferences for selected date
 
69
  };
70
 
71
  const selectedDateConferences = selectedDate ? getConferencesForDate(selectedDate) : [];
72
+ const datesWithEvents = getDatesWithEvents();
73
 
74
  return (
75
  <div className="min-h-screen bg-neutral-light p-6">
76
  <div className="max-w-7xl mx-auto">
77
+ <h1 className="text-3xl font-bold mb-8 text-center">Calendar Overview</h1>
78
+
79
+ {/* Color Legend */}
80
+ <div className="flex justify-center gap-6 mb-6">
81
+ <div className="flex items-center gap-2">
82
+ <CircleDot className="h-4 w-4 text-purple-600" />
83
+ <span>Conference Dates</span>
84
+ </div>
85
+ <div className="flex items-center gap-2">
86
+ <CircleDot className="h-4 w-4 text-red-500" />
87
+ <span>Submission Deadlines</span>
88
+ </div>
89
+ </div>
90
+
91
+ <div className="grid grid-cols-1 gap-8">
92
+ <div className="mx-auto w-full max-w-3xl">
93
  <Calendar
94
  mode="single"
95
  selected={selectedDate}
96
  onSelect={setSelectedDate}
97
+ className="bg-white rounded-lg p-6 shadow-sm mx-auto w-full"
98
+ classNames={{
99
+ month: "w-full",
100
+ table: "w-full",
101
+ cell: "h-14 w-14 text-center text-sm p-0 relative [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20",
102
+ day: "h-14 w-14 p-0 font-normal aria-selected:opacity-100 hover:bg-neutral-100 rounded-lg transition-colors",
103
+ day_today: "bg-neutral-100 text-primary font-semibold"
104
+ }}
105
  modifiers={{
106
+ conference: datesWithEvents.conferences,
107
+ deadline: datesWithEvents.deadlines
108
  }}
109
  modifiersStyles={{
110
+ conference: {
111
+ color: '#7C3AED', // purple-600
112
+ fontWeight: 'bold'
113
+ },
114
+ deadline: {
115
+ color: '#EF4444', // red-500
116
+ fontWeight: 'bold'
117
  }
118
  }}
119
  />
120
  </div>
121
+
122
+ {/* Selected Date Events */}
123
+ {selectedDate && selectedDateConferences.length > 0 && (
124
+ <div className="mx-auto w-full max-w-3xl space-y-4">
125
+ <h2 className="text-xl font-semibold flex items-center gap-2">
126
+ <CalendarIcon className="h-5 w-5" />
127
+ Events on {format(selectedDate, 'MMMM d, yyyy')}
128
+ </h2>
129
+ <div className="space-y-4">
130
+ {selectedDateConferences.map((conf: Conference) => (
131
+ <div key={conf.id} className="bg-white p-4 rounded-lg shadow-sm">
132
+ <h3 className="font-semibold text-lg">{conf.title}</h3>
133
+ {conf.deadline && safeParseISO(conf.deadline) &&
134
+ format(safeParseISO(conf.deadline)!, 'yyyy-MM-dd') === format(selectedDate, 'yyyy-MM-dd') && (
135
+ <p className="text-red-500">Submission Deadline</p>
136
+ )}
137
+ {conf.start && safeParseISO(conf.start) &&
138
+ format(safeParseISO(conf.start)!, 'yyyy-MM-dd') === format(selectedDate, 'yyyy-MM-dd') && (
139
+ <p className="text-purple-600">Conference Start Date</p>
140
+ )}
141
+ <div className="mt-2 flex flex-wrap gap-2">
142
+ {conf.tags.map((tag) => (
143
+ <span key={tag} className="tag text-sm">
144
+ <Tag className="h-3 w-3 mr-1" />
145
+ {tag}
146
+ </span>
147
+ ))}
148
+ </div>
 
 
 
 
149
  </div>
150
+ ))}
151
+ </div>
152
+ </div>
153
+ )}
154
  </div>
155
  </div>
156
  </div>