Skip to content

Commit 402be59

Browse files
Tony QiuTony Qiu
authored andcommitted
fix empty search input
1 parent d7775c5 commit 402be59

File tree

9 files changed

+66
-17
lines changed

9 files changed

+66
-17
lines changed

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ python manage.py runserver
8282
```bash
8383
cd backend
8484
docker build -t instagram-scraper-api .
85-
docker run -p 8000:8000 instagram-scraper-api
85+
docker run -p 3000:3000 instagram-scraper-api
8686
```
8787

8888
## Dependencies
@@ -98,7 +98,7 @@ docker run -p 8000:8000 instagram-scraper-api
9898

9999
## Notes
100100

101-
- The Django server runs on port 8000
101+
- The Django server runs on port 3000
102102
- CSV files are now located in `/backend/scripts/`
103103
- API endpoints are prefixed with `/api/`
104104
- CORS is enabled for frontend integration
@@ -108,9 +108,9 @@ docker run -p 8000:8000 instagram-scraper-api
108108

109109
| Goal/Description | cURL Command |
110110
|------------------|--------------|
111-
| Get API info | `curl http://localhost:8000/api/` |
112-
| Health check | `curl http://localhost:8000/api/health/` |
113-
| Get all events | `curl http://localhost:8000/api/events/` |
114-
| Get all clubs | `curl http://localhost:8000/api/clubs/` |
115-
| Create mock event | `curl -X POST http://localhost:8000/api/mock-event/ -H "Content-Type: application/json" -d '{"name": "Test Event", "location": "Test Location", "food": "Pizza"}'` |
116-
| Find similar events | `curl "http://localhost:8000/api/test-similarity/?text=Your%20Search%20Text"` |
111+
| Get API info | `curl http://localhost:3000/api/` |
112+
| Health check | `curl http://localhost:3000/health/` |
113+
| Get all events | `curl http://localhost:3000/api/events/` |
114+
| Get all clubs | `curl http://localhost:3000/api/clubs/` |
115+
| Create mock event | `curl -X POST http://localhost:3000/api/mock-event/ -H "Content-Type: application/json" -d '{"name": "Test Event", "location": "Test Location", "food": "Pizza"}'` |
116+
| Find similar events | `curl "http://localhost:3000/api/test-similarity/?text=Your%20Search%20Text"` |

backend/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ COPY docker-entrypoint.sh /usr/local/bin/
2424
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
2525

2626
# Expose port
27-
EXPOSE 8000
27+
EXPOSE 3000
2828

2929
# Use entrypoint script
3030
ENTRYPOINT ["docker-entrypoint.sh"]

backend/api/urls.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717

1818
from django.contrib import admin
1919
from django.urls import include, path
20+
from example import views
2021

2122
urlpatterns = [
2223
path("admin/", admin.site.urls),
24+
path("health/", views.health, name="health"),
2325
path("api/", include("example.urls")),
2426
]

backend/docker-entrypoint.sh

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,42 @@
11
#!/bin/bash
22
set -e
33

4+
# Wait for database to be ready
5+
echo "Waiting for database..."
6+
max_attempts=30
7+
attempt=0
8+
until python manage.py check --database default > /dev/null 2>&1 || [ $attempt -eq $max_attempts ]; do
9+
attempt=$((attempt + 1))
10+
echo "Database not ready, attempt $attempt/$max_attempts..."
11+
sleep 2
12+
done
13+
14+
if [ $attempt -eq $max_attempts ]; then
15+
echo "ERROR: Database connection timeout after $max_attempts attempts"
16+
exit 1
17+
fi
18+
19+
echo "Database is ready!"
20+
421
echo "Running database migrations..."
522
python manage.py migrate --noinput
623

724
echo "Collecting static files..."
825
python manage.py collectstatic --noinput
926

