Skip to content

Commit 6ecb579

Browse files
committed
Merge branch 'main' of https://github.com/ericahan22/Wat2Do
2 parents 4367e25 + e9b1ebf commit 6ecb579

File tree

13 files changed

+141
-82
lines changed

13 files changed

+141
-82
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Generated by Django 4.2.7 on 2025-10-29 21:32
2+
3+
from django.db import migrations, models
4+
import django.db.models.deletion
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
("events", "0014_alter_eventsubmission_submitted_by"),
11+
]
12+
13+
operations = [
14+
migrations.AddField(
15+
model_name="events",
16+
name="other_handle",
17+
field=models.CharField(
18+
blank=True,
19+
help_text="Other social media handle",
20+
max_length=100,
21+
null=True,
22+
),
23+
),
24+
migrations.AlterField(
25+
model_name="eventsubmission",
26+
name="created_event",
27+
field=models.ForeignKey(
28+
on_delete=django.db.models.deletion.CASCADE,
29+
related_name="submission",
30+
to="events.events",
31+
),
32+
),
33+
]

backend/apps/events/models.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ class Events(models.Model):
124124
fb_handle = models.CharField(
125125
max_length=100, blank=True, null=True, help_text="'uwcareercenter'"
126126
)
127+
other_handle = models.CharField(
128+
max_length=100, blank=True, null=True, help_text="Other social media handle"
129+
)
127130

128131
class Meta:
129132
db_table = "events"

backend/apps/events/views.py

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def get_events(request):
3030
try:
3131
search_term = request.GET.get("search", "").strip()
3232

33-
queryset = Events.objects.all().order_by("dtstart")
33+
queryset = Events.objects.filter(status__iexact="CONFIRMED").order_by("dtstart")
3434
filterset = EventFilter(request.GET, queryset=queryset)
3535
if not filterset.is_valid():
3636
return Response(
@@ -50,27 +50,19 @@ def get_events(request):
5050
# Build OR query: match any of the search terms in any field
5151
or_queries = Q()
5252
for term in search_terms:
53-
# Special handling for "free food" search
54-
if term.lower() == "free food":
55-
term_query = Q(
56-
(Q(price__isnull=True) | Q(price=0) | Q(price__icontains="free"))
57-
& Q(food__isnull=False)
58-
& ~Q(food="")
59-
)
60-
else:
61-
term_query = (
62-
Q(title__icontains=term)
63-
| Q(location__icontains=term)
64-
| Q(description__icontains=term)
65-
| Q(food__icontains=term)
66-
| Q(club_type__icontains=term)
67-
| Q(school__icontains=term)
68-
| Q(ig_handle__icontains=term)
69-
| Q(discord_handle__icontains=term)
70-
| Q(x_handle__icontains=term)
71-
| Q(tiktok_handle__icontains=term)
72-
| Q(fb_handle__icontains=term)
73-
)
53+
term_query = (
54+
Q(title__icontains=term)
55+
| Q(location__icontains=term)
56+
| Q(description__icontains=term)
57+
| Q(food__icontains=term)
58+
| Q(club_type__icontains=term)
59+
| Q(school__icontains=term)
60+
| Q(ig_handle__icontains=term)
61+
| Q(discord_handle__icontains=term)
62+
| Q(x_handle__icontains=term)
63+
| Q(tiktok_handle__icontains=term)
64+
| Q(fb_handle__icontains=term)
65+
)
7466
or_queries |= term_query
7567

7668
keyword_events = filtered_queryset.filter(or_queries)
@@ -111,6 +103,7 @@ def get_events(request):
111103
"x_handle",
112104
"tiktok_handle",
113105
"fb_handle",
106+
"other_handle",
114107
]
115108
results = list(filtered_queryset.values(*fields))
116109

@@ -449,13 +442,14 @@ def rss_feed(request):
449442

450443

451444
@api_view(["POST"])
452-
@permission_classes([AllowAny])
445+
@permission_classes([ClerkAuthenticated])
453446
@ratelimit(key="ip", rate="5/hr", block=True)
454447
def submit_event(request):
455448
"""Submit event for review - accepts screenshot file and source URL, runs extraction, creates Event and links submission"""
456449
try:
457450
screenshot = request.FILES.get("screenshot")
458451
source_url = request.data.get("source_url")
452+
other_handle = request.data.get("other_handle")
459453

