nielsr HF staff commited on
Commit
1685b02
·
1 Parent(s): 4c1a811

Update filters

Browse files
src/components/ConferenceCard.tsx CHANGED
@@ -31,17 +31,40 @@ const ConferenceCard = ({
31
  };
32
 
33
  const handleCardClick = (e: React.MouseEvent) => {
34
- // Only open dialog if the click wasn't on a link or interactive element
35
- if (!(e.target as HTMLElement).closest('a')) {
36
  setDialogOpen(true);
37
  }
38
  };
39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  return (
41
  <>
42
  <div
43
- onClick={handleCardClick}
44
  className="bg-white rounded-lg shadow-sm hover:shadow-md transition-shadow p-4 flex flex-col cursor-pointer"
 
45
  >
46
  <div className="flex justify-between items-start mb-2">
47
  <h3 className="text-lg font-semibold text-primary">{title}</h3>
@@ -82,12 +105,16 @@ const ConferenceCard = ({
82
  </div>
83
 
84
  {Array.isArray(tags) && tags.length > 0 && (
85
- <div className="flex flex-wrap gap-1 mt-auto">
86
  {tags.map((tag) => (
87
- <span key={tag} className="tag text-xs py-0.5">
 
 
 
 
88
  <Tag className="h-3 w-3 mr-1" />
89
  {tag}
90
- </span>
91
  ))}
92
  </div>
93
  )}
 
31
  };
32
 
33
  const handleCardClick = (e: React.MouseEvent) => {
34
+ if (!(e.target as HTMLElement).closest('a') &&
35
+ !(e.target as HTMLElement).closest('.tag-button')) {
36
  setDialogOpen(true);
37
  }
38
  };
39
 
40
+ const handleTagClick = (e: React.MouseEvent, tag: string) => {
41
+ e.stopPropagation();
42
+ const searchParams = new URLSearchParams(window.location.search);
43
+ const currentTags = searchParams.get('tags')?.split(',') || [];
44
+
45
+ let newTags;
46
+ if (currentTags.includes(tag)) {
47
+ newTags = currentTags.filter(t => t !== tag);
48
+ } else {
49
+ newTags = [...currentTags, tag];
50
+ }
51
+
52
+ if (newTags.length > 0) {
53
+ searchParams.set('tags', newTags.join(','));
54
+ } else {
55
+ searchParams.delete('tags');
56
+ }
57
+
58
+ const newUrl = `${window.location.pathname}${searchParams.toString() ? `?${searchParams.toString()}` : ''}`;
59
+ window.history.pushState({}, '', newUrl);
60
+ window.dispatchEvent(new CustomEvent('urlchange', { detail: { tag } }));
61
+ };
62
+
63
  return (
64
  <>
65
  <div
 
66
  className="bg-white rounded-lg shadow-sm hover:shadow-md transition-shadow p-4 flex flex-col cursor-pointer"
67
+ onClick={handleCardClick}
68
  >
69
  <div className="flex justify-between items-start mb-2">
70
  <h3 className="text-lg font-semibold text-primary">{title}</h3>
 
105
  </div>
106
 
107
  {Array.isArray(tags) && tags.length > 0 && (
108
+ <div className="flex flex-wrap gap-2">
109
  {tags.map((tag) => (
110
+ <button
111
+ key={tag}
112
+ className="tag tag-button"
113
+ onClick={(e) => handleTagClick(e, tag)}
114
+ >
115
  <Tag className="h-3 w-3 mr-1" />
116
  {tag}
117
+ </button>
118
  ))}
119
  </div>
120
  )}
src/pages/Index.tsx CHANGED
@@ -41,6 +41,46 @@ const Index = () => {
41
  });
42
  }, [selectedTags, searchQuery, showPastConferences]);
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  if (!Array.isArray(conferencesData)) {
45
  return <div>Loading conferences...</div>;
46
  }
@@ -52,7 +92,7 @@ const Index = () => {
52
  <div className="space-y-4 py-4">
53
  <FilterBar
54
  selectedTags={selectedTags}
55
- onTagSelect={setSelectedTags}
56
  />
57
  <div className="flex items-center gap-2">
58
  <label htmlFor="show-past" className="text-sm text-neutral-600">
 
41
  });
42
  }, [selectedTags, searchQuery, showPastConferences]);
43
 
44
+ // Update handleTagsChange to handle multiple tags
45
+ const handleTagsChange = (newTags: Set<string>) => {
46
+ setSelectedTags(newTags);
47
+ const searchParams = new URLSearchParams(window.location.search);
48
+ if (newTags.size > 0) {
49
+ searchParams.set('tags', Array.from(newTags).join(','));
50
+ } else {
51
+ searchParams.delete('tags');
52
+ }
53
+ const newUrl = `${window.location.pathname}${searchParams.toString() ? `?${searchParams.toString()}` : ''}`;
54
+ window.history.pushState({}, '', newUrl);
55
+ };
56
+
57
+ useEffect(() => {
58
+ const handleUrlChange = (event: CustomEvent) => {
59
+ const { tag } = event.detail;
60
+ // Create new Set with existing tags plus the new one
61
+ const newTags = new Set(selectedTags);
62
+ if (newTags.has(tag)) {
63
+ newTags.delete(tag);
64
+ } else {
65
+ newTags.add(tag);
66
+ }
67
+ handleTagsChange(newTags);
68
+ };
69
+
70
+ window.addEventListener('urlchange', handleUrlChange as EventListener);
71
+
72
+ // Check URL params on mount
73
+ const params = new URLSearchParams(window.location.search);
74
+ const tagsParam = params.get('tags');
75
+ if (tagsParam) {
76
+ setSelectedTags(new Set(tagsParam.split(',')));
77
+ }
78
+
79
+ return () => {
80
+ window.removeEventListener('urlchange', handleUrlChange as EventListener);
81
+ };
82
+ }, [selectedTags]); // Add selectedTags as dependency
83
+
84
  if (!Array.isArray(conferencesData)) {
85
  return <div>Loading conferences...</div>;
86
  }
 
92
  <div className="space-y-4 py-4">
93
  <FilterBar
94
  selectedTags={selectedTags}
95
+ onTagSelect={handleTagsChange}
96
  />
97
  <div className="flex items-center gap-2">
98
  <label htmlFor="show-past" className="text-sm text-neutral-600">
src/styles/globals.css CHANGED
@@ -1,4 +1,3 @@
1
-
2
  /* Add these styles to make the filter tags more interactive */
3
  .filter-tag {
4
  @apply transition-all duration-200;
@@ -18,3 +17,21 @@
18
  .filter-tag-active {
19
  animation: subtle-pulse 2s infinite;
20
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  /* Add these styles to make the filter tags more interactive */
2
  .filter-tag {
3
  @apply transition-all duration-200;
 
17
  .filter-tag-active {
18
  animation: subtle-pulse 2s infinite;
19
  }
20
+
21
+ .tag-button {
22
+ background: none;
23
+ border: none;
24
+ padding: 0;
25
+ cursor: pointer;
26
+ display: inline-flex;
27
+ align-items: center;
28
+ font-size: 0.875rem;
29
+ color: #666;
30
+ background-color: #f5f5f5;
31
+ padding: 0.25rem 0.5rem;
32
+ border-radius: 0.375rem;
33
+ }
34
+
35
+ .tag-button:hover {
36
+ background-color: #e5e5e5;
37
+ }