nielsr HF staff commited on
Commit
c6fd919
·
1 Parent(s): 51ec36d

Add legend filter

Browse files
Files changed (1) hide show
  1. src/pages/Calendar.tsx +66 -20
src/pages/Calendar.tsx CHANGED
@@ -49,6 +49,7 @@ const CalendarPage = () => {
49
  date: null,
50
  events: { deadlines: [], conferences: [] }
51
  });
 
52
 
53
  const safeParseISO = (dateString: string | undefined | number): Date | null => {
54
  if (!dateString) return null;
@@ -84,7 +85,11 @@ const CalendarPage = () => {
84
  conf.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
85
  (conf.full_name && conf.full_name.toLowerCase().includes(searchQuery.toLowerCase()));
86
 
87
- if (!matchesSearch) return false;
 
 
 
 
88
 
89
  const deadlineDate = safeParseISO(conf.deadline);
90
  const startDate = safeParseISO(conf.start);
@@ -115,15 +120,20 @@ const CalendarPage = () => {
115
  const getDayEvents = (date: Date) => {
116
  const deadlines = conferencesData.filter(conf => {
117
  const deadlineDate = safeParseISO(conf.deadline);
118
- return deadlineDate && isSameDay(deadlineDate, date);
 
 
119
  });
120
 
121
  const conferences = conferencesData.filter(conf => {
122
  const startDate = safeParseISO(conf.start);
123
  const endDate = safeParseISO(conf.end);
 
 
124
  return startDate && endDate &&
125
  date >= startDate &&
126
- date <= endDate;
 
127
  });
128
 
129
  return {
@@ -167,7 +177,9 @@ const CalendarPage = () => {
167
  .filter(conf => {
168
  const startDate = safeParseISO(conf.start);
169
  const endDate = safeParseISO(conf.end);
170
- return startDate && endDate && date >= startDate && date <= endDate;
 
 
171
  })
172
  .map(conf => {
173
  const startDate = safeParseISO(conf.start);
@@ -348,6 +360,52 @@ const CalendarPage = () => {
348
  conferencesData.some(conf => conf.tags?.includes(category))
349
  );
350
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
351
  return (
352
  <div className="min-h-screen bg-neutral-light">
353
  <Header onSearch={setSearchQuery} />
@@ -423,35 +481,23 @@ const CalendarPage = () => {
423
  <div className="max-w-7xl mx-auto">
424
  <div className="flex flex-col items-center mb-8">
425
  <h1 className="text-3xl font-bold mb-4">Calendar Overview</h1>
426
- <div className="flex items-center gap-4">
427
  <Toggle
428
  pressed={!isYearView}
429
  onPressedChange={() => setIsYearView(false)}
430
  variant="outline"
431
  >
432
- Month
433
  </Toggle>
434
  <Toggle
435
  pressed={isYearView}
436
  onPressedChange={() => setIsYearView(true)}
437
  variant="outline"
438
  >
439
- Year
440
  </Toggle>
441
  </div>
442
- </div>
443
-
444
- <div className="flex justify-center flex-wrap gap-4 mb-6">
445
- <div className="flex items-center gap-2">
446
- <div className="w-4 h-1 bg-red-500" />
447
- <span>Submission Deadlines</span>
448
- </div>
449
- {categories.map(([category, color]) => (
450
- <div key={category} className="flex items-center gap-2">
451
- <div className={`w-4 h-1 ${color}`} />
452
- <span>{categoryNames[category]}</span>
453
- </div>
454
- ))}
455
  </div>
456
 
457
  <div className="grid grid-cols-1 gap-8">
 
49
  date: null,
50
  events: { deadlines: [], conferences: [] }
51
  });
52
+ const [selectedCategories, setSelectedCategories] = useState<Set<string>>(new Set());
53
 
54
  const safeParseISO = (dateString: string | undefined | number): Date | null => {
55
  if (!dateString) return null;
 
85
  conf.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
86
  (conf.full_name && conf.full_name.toLowerCase().includes(searchQuery.toLowerCase()));
87
 
88
+ // Add category filter
89
+ const matchesCategory = selectedCategories.size === 0 ||
90
+ (Array.isArray(conf.tags) && conf.tags.some(tag => selectedCategories.has(tag)));
91
+
92
+ if (!matchesSearch || !matchesCategory) return false;
93
 
94
  const deadlineDate = safeParseISO(conf.deadline);
95
  const startDate = safeParseISO(conf.start);
 
120
  const getDayEvents = (date: Date) => {
121
  const deadlines = conferencesData.filter(conf => {
122
  const deadlineDate = safeParseISO(conf.deadline);
123
+ const matchesCategory = selectedCategories.size === 0 ||
124
+ (Array.isArray(conf.tags) && conf.tags.some(tag => selectedCategories.has(tag)));
125
+ return deadlineDate && isSameDay(deadlineDate, date) && matchesCategory;
126
  });
127
 
128
  const conferences = conferencesData.filter(conf => {
129
  const startDate = safeParseISO(conf.start);
130
  const endDate = safeParseISO(conf.end);
131
+ const matchesCategory = selectedCategories.size === 0 ||
132
+ (Array.isArray(conf.tags) && conf.tags.some(tag => selectedCategories.has(tag)));
133
  return startDate && endDate &&
134
  date >= startDate &&
135
+ date <= endDate &&
136
+ matchesCategory;
137
  });
138
 
139
  return {
 
177
  .filter(conf => {
178
  const startDate = safeParseISO(conf.start);
179
  const endDate = safeParseISO(conf.end);
180
+ const matchesCategory = selectedCategories.size === 0 ||
181
+ (Array.isArray(conf.tags) && conf.tags.some(tag => selectedCategories.has(tag)));
182
+ return startDate && endDate && date >= startDate && date <= endDate && matchesCategory;
183
  })
184
  .map(conf => {
185
  const startDate = safeParseISO(conf.start);
 
360
  conferencesData.some(conf => conf.tags?.includes(category))
361
  );
362
 
363
+ const renderLegend = () => {
364
+ const categories = Object.entries(categoryColors);
365
+
366
+ return (
367
+ <div className="flex flex-wrap gap-4 items-center mb-6">
368
+ <div className="flex items-center gap-2">
369
+ <div className="w-4 h-1 bg-red-500" />
370
+ <span className="text-sm">Submission Deadlines</span>
371
+ </div>
372
+ {categories.map(([category, color]) => {
373
+ const isSelected = selectedCategories.has(category);
374
+ return (
375
+ <button
376
+ key={category}
377
+ onClick={() => {
378
+ const newCategories = new Set(selectedCategories);
379
+ if (isSelected) {
380
+ newCategories.delete(category);
381
+ } else {
382
+ newCategories.add(category);
383
+ }
384
+ setSelectedCategories(newCategories);
385
+ }}
386
+ className={`flex items-center gap-2 px-3 py-1.5 rounded-lg transition-colors ${
387
+ isSelected
388
+ ? 'bg-neutral-100 ring-1 ring-neutral-200'
389
+ : 'hover:bg-neutral-50'
390
+ }`}
391
+ >
392
+ <div className={`w-4 h-1 ${color}`} />
393
+ <span className="text-sm">{categoryNames[category]}</span>
394
+ </button>
395
+ )
396
+ })}
397
+ {selectedCategories.size > 0 && (
398
+ <button
399
+ onClick={() => setSelectedCategories(new Set())}
400
+ className="text-sm text-neutral-500 hover:text-neutral-700"
401
+ >
402
+ Clear filters
403
+ </button>
404
+ )}
405
+ </div>
406
+ );
407
+ };
408
+
409
  return (
410
  <div className="min-h-screen bg-neutral-light">
411
  <Header onSearch={setSearchQuery} />
 
481
  <div className="max-w-7xl mx-auto">
482
  <div className="flex flex-col items-center mb-8">
483
  <h1 className="text-3xl font-bold mb-4">Calendar Overview</h1>
484
+ <div className="flex items-center gap-4 mb-6">
485
  <Toggle
486
  pressed={!isYearView}
487
  onPressedChange={() => setIsYearView(false)}
488
  variant="outline"
489
  >
490
+ Month View
491
  </Toggle>
492
  <Toggle
493
  pressed={isYearView}
494
  onPressedChange={() => setIsYearView(true)}
495
  variant="outline"
496
  >
497
+ Year View
498
  </Toggle>
499
  </div>
500
+ {renderLegend()}
 
 
 
 
 
 
 
 
 
 
 
 
501
  </div>
502
 
503
  <div className="grid grid-cols-1 gap-8">