460454
if not screenshot or not source_url:
461455
return Response(
@@ -483,8 +477,12 @@ def submit_event(request):
483477
if isinstance(event_data, dict):
484478
event_data["source_url"] = source_url
485479
event_data["source_image_url"] = event_data.get("source_image_url") or screenshot_url
480+
if other_handle:
481+
event_data["other_handle"] = other_handle
486482
else:
487483
event_data = {"source_url": source_url, "source_image_url": screenshot_url}
484+
if other_handle:
485+
event_data["other_handle"] = other_handle
488486

489487
# Create Event immediately and link submission
490488
allowed_fields = {f.name for f in Events._meta.get_fields()}
@@ -502,6 +500,9 @@ def submit_event(request):
502500
status=status.HTTP_400_BAD_REQUEST,
503501
)
504502

503+
# Create event with pending status by default
504+
if "status" not in cleaned or not cleaned.get("status"):
505+
cleaned["status"] = "PENDING"
505506
event = Events.objects.create(**cleaned)
506507

507508
# Attempt to capture submitting user if available (optional for anonymous)

frontend/public/rss.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<link>https://wat2do.ca</link>
66
<atom:link href="https://wat2do.ca/rss.xml" rel="self" type="application/rss+xml" />
77
<description>Upcoming events at the University of Waterloo</description>
8-
<lastBuildDate>Wed, 29 Oct 2025 22:08:56 GMT</lastBuildDate>
8+
<lastBuildDate>Wed, 29 Oct 2025 22:29:48 GMT</lastBuildDate>
99
<ttl>10</ttl>
1010
<item>
1111
<title>Future City Hackathon</title>

frontend/src/app/App.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,14 @@ function App() {
2929
<Route path="/" element={<EventsPage />} />
3030
<Route path="/events" element={<EventsPage />} />
3131
<Route path="/events/:eventId" element={<EventDetailPage />} />
32-
<Route path="/submit" element={<SubmitEventPage />} />
32+
<Route
33+
path="/submit"
34+
element={
35+
<ProtectedRoute>
36+
<SubmitEventPage />
37+
</ProtectedRoute>
38+
}
39+
/>
3340
<Route path="/clubs" element={<ClubsPage />} />
3441
<Route path="/about" element={<AboutPage />} />
3542
<Route path="/contact" element={<ContactPage />} />

frontend/src/data/staticData.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
export const LAST_UPDATED = "2025-10-29T22:08:56.280095+00:00";
1+
export const LAST_UPDATED = "2025-10-29T22:29:48.066807+00:00";
22

33
export const RECOMMENDED_FILTERS: [string, string, string][] = [
44
["Food%20and%20Drink", "Pizza", "Pizza"],
55
["Food%20and%20Drink", "Cookie", "Cookies"],
6+
["Food%20and%20Drink", "Beverage%20Box", "free food"],
67
["Smileys", "Ghost", "Halloween"],
8+
["Activity", "Ticket", "event"],
9+
["People", "Family%20Man%20Woman%20Girl%20Boy", "family"],
10+
["Food%20and%20Drink", "Doughnut", "treats"],
711
["Smileys", "Smiling%20Face%20With%20Hearts", "wellness"],
8-
["Activity", "Ticket", "workshop"],
9-
["Activity", "Basketball", "basketball"],
10-
["People", "Clapping%20Hands", "networking"],
11-
["Food%20and%20Drink", "Beverage%20Box", "drinks"],
12-
["Food%20and%20Drink", "Cupcake", "baked treats"],
13-
["Smileys", "Smiling%20Face%20With%20Halo", "community"],
14-
["Smileys", "Face%20With%20Tears%20Of%20Joy", "fun"],
15-
["Activity", "Sparkler", "festivities"],
1612
["Activity", "Confetti%20Ball", "celebration"],
17-
["Activity", "Fireworks", "event"],
18-
["Objects", "Microphone", "open mic"]
13+
["Smileys", "Grinning%20Face", "games"],
14+
["Smileys", "Hugging%20Face", "community"],
15+
["Activity", "Trophy", "competition"],
16+
["Smileys", "Beaming%20Face%20With%20Smiling%20Eyes", "fun"],
17+
["Food%20and%20Drink", "Chocolate%20Bar", "snacks"],
18+
["Smileys", "Winking%20Face", "social"]
1919
];

frontend/src/features/clubs/pages/ClubsPage.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { useMemo, useRef } from "react";
2+
import NumberFlow from "@number-flow/react";
23
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, useDocumentTitle, useCategoryParam, SEOHead } from "@/shared";
34
import { useClubs, ClubsGrid } from "@/features/clubs";
45
import SearchInput from "@/features/search/components/SearchInput";
@@ -44,14 +45,11 @@ function ClubsPage() {
4445
'campus groups'
4546
]}
4647
/>
47-
{/* Header */}
4848
<div className="sm:text-left">
49-
<h1 className="text-3xl font-bold text-gray-900 dark:text-white mb-2">
50-
Clubs
49+
<h1 className="sm:text-3xl text-2xl font-bold mb-2">
50+
<NumberFlow value={data.length} suffix={" clubs"} />
5151
</h1>
52-
<p className="text-gray-600 dark:text-gray-400">
53-
Explore student clubs and organizations
54-
</p>
52+
<p className="text-gray-600 dark:text-gray-400">Explore student clubs and organizations</p>
5553
</div>
5654