1027
echo "Starting gunicorn..."
11-
exec gunicorn --bind 0.0.0.0:8000 --workers 4 --timeout 120 api.wsgi:app
28+
# Graceful shutdown settings:
29+
# --graceful-timeout: Time to wait for workers to finish after SIGTERM (default 30s)
30+
# --timeout: Worker timeout for requests (120s)
31+
# --worker-class: Use sync workers (default)
32+
# --access-logfile and --error-logfile: Send logs to stdout/stderr for ECS CloudWatch
33+
exec gunicorn \
34+
--bind 0.0.0.0:3000 \
35+
--workers 4 \
36+
--timeout 120 \
37+
--graceful-timeout 30 \
38+
--access-logfile - \
39+
--error-logfile - \
40+
--log-level info \
41+
api.wsgi:app
1242

backend/example/views.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def home(_request):
3131
"endpoints": {
3232
"GET /api/events/?search=search_text": "Search events using vector similarity",
3333
"GET /api/clubs/": "Get all clubs from database",
34-
"GET /api/health/": "Health check",
34+
"GET /health/": "Health check",
3535
"POST /api/mock-event/": (
3636
"Create a mock event with vector embedding (admin only)"
3737
),

frontend/src/hooks/useClubs.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export interface Club {
1616
}
1717

1818
const API_BASE_URL =
19-
import.meta.env.VITE_API_BASE_URL || "http://localhost:8000";
19+
import.meta.env.VITE_API_BASE_URL || "http://localhost:3000";
2020

2121
const fetchClubs = async ({
2222
queryKey,

frontend/src/hooks/useEvents.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ interface EventsResponse {
2727
}
2828

2929
const API_BASE_URL =
30-
import.meta.env.VITE_API_BASE_URL || "http://localhost:8000";
30+
import.meta.env.VITE_API_BASE_URL || "http://localhost:3000";
3131

3232
// Format the last updated timestamp into a human-readable format
3333
export const getLastUpdatedText = (): string => {

frontend/src/hooks/useSearchState.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useState, useEffect, useCallback } from "react";
1+
import { useState, useEffect, useCallback, useRef } from "react";
22
import { useSearchParams } from "react-router-dom";
33
import { useLocalStorage } from "react-use";
44

@@ -10,10 +10,18 @@ export function useSearchState() {
1010

1111
const searchParam = searchParams.get("search") || "";
1212
const [inputValue, setInputValue] = useState(searchParam || lastSearch || "");
13+
const isInitialMount = useRef(true);
1314

1415
// Sync input value with URL search param when it changes
1516
useEffect(() => {
16-
if (searchParam) {
17+
if (isInitialMount.current) {
18+
isInitialMount.current = false;
19+
// On initial mount, only sync if there's an actual search param
20+
if (searchParam) {
21+
setInputValue(searchParam);
22+
}
23+
} else {
24+
// On subsequent updates, always sync with URL
1725
setInputValue(searchParam);
1826
}
1927
}, [searchParam]);
@@ -26,6 +34,15 @@ export function useSearchState() {
2634
nextParams.set("search", inputValue);
2735
return nextParams;
2836
});
37+
} else {
38+
// If input is empty, clear the search
39+
setInputValue("");
40+
setLastSearch("");
41+
setSearchParams((prev) => {
42+
const nextParams = new URLSearchParams(prev);
43+
nextParams.delete("search");
44+
return nextParams;
45+
});
2946
}
3047
}, [inputValue, setLastSearch, setSearchParams]);
3148

frontend/src/pages/EventsPage.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ function EventsPage() {
6262
<SearchInput placeholder="Search events..." className="flex-1" />
6363

6464
{/* View toggle tabs */}
65-
<div className="flex gap-2">
65+
<div className="flex justify-between gap-2">
6666
{view === "grid" && (
6767
<Button
6868
variant="outline"
@@ -78,7 +78,7 @@ function EventsPage() {
7878
) : (
7979
<>
8080
<Calendar className="h-4 w-4" />
81-
Export to Calendar
81+
Export
8282
</>
8383
)}
8484
</Button>

0 commit comments

Comments
 (0)