File size: 4,872 Bytes
64b8b1b
 
 
 
 
 
 
 
 
 
 
67688f8
 
 
 
 
 
 
 
 
 
 
 
64b8b1b
 
 
 
67688f8
 
 
 
 
64b8b1b
67688f8
 
64b8b1b
 
 
 
 
 
 
 
 
67688f8
 
 
 
 
 
 
64b8b1b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67688f8
 
64b8b1b
 
67688f8
 
64b8b1b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

import { useState } from "react";
import conferencesData from "@/data/conferences.yml";
import { Conference } from "@/types/conference";
import { Calendar as CalendarIcon, Tag } from "lucide-react";
import { Calendar } from "@/components/ui/calendar";
import { parseISO, format, isValid } from "date-fns";

const CalendarPage = () => {
  const [selectedDate, setSelectedDate] = useState<Date | undefined>(new Date());
  
  // Helper function to safely parse dates
  const safeParseISO = (dateString: string | undefined): Date | null => {
    if (!dateString || dateString === 'TBD') return null;
    
    // Try to parse the date, handling different formats
    const normalizedDate = dateString.replace(/(\d{4})-(\d{1})-(\d{1,2})/, '$1-0$2-$3')
                                   .replace(/(\d{4})-(\d{2})-(\d{1})/, '$1-$2-0$3');
    
    const parsedDate = parseISO(normalizedDate);
    return isValid(parsedDate) ? parsedDate : null;
  };

  // Get all unique dates (deadlines and conference dates)
  const getDatesWithEvents = () => {
    const dates = new Set<string>();
    conferencesData.forEach((conf: Conference) => {
      const deadlineDate = safeParseISO(conf.deadline);
      const startDate = safeParseISO(conf.start);

      if (deadlineDate) {
        dates.add(format(deadlineDate, 'yyyy-MM-dd'));
      }
      if (startDate) {
        dates.add(format(startDate, 'yyyy-MM-dd'));
      }
    });
    return Array.from(dates).map(date => parseISO(date));
  };

  // Get conferences for selected date
  const getConferencesForDate = (date: Date) => {
    const formattedDate = format(date, 'yyyy-MM-dd');
    return conferencesData.filter((conf: Conference) => {
      const deadlineDate = safeParseISO(conf.deadline);
      const startDate = safeParseISO(conf.start);

      const deadlineDateStr = deadlineDate ? format(deadlineDate, 'yyyy-MM-dd') : null;
      const startDateStr = startDate ? format(startDate, 'yyyy-MM-dd') : null;

      return deadlineDateStr === formattedDate || startDateStr === formattedDate;
    });
  };

  const selectedDateConferences = selectedDate ? getConferencesForDate(selectedDate) : [];

  return (
    <div className="min-h-screen bg-neutral-light p-6">
      <div className="max-w-7xl mx-auto">
        <h1 className="text-3xl font-bold mb-8">Calendar Overview</h1>
        <div className="grid md:grid-cols-2 gap-8">
          <div>
            <Calendar
              mode="single"
              selected={selectedDate}
              onSelect={setSelectedDate}
              className="bg-white rounded-lg p-4 shadow-sm"
              modifiers={{
                event: getDatesWithEvents()
              }}
              modifiersStyles={{
                event: {
                  fontWeight: 'bold',
                  color: '#0284C7',
                  textDecoration: 'underline'
                }
              }}
            />
          </div>
          <div className="space-y-4">
            {selectedDate && (
              <>
                <h2 className="text-xl font-semibold flex items-center gap-2">
                  <CalendarIcon className="h-5 w-5" />
                  Events on {format(selectedDate, 'MMMM d, yyyy')}
                </h2>
                {selectedDateConferences.length === 0 ? (
                  <p className="text-neutral-600">No events on this date.</p>
                ) : (
                  <div className="space-y-4">
                    {selectedDateConferences.map((conf: Conference) => (
                      <div key={conf.id} className="bg-white p-4 rounded-lg shadow-sm">
                        <h3 className="font-semibold text-lg">{conf.title}</h3>
                        {conf.deadline && safeParseISO(conf.deadline) && 
                          format(safeParseISO(conf.deadline)!, 'yyyy-MM-dd') === format(selectedDate, 'yyyy-MM-dd') && (
                          <p className="text-red-600">Submission Deadline</p>
                        )}
                        {conf.start && safeParseISO(conf.start) && 
                          format(safeParseISO(conf.start)!, 'yyyy-MM-dd') === format(selectedDate, 'yyyy-MM-dd') && (
                          <p className="text-green-600">Conference Start Date</p>
                        )}
                        <div className="mt-2 flex flex-wrap gap-2">
                          {conf.tags.map((tag) => (
                            <span key={tag} className="tag text-sm">
                              <Tag className="h-3 w-3 mr-1" />
                              {tag}
                            </span>
                          ))}
                        </div>
                      </div>
                    ))}
                  </div>
                )}
              </>
            )}
          </div>
        </div>
      </div>
    </div>
  );
};

export default CalendarPage;