5755
{/* Filters */}

frontend/src/features/events/hooks/useUserSubmissions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ export const useUserSubmissions = () => {
1313
queryKey: ['user-submissions', userId],
1414
queryFn: () => events.getUserSubmissions(),
1515
enabled: isSignedIn && !!userId,
16-
staleTime: 30 * 1000, // 30 seconds - submissions don't change often
17-
gcTime: 5 * 60 * 1000, // 5 minutes
16+
staleTime: 30 * 1000,
17+
gcTime: 5 * 60 * 1000,
1818
});
1919

2020
// Delete a submission owned by the current user

frontend/src/features/events/pages/MySubmissionsPage.tsx

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
import { formatPrettyDate } from "@/shared/lib/dateUtils";
2020
import type { EventSubmission } from "@/features/events/types/submission";
2121
import { useNavigate } from "react-router-dom";
22+
import { useClerk } from "@clerk/clerk-react";
2223

2324
export function MySubmissionsPage() {
2425
const {
@@ -28,6 +29,7 @@ export function MySubmissionsPage() {
2829
isDeleting,
2930
} = useUserSubmissions();
3031
const navigate = useNavigate();
32+
const { signOut } = useClerk();
3133
// Type assertion to fix TypeScript issues
3234
const submissionsArray = submissions as EventSubmission[];
3335

@@ -76,13 +78,16 @@ export function MySubmissionsPage() {
7678
<div className="min-h-screen bg-gray-50 dark:bg-gray-900 py-12 px-4 sm:px-6 lg:px-8">
7779
<div className="max-w-6xl mx-auto">
7880
{/* Header */}
79-
<div className="mb-8">
80-
<h1 className="text-3xl font-bold text-gray-900 dark:text-gray-100">
81-
My Event Submissions
82-
</h1>
83-
<p className="text-gray-600 dark:text-gray-400 mt-2">
84-
Track the status of your submitted events
85-
</p>
81+
<div className="mb-8 flex items-start justify-between gap-4">
82+
<div>
83+
<h1 className="text-3xl font-bold text-gray-900 dark:text-gray-100">
84+
My Event Submissions
85+
</h1>
86+
<p className="text-gray-600 dark:text-gray-400 mt-2">
87+
Track the status of your submitted events
88+
</p>
89+
</div>
90+
<Button variant="outline" onMouseDown={() => signOut()}>Logout</Button>
8691
</div>
8792

8893
{/* Submissions Grid */}

frontend/src/features/events/pages/SubmitEventPage.tsx

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ export function SubmitEventPage() {
114114
<div className="space-y-3">
115115
<Label className="text-base font-medium flex items-center gap-2">
116116
<ImageIcon className="h-4 w-4" />
117-
Event Screenshot
117+
Event Screenshot*
118118
</Label>
119119
<DragDropFileUpload
120120
onFileSelect={handleFileSelect}
@@ -127,11 +127,10 @@ export function SubmitEventPage() {
127127
/>
128128
</div>
129129

130-
{/* Source URL */}
131130
<div className="space-y-3">
132131
<Label htmlFor="source_url" className="text-base font-medium flex items-center gap-2">
133132
<Link className="h-4 w-4" />
134-
Event Source URL
133+
Event Source URL*
135134
</Label>
136135
<Input
137136
id="source_url"
@@ -149,6 +148,24 @@ export function SubmitEventPage() {
149148
</p>
150149
</div>
151150

151+
{/* Organizer link / other handle (optional) */}
152+
<div className="space-y-3">
153+
<Label htmlFor="source_url" className="text-base font-medium flex items-center gap-2">
154+
Where can people find more events from you?
155+
</Label>
156+
<Input
157+
id="other_handle"
158+
type="url"
159+
placeholder="https://instagram.com/yourclub or https://discord.gg/yourinvite"
160+
className="h-12 text-base"
161+
{...register('other_handle')}
162+
disabled={isLoading}
163+
/>
164+
{errors.other_handle && (
165+
<p className="text-sm text-red-500 mt-1">{errors.other_handle.message as string}</p>
166+
)}
167+
</div>
168+
152169
{/* Submit Button */}
153170
<Button
154171
type="submit"

0 commit comments

Comments
 (0)