Conversation
Adds optional trip date range support across the full backend stack: - Migration: adds start_date/end_date DATE columns with composite index - Models: Trip, TripAPIResponse, TripDatabaseResponse, CreateTripRequest, UpdateTripRequest - Repository: includes date columns in SELECT queries and UPDATE handler - Service: maps dates through create/update/get paths with end > start validation Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Runs kubb to regenerate TypeScript types, Zod schemas, and React Query hooks reflecting the new start_date and end_date fields on TripAPIResponse. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis PR adds comment-reaction API schemas and frontend types/hooks, introduces trip start_date/end_date (DB migration, models, repo, service, tests), and adds activity time_of_day plus optional date/time filters for activity listing. API docs and generated types/schemas are updated accordingly. Changes
Sequence Diagram(s)(omitted) Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Covers happy paths (create/get/list/update with dates), validation (end before start rejected on both create and update), and the no-dates case (fields omitted from response when not set). Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 9
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
backend/docs/swagger.json (1)
1593-1627:⚠️ Potential issue | 🟠 MajorAdd
format: dateto date-typed fields in Go struct annotations.The
datequery parameter,start_date, andend_datefields in Trip and related models are missing theformat: "date"specification in the generated swagger.json. Add the format tag to the Go struct field annotations (consistent with DateRange's existing pattern) so swag generates the proper OpenAPI schema withtype: "string"andformat: "date".Affected locations
- Lines 1593-1627: date query parameter in getActivitiesByTripID
- Lines 6099-6107, 7183-7194, 7218-7229, 7435-7443: start_date and end_date fields in model definitions
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@backend/docs/swagger.json` around lines 1593 - 1627, The OpenAPI schema is missing the date format for date-typed fields; update the Go struct field annotations and operation param docs to include format:"date" for the relevant fields: add the format tag for the query parameter named "date" in the getActivitiesByTripID handler docs, and add format:"date" to the struct tags for start_date and end_date on the Trip and related models (e.g., the Trip struct and DateRange-related structs referenced in swagger generation) so swag generates type: "string" with format: "date".frontend/types/schema.gen.ts (1)
1128-1136:⚠️ Potential issue | 🟠 MajorAdd
format: dateannotation to trip date fields in the upstream OpenAPI specification.The
start_dateandend_datefields in CreateTripRequest and related trip schemas are currently defined as plain strings in the OpenAPI spec, but they should useformat: dateto enforce ISO 8601 date validation. This matches the Go backend models which usetime.Timeand the pattern already established elsewhere in the spec. Without this annotation, the generated frontend schemas accept invalid dates like2026-13-40, and the TypeScript types lack proper date validation.Update
backend/docs/swagger.jsonandbackend/docs/swagger.yamlto addformat: dateto these fields, then regenerate the frontend types.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/types/schema.gen.ts` around lines 1128 - 1136, The generated schema modelsCreateTripRequestSchema allows invalid dates because start_date and end_date are plain strings in the OpenAPI spec; update the upstream OpenAPI definitions for CreateTripRequest (and any related trip schemas) in backend/docs/swagger.json and backend/docs/swagger.yaml to add "format": "date" for the start_date and end_date properties (matching the Go time.Time usage), then regenerate the frontend types so modelsCreateTripRequestSchema (and related schemas) use zod date-format validation; ensure the CreateTripRequest schema name and the start_date/end_date property keys are updated consistently in both JSON and YAML before running the typegen.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@backend/docs/docs.go`:
- Around line 1628-1633: Add explicit "format: date" metadata to all date fields
and the query param so the OpenAPI spec marks them as dates: update the
struct/annotation definitions for models.CreateTripRequest.start_date,
models.CreateTripRequest.end_date, models.UpdateTripRequest.start_date,
models.UpdateTripRequest.end_date, models.Trip.start_date, models.Trip.end_date,
models.TripAPIResponse.start_date, models.TripAPIResponse.end_date to include
the OpenAPI format=date (e.g., via your project's Swagger/swag annotations or
struct tags for format) and update the handler/doc annotation for the
/api/v1/trips/{tripID}/activities query parameter named "date" to include
format: date; then regenerate the docs so the generated OpenAPI JSON/YAML
includes "type: string" and "format: date" for these fields.
In `@backend/docs/swagger.json`:
- Around line 195-451: The swagger docs are missing security declarations
because the handler comment blocks in
backend/internal/controllers/comment_reactions.go for AddReaction,
RemoveReaction, GetReactionSummary, and GetReactionUsers need an `@Security`
BearerAuth annotation; update each function's top-of-function swag comment (the
block that contains `@Summary/`@Description/@Router) to include a line "@Security
BearerAuth" so swag will generate the BearerAuth security requirement for those
endpoints.
In `@backend/docs/swagger.yaml`:
- Around line 570-576: The Trip schema fields start_date and end_date are
declared as type: string but lack a date format; update models.Trip,
models.TripAPIResponse, and models.UpdateTripRequest to mirror models.DateRange
by adding format: date (and optional example values) to both start_date and
end_date so API consumers know the expected YYYY-MM-DD date format; locate the
definitions for models.Trip, models.TripAPIResponse, and
models.UpdateTripRequest and add format: date under each start_date/end_date
entry (and add example: "2023-05-01" if desired) for consistency.
In `@backend/internal/migrations/20260401000000_add_trip_dates.sql`:
- Around line 2-4: Add a schema-level CHECK constraint to the ALTER TABLE
statement on trips to prevent invalid ranges; modify the migration that adds
start_date and end_date to also add a named constraint (e.g.,
trips_end_after_start_chk) such as CHECK (start_date IS NULL OR end_date IS NULL
OR end_date > start_date) so rows with both dates present must satisfy end_date
> start_date while allowing NULLs during migration.
In `@backend/internal/models/trips.go`:
- Around line 16-17: Replace the pointer time.Time fields StartDate and EndDate
in the Trips model with a custom Date type (e.g., type Date struct) that
serializes to/from "YYYY-MM-DD" for JSON and avoids timezone shifts; implement
json.Marshaler and json.Unmarshaler on that Date to emit/parse ISO date-only
strings, and also implement sql.Scanner and driver.Valuer so Bun can read/write
the DATE column; update all usages (StartDate, EndDate and any other trip/date
fields called out) to use *Date instead of *time.Time, matching the DateRange
string-style precedent in activity.go.
In `@backend/internal/services/trips.go`:
- Around line 230-232: The current validation only compares req.StartDate and
req.EndDate when both are present, so partial updates can break ordering; before
that check in trips.go, load the existing trip (e.g., via the service/repo
method used elsewhere such as GetByID/GetTrip) and merge current values with the
incoming request values (use existingTrip.StartDate/EndDate when req.StartDate
or req.EndDate is nil) and then validate that mergedStart and mergedEnd satisfy
mergedEnd.After(mergedStart); update the code paths that return errs.BadRequest
to use the merged dates so partial updates cannot produce end_date < start_date.
In `@frontend/schemas/modelsCommentReactionUser.json`:
- Line 4: The JSON schema for profile_picture_url currently requires a string
but the backend model uses a pointer (*string) allowing null; update the schema
entry for "profile_picture_url" in
frontend/schemas/modelsCommentReactionUser.json to accept nulls (e.g., make the
type allow "null" or set nullable true) so it matches
backend/internal/models/comment_reactions.go's *string behavior and prevents
validation errors from null API responses.
In `@frontend/schemas/modelsCreateActivityRequest.json`:
- Around line 45-59: Remove the redundant allOf wrapper and duplicated enum in
the time_of_day property: replace the current object that nests type/enum inside
allOf with a single schema entry that directly defines "type": "string", the
"enum": ["morning","afternoon","evening"], and the
x-enum-varnames/x-readme-ref-name metadata; apply the same change to the
corresponding time_of_day field in modelsUpdateActivityRequest.json so both
request schemas match the simpler pattern used by modelsActivity.json,
modelsActivityAPIResponse.json, modelsSearchActivitiesResult.json, and
modelsActivityCursorPageResult.json.
In `@frontend/schemas/modelsCreateTripRequest.json`:
- Around line 9-11: Update the JSON schema for trip date fields so they validate
ISO dates: modify the "start_date" and "end_date" properties in
modelsCreateTripRequest.json to include "format": "date" in addition to "type":
"string" (e.g., keep the "name" constraints unchanged) so the schema enforces
ISO date format validation for those fields.
---
Outside diff comments:
In `@backend/docs/swagger.json`:
- Around line 1593-1627: The OpenAPI schema is missing the date format for
date-typed fields; update the Go struct field annotations and operation param
docs to include format:"date" for the relevant fields: add the format tag for
the query parameter named "date" in the getActivitiesByTripID handler docs, and
add format:"date" to the struct tags for start_date and end_date on the Trip and
related models (e.g., the Trip struct and DateRange-related structs referenced
in swagger generation) so swag generates type: "string" with format: "date".
In `@frontend/types/schema.gen.ts`:
- Around line 1128-1136: The generated schema modelsCreateTripRequestSchema
allows invalid dates because start_date and end_date are plain strings in the
OpenAPI spec; update the upstream OpenAPI definitions for CreateTripRequest (and
any related trip schemas) in backend/docs/swagger.json and
backend/docs/swagger.yaml to add "format": "date" for the start_date and
end_date properties (matching the Go time.Time usage), then regenerate the
frontend types so modelsCreateTripRequestSchema (and related schemas) use zod
date-format validation; ensure the CreateTripRequest schema name and the
start_date/end_date property keys are updated consistently in both JSON and YAML
before running the typegen.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 224aa54e-55d3-46cf-bc4e-ca95a5293773
📒 Files selected for processing (33)
backend/docs/docs.gobackend/docs/swagger.jsonbackend/docs/swagger.yamlbackend/internal/migrations/20260401000000_add_trip_dates.sqlbackend/internal/models/trips.gobackend/internal/repository/trips.gobackend/internal/services/trips.gofrontend/api/activities/useGetActivitiesByTripID.tsfrontend/api/activities/useGetActivitiesByTripIDSuspense.tsfrontend/api/index.tsfrontend/index.tsfrontend/schemas/modelsActivity.jsonfrontend/schemas/modelsActivityAPIResponse.jsonfrontend/schemas/modelsActivityCursorPageResult.jsonfrontend/schemas/modelsActivityTimeOfDay.jsonfrontend/schemas/modelsCommentReaction.jsonfrontend/schemas/modelsCommentReactionSummary.jsonfrontend/schemas/modelsCommentReactionUser.jsonfrontend/schemas/modelsCommentReactionUsersResponse.jsonfrontend/schemas/modelsCommentReactionsSummaryResponse.jsonfrontend/schemas/modelsCreateActivityRequest.jsonfrontend/schemas/modelsCreateCommentReactionRequest.jsonfrontend/schemas/modelsCreateTripRequest.jsonfrontend/schemas/modelsDeleteCommentReactionRequest.jsonfrontend/schemas/modelsSearchActivitiesResult.jsonfrontend/schemas/modelsSearchTripsResult.jsonfrontend/schemas/modelsTrip.jsonfrontend/schemas/modelsTripAPIResponse.jsonfrontend/schemas/modelsTripCursorPageResult.jsonfrontend/schemas/modelsUpdateActivityRequest.jsonfrontend/schemas/modelsUpdateTripRequest.jsonfrontend/types/schema.gen.tsfrontend/types/types.gen.ts
| { | ||
| "type": "string", | ||
| "description": "Filter by calendar date (YYYY-MM-DD); activity must have a date range containing this day", | ||
| "name": "date", | ||
| "in": "query" | ||
| }, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify whether generated swagger marks trip/date filters as date-formatted.
python - <<'PY'
import json
from pathlib import Path
p = Path("backend/docs/swagger.json")
if not p.exists():
print("backend/docs/swagger.json not found")
raise SystemExit(0)
doc = json.loads(p.read_text())
checks = [
("definitions", "models.CreateTripRequest", "start_date"),
("definitions", "models.CreateTripRequest", "end_date"),
("definitions", "models.UpdateTripRequest", "start_date"),
("definitions", "models.UpdateTripRequest", "end_date"),
("definitions", "models.Trip", "start_date"),
("definitions", "models.Trip", "end_date"),
("definitions", "models.TripAPIResponse", "start_date"),
("definitions", "models.TripAPIResponse", "end_date"),
]
for _, model, field in checks:
prop = (
doc.get("definitions", {})
.get(model, {})
.get("properties", {})
.get(field)
)
if prop is None:
print(f"MISSING {model}.{field}")
continue
print(f"{model}.{field}: type={prop.get('type')} format={prop.get('format')}")
params = (
doc.get("paths", {})
.get("/api/v1/trips/{tripID}/activities", {})
.get("get", {})
.get("parameters", [])
)
for prm in params:
if prm.get("name") == "date":
print(f"query date param: type={prm.get('type')} format={prm.get('format')}")
PYRepository: GenerateNU/toggo
Length of output: 551
Add explicit date format to date fields in the OpenAPI specification.
The date-related fields in the API specification lack explicit format metadata. All instances of start_date, end_date, and the date query parameter are documented as plain strings without format: date. This omission weakens the API contract and can cause inconsistencies in SDK generation and client-side validation.
Update the source annotations or models to include format: date for these fields, then regenerate the documentation.
Affected fields:
models.CreateTripRequest.start_datemodels.CreateTripRequest.end_datemodels.UpdateTripRequest.start_datemodels.UpdateTripRequest.end_datemodels.Trip.start_datemodels.Trip.end_datemodels.TripAPIResponse.start_datemodels.TripAPIResponse.end_date/api/v1/trips/{tripID}/activitiesquery parameterdate
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@backend/docs/docs.go` around lines 1628 - 1633, Add explicit "format: date"
metadata to all date fields and the query param so the OpenAPI spec marks them
as dates: update the struct/annotation definitions for
models.CreateTripRequest.start_date, models.CreateTripRequest.end_date,
models.UpdateTripRequest.start_date, models.UpdateTripRequest.end_date,
models.Trip.start_date, models.Trip.end_date, models.TripAPIResponse.start_date,
models.TripAPIResponse.end_date to include the OpenAPI format=date (e.g., via
your project's Swagger/swag annotations or struct tags for format) and update
the handler/doc annotation for the /api/v1/trips/{tripID}/activities query
parameter named "date" to include format: date; then regenerate the docs so the
generated OpenAPI JSON/YAML includes "type: string" and "format: date" for these
fields.
| "/api/v1/comments/{commentID}/reactions": { | ||
| "get": { | ||
| "description": "Retrieves aggregated emoji reactions for a comment", | ||
| "produces": [ | ||
| "application/json" | ||
| ], | ||
| "tags": [ | ||
| "comment-reactions" | ||
| ], | ||
| "summary": "Get reactions summary for a comment", | ||
| "operationId": "getCommentReactionsSummary", | ||
| "parameters": [ | ||
| { | ||
| "type": "string", | ||
| "description": "Comment ID", | ||
| "name": "commentID", | ||
| "in": "path", | ||
| "required": true | ||
| } | ||
| ], | ||
| "responses": { | ||
| "200": { | ||
| "description": "OK", | ||
| "schema": { | ||
| "$ref": "#/definitions/models.CommentReactionsSummaryResponse" | ||
| } | ||
| }, | ||
| "400": { | ||
| "description": "Bad Request", | ||
| "schema": { | ||
| "$ref": "#/definitions/errs.APIError" | ||
| } | ||
| }, | ||
| "401": { | ||
| "description": "Unauthorized", | ||
| "schema": { | ||
| "$ref": "#/definitions/errs.APIError" | ||
| } | ||
| }, | ||
| "404": { | ||
| "description": "Not Found", | ||
| "schema": { | ||
| "$ref": "#/definitions/errs.APIError" | ||
| } | ||
| }, | ||
| "500": { | ||
| "description": "Internal Server Error", | ||
| "schema": { | ||
| "$ref": "#/definitions/errs.APIError" | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "post": { | ||
| "description": "Adds an emoji reaction to a comment", | ||
| "consumes": [ | ||
| "application/json" | ||
| ], | ||
| "produces": [ | ||
| "application/json" | ||
| ], | ||
| "tags": [ | ||
| "comment-reactions" | ||
| ], | ||
| "summary": "Add a reaction to a comment", | ||
| "operationId": "addCommentReaction", | ||
| "parameters": [ | ||
| { | ||
| "type": "string", | ||
| "description": "Comment ID", | ||
| "name": "commentID", | ||
| "in": "path", | ||
| "required": true | ||
| }, | ||
| { | ||
| "description": "Create reaction request", | ||
| "name": "request", | ||
| "in": "body", | ||
| "required": true, | ||
| "schema": { | ||
| "$ref": "#/definitions/models.CreateCommentReactionRequest" | ||
| } | ||
| } | ||
| ], | ||
| "responses": { | ||
| "201": { | ||
| "description": "Created", | ||
| "schema": { | ||
| "$ref": "#/definitions/models.CommentReaction" | ||
| } | ||
| }, | ||
| "400": { | ||
| "description": "Bad Request", | ||
| "schema": { | ||
| "$ref": "#/definitions/errs.APIError" | ||
| } | ||
| }, | ||
| "401": { | ||
| "description": "Unauthorized", | ||
| "schema": { | ||
| "$ref": "#/definitions/errs.APIError" | ||
| } | ||
| }, | ||
| "404": { | ||
| "description": "Not Found", | ||
| "schema": { | ||
| "$ref": "#/definitions/errs.APIError" | ||
| } | ||
| }, | ||
| "409": { | ||
| "description": "Conflict", | ||
| "schema": { | ||
| "$ref": "#/definitions/errs.APIError" | ||
| } | ||
| }, | ||
| "422": { | ||
| "description": "Unprocessable Entity", | ||
| "schema": { | ||
| "$ref": "#/definitions/errs.APIError" | ||
| } | ||
| }, | ||
| "500": { | ||
| "description": "Internal Server Error", | ||
| "schema": { | ||
| "$ref": "#/definitions/errs.APIError" | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "delete": { | ||
| "description": "Removes the current user's emoji reaction from a comment", | ||
| "consumes": [ | ||
| "application/json" | ||
| ], | ||
| "produces": [ | ||
| "application/json" | ||
| ], | ||
| "tags": [ | ||
| "comment-reactions" | ||
| ], | ||
| "summary": "Remove a reaction from a comment", | ||
| "operationId": "removeCommentReaction", | ||
| "parameters": [ | ||
| { | ||
| "type": "string", | ||
| "description": "Comment ID", | ||
| "name": "commentID", | ||
| "in": "path", | ||
| "required": true | ||
| }, | ||
| { | ||
| "description": "Delete reaction request", | ||
| "name": "request", | ||
| "in": "body", | ||
| "required": true, | ||
| "schema": { | ||
| "$ref": "#/definitions/models.DeleteCommentReactionRequest" | ||
| } | ||
| } | ||
| ], | ||
| "responses": { | ||
| "204": { | ||
| "description": "No Content" | ||
| }, | ||
| "400": { | ||
| "description": "Bad Request", | ||
| "schema": { | ||
| "$ref": "#/definitions/errs.APIError" | ||
| } | ||
| }, | ||
| "401": { | ||
| "description": "Unauthorized", | ||
| "schema": { | ||
| "$ref": "#/definitions/errs.APIError" | ||
| } | ||
| }, | ||
| "404": { | ||
| "description": "Not Found", | ||
| "schema": { | ||
| "$ref": "#/definitions/errs.APIError" | ||
| } | ||
| }, | ||
| "422": { | ||
| "description": "Unprocessable Entity", | ||
| "schema": { | ||
| "$ref": "#/definitions/errs.APIError" | ||
| } | ||
| }, | ||
| "500": { | ||
| "description": "Internal Server Error", | ||
| "schema": { | ||
| "$ref": "#/definitions/errs.APIError" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "/api/v1/comments/{commentID}/reactions/{emoji}/users": { | ||
| "get": { | ||
| "description": "Retrieves users who reacted with a specific emoji on a comment", | ||
| "produces": [ | ||
| "application/json" | ||
| ], | ||
| "tags": [ | ||
| "comment-reactions" | ||
| ], | ||
| "summary": "Get users who reacted with an emoji", | ||
| "operationId": "getCommentReactionUsers", | ||
| "parameters": [ | ||
| { | ||
| "type": "string", | ||
| "description": "Comment ID", | ||
| "name": "commentID", | ||
| "in": "path", | ||
| "required": true | ||
| }, | ||
| { | ||
| "type": "string", | ||
| "description": "Emoji (URL-encoded)", | ||
| "name": "emoji", | ||
| "in": "path", | ||
| "required": true | ||
| } | ||
| ], | ||
| "responses": { | ||
| "200": { | ||
| "description": "OK", | ||
| "schema": { | ||
| "$ref": "#/definitions/models.CommentReactionUsersResponse" | ||
| } | ||
| }, | ||
| "400": { | ||
| "description": "Bad Request", | ||
| "schema": { | ||
| "$ref": "#/definitions/errs.APIError" | ||
| } | ||
| }, | ||
| "401": { | ||
| "description": "Unauthorized", | ||
| "schema": { | ||
| "$ref": "#/definitions/errs.APIError" | ||
| } | ||
| }, | ||
| "404": { | ||
| "description": "Not Found", | ||
| "schema": { | ||
| "$ref": "#/definitions/errs.APIError" | ||
| } | ||
| }, | ||
| "500": { | ||
| "description": "Internal Server Error", | ||
| "schema": { | ||
| "$ref": "#/definitions/errs.APIError" | ||
| } | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Check the comment_reactions controller to verify auth enforcement
fd -t f "comment_reactions.go" backend/Repository: GenerateNU/toggo
Length of output: 250
🏁 Script executed:
# Search for security declarations in swagger.json
rg '"security"' backend/docs/swagger.json | head -20Repository: GenerateNU/toggo
Length of output: 149
🏁 Script executed:
# Check if other endpoints use security declarations
rg -A 3 'operationId.*:' backend/docs/swagger.json | grep -A 3 'security' | head -30Repository: GenerateNU/toggo
Length of output: 42
🏁 Script executed:
# Look for patterns of existing protected endpoints in swagger.json
rg -B 5 '"401"' backend/docs/swagger.json | grep -E '(operationId|security)' | head -40Repository: GenerateNU/toggo
Length of output: 42
🏁 Script executed:
# Read the comment reactions controller
cat -n backend/internal/controllers/comment_reactions.go | head -100Repository: GenerateNU/toggo
Length of output: 3892
🏁 Script executed:
# Get more context on security declarations in swagger.json
rg -B 10 '"security"' backend/docs/swagger.json | head -60Repository: GenerateNU/toggo
Length of output: 1093
🏁 Script executed:
# Search for endpoints that protect with 401 and use security
rg -A 20 'operationId.*Comment' backend/docs/swagger.json | grep -E '(operationId|"security"|"401")' | head -40Repository: GenerateNU/toggo
Length of output: 515
🏁 Script executed:
# Check a known protected endpoint to see security pattern
rg -B 5 -A 25 'operationId.*:.*createUser' backend/docs/swagger.jsonRepository: GenerateNU/toggo
Length of output: 1185
🏁 Script executed:
# Check rest of comment_reactions.go for `@Security` annotations
cat -n backend/internal/controllers/comment_reactions.go | grep -E '(@|func)' | head -30Repository: GenerateNU/toggo
Length of output: 1807
🏁 Script executed:
# Get the full security block structure and definition in swagger.json
rg -A 5 '"security": \[' backend/docs/swagger.json | head -40Repository: GenerateNU/toggo
Length of output: 1042
🏁 Script executed:
# Check if BearerAuth is defined in the spec
rg -A 5 'securityDefinitions|BearerAuth|bearer' backend/docs/swagger.json | head -50Repository: GenerateNU/toggo
Length of output: 1093
🏁 Script executed:
# Look at a comment endpoint that doesn't have reactions to see if it has security
rg -A 30 'operationId.*createComment' backend/docs/swagger.json | head -50Repository: GenerateNU/toggo
Length of output: 1263
🏁 Script executed:
# Check if createComment in swagger.json has security declaration
rg -B 10 'operationId.*createComment' backend/docs/swagger.json | grep -E '(security|operationId)' | head -10Repository: GenerateNU/toggo
Length of output: 107
🏁 Script executed:
# Check the RemoveReaction handler to verify auth enforcement
sed -n '92,120p' backend/internal/controllers/comment_reactions.goRepository: GenerateNU/toggo
Length of output: 761
🏁 Script executed:
# Look for GetCommentReactionsSummary to verify auth there too
rg -A 25 'GetCommentReactionsSummary|getSummary' backend/internal/controllers/comment_reactions.go | head -40Repository: GenerateNU/toggo
Length of output: 42
🏁 Script executed:
# Find GetCommentReactionsSummary or equivalent in the controller
rg -n 'Summary|Get.*Reaction' backend/internal/controllers/comment_reactions.go | head -20Repository: GenerateNU/toggo
Length of output: 742
🏁 Script executed:
# Get the full file to see all handlers
wc -l backend/internal/controllers/comment_reactions.goRepository: GenerateNU/toggo
Length of output: 113
🏁 Script executed:
# Read more of the file to find the summary handler
sed -n '100,180p' backend/internal/controllers/comment_reactions.goRepository: GenerateNU/toggo
Length of output: 2608
🏁 Script executed:
# Check if createComment handler also enforces auth
rg -A 30 'func.*CreateComment' backend/internal/controllers/comment.go | head -50Repository: GenerateNU/toggo
Length of output: 139
🏁 Script executed:
# Verify the swagger definitions section has BearerAuth defined
rg -A 10 'securityDefinitions' backend/docs/swagger.json | head -20Repository: GenerateNU/toggo
Length of output: 42
🏁 Script executed:
# Find the comment controller file
fd -t f 'comment.*\.go' backend/internal/controllers/ | head -10Repository: GenerateNU/toggo
Length of output: 150
🏁 Script executed:
# Search for createComment in controllers directory
rg -l 'createComment|CreateComment' backend/internal/controllers/Repository: GenerateNU/toggo
Length of output: 150
🏁 Script executed:
# Check swagger.json for securityDefinitions
rg 'securityDefinitions|swagger|version' backend/docs/swagger.json | head -10Repository: GenerateNU/toggo
Length of output: 106
🏁 Script executed:
# Check comments.go for CreateComment handler and its `@Security` annotation
rg -A 30 '@Summary.*[Cc]reate.*comment|func.*CreateComment' backend/internal/controllers/comments.go | head -50Repository: GenerateNU/toggo
Length of output: 1360
🏁 Script executed:
# Check if any handlers in comments.go have `@Security` annotations
rg '@Security' backend/internal/controllers/comments.goRepository: GenerateNU/toggo
Length of output: 42
🏁 Script executed:
# Check comment_reactions.go for `@Security` annotations
rg '@Security' backend/internal/controllers/comment_reactions.goRepository: GenerateNU/toggo
Length of output: 42
Add @Security BearerAuth annotations to the comment reaction handler functions in the source code.
All three comment reaction handlers (AddReaction, RemoveReaction, GetReactionSummary, GetReactionUsers) enforce authentication by checking c.Locals("userID") and returning 401 when it is absent. However, the swagger annotations lack @Security BearerAuth, so the generated swagger.json does not declare security requirements. This causes Swagger UI and generated API clients to treat these endpoints as public. The fix must be applied to the Go handler comments in backend/internal/controllers/comment_reactions.go where the swag tool will pick up the annotation during code generation.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@backend/docs/swagger.json` around lines 195 - 451, The swagger docs are
missing security declarations because the handler comment blocks in
backend/internal/controllers/comment_reactions.go for AddReaction,
RemoveReaction, GetReactionSummary, and GetReactionUsers need an `@Security`
BearerAuth annotation; update each function's top-of-function swag comment (the
block that contains `@Summary/`@Description/@Router) to include a line "@Security
BearerAuth" so swag will generate the BearerAuth security requirement for those
endpoints.
| end_date: | ||
| type: string | ||
| name: | ||
| minLength: 1 | ||
| type: string | ||
| start_date: | ||
| type: string |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Trip date fields lack format specification.
The start_date and end_date fields are typed as plain string without a format: date annotation. Compare with models.DateRange (lines 596-608) which specifies format: date and includes example values. This inconsistency may confuse API consumers about the expected date format.
Proposed fix
end_date:
+ description: ISO 8601 date format (YYYY-MM-DD)
+ example: "2024-01-15"
+ format: date
type: string
name:
minLength: 1
type: string
start_date:
+ description: ISO 8601 date format (YYYY-MM-DD)
+ example: "2024-01-01"
+ format: date
type: stringApply similar changes to models.Trip, models.TripAPIResponse, and models.UpdateTripRequest for consistency.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| end_date: | |
| type: string | |
| name: | |
| minLength: 1 | |
| type: string | |
| start_date: | |
| type: string | |
| end_date: | |
| description: ISO 8601 date format (YYYY-MM-DD) | |
| example: "2024-01-15" | |
| format: date | |
| type: string | |
| name: | |
| minLength: 1 | |
| type: string | |
| start_date: | |
| description: ISO 8601 date format (YYYY-MM-DD) | |
| example: "2024-01-01" | |
| format: date | |
| type: string |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@backend/docs/swagger.yaml` around lines 570 - 576, The Trip schema fields
start_date and end_date are declared as type: string but lack a date format;
update models.Trip, models.TripAPIResponse, and models.UpdateTripRequest to
mirror models.DateRange by adding format: date (and optional example values) to
both start_date and end_date so API consumers know the expected YYYY-MM-DD date
format; locate the definitions for models.Trip, models.TripAPIResponse, and
models.UpdateTripRequest and add format: date under each start_date/end_date
entry (and add example: "2023-05-01" if desired) for consistency.
| ALTER TABLE trips | ||
| ADD COLUMN start_date DATE, | ||
| ADD COLUMN end_date DATE; |
There was a problem hiding this comment.
Enforce date-range integrity in the database, not only in service logic.
end_date > start_date is currently not protected at the schema level. Add a CHECK constraint so invalid ranges cannot be inserted outside the service path.
Proposed fix
ALTER TABLE trips
ADD COLUMN start_date DATE,
-ADD COLUMN end_date DATE;
+ADD COLUMN end_date DATE,
+ADD CONSTRAINT trips_date_range_check
+ CHECK (start_date IS NULL OR end_date IS NULL OR end_date > start_date);
CREATE INDEX idx_trips_dates ON trips(start_date, end_date);
-- +goose Down
DROP INDEX IF EXISTS idx_trips_dates;
+ALTER TABLE trips DROP CONSTRAINT IF EXISTS trips_date_range_check;
ALTER TABLE trips DROP COLUMN IF EXISTS end_date;
ALTER TABLE trips DROP COLUMN IF EXISTS start_date;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@backend/internal/migrations/20260401000000_add_trip_dates.sql` around lines 2
- 4, Add a schema-level CHECK constraint to the ALTER TABLE statement on trips
to prevent invalid ranges; modify the migration that adds start_date and
end_date to also add a named constraint (e.g., trips_end_after_start_chk) such
as CHECK (start_date IS NULL OR end_date IS NULL OR end_date > start_date) so
rows with both dates present must satisfy end_date > start_date while allowing
NULLs during migration.
There was a problem hiding this comment.
@aahiltn, understood. The service-layer validation in trips.go will continue to enforce the date ordering. No changes needed.
| StartDate *time.Time `bun:"start_date" json:"start_date,omitempty"` | ||
| EndDate *time.Time `bun:"end_date" json:"end_date,omitempty"` |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
In Go, how does encoding/json marshal time.Time by default, and what is the recommended approach for date-only (YYYY-MM-DD) API fields to avoid timezone day shifts?
💡 Result:
By default, encoding/json marshals time.Time to a quoted string in RFC 3339 format (e.g., "2006-01-02T15:04:05Z" or with nanoseconds and timezone offset if present), via time.Time's MarshalJSON method which uses time.RFC3339Nano but trims trailing zeros in fractional seconds. For date-only (YYYY-MM-DD) API fields, use a custom type wrapping time.Time that implements json.Marshaler and json.Unmarshaler, formatting to/from "2006-01-02" in UTC to avoid timezone-induced day shifts. Example: type Date struct { time.Time } func (d Date) MarshalJSON ([]byte, error) { return json.Marshal(d.Time.UTC.Format("2006-01-02")) } func (d *Date) UnmarshalJSON(data []byte) error { var s string if err := json.Unmarshal(data, &s); err != nil { return err } t, err := time.Parse("2006-01-02", s) if err != nil { return err } d.Time = t return nil } Use as DateField Date json:"date_field" in structs. This ensures consistent date representation regardless of the original time.Time's location, preventing day boundary issues from timezone offsets.
Citations:
- 1: https://stackoverflow.com/questions/30413324/golang-json-time-default-layout-varies-by-platform
- 2: https://pkg.go.dev/encoding/json@go1.25.6
- 3: https://stackoverflow.com/questions/20475321/override-the-layout-used-by-json-marshal-to-format-time-time
- 4: https://www.willem.dev/articles/change-time-format-json/
- 5: https://stackoverflow.com/questions/23695479/how-to-format-timestamp-in-outgoing-json
- 6: https://golang.org/src/time/time.go
- 7: https://go.dev/src/time/format_rfc3339.go
🏁 Script executed:
# First, examine the trips.go file to verify the structure at specified lines
head -100 backend/internal/models/trips.go | cat -nRepository: GenerateNU/toggo
Length of output: 4052
🏁 Script executed:
# Search for any existing date-only types or custom date handling in the codebase
fd -e go . backend --type f --exec rg -l "type.*Date|MarshalJSON|UnmarshalJSON" {} \; | head -20Repository: GenerateNU/toggo
Length of output: 95
🏁 Script executed:
# Check if there are any custom time-related types already defined
rg "type.*time\.Time" backend --type go -A 2 | head -50Repository: GenerateNU/toggo
Length of output: 42
🏁 Script executed:
# Check the activity.go file for any date-related patterns
cat backend/internal/models/activity.go | grep -A 5 -B 5 "Date\|MarshalJSON\|UnmarshalJSON" | head -40Repository: GenerateNU/toggo
Length of output: 2032
🏁 Script executed:
# Search more broadly for any custom types that might handle dates
rg "type\s+\w+\s+struct" backend --type go -A 10 | grep -B 5 -A 5 "Date\|time" | head -80Repository: GenerateNU/toggo
Length of output: 5643
🏁 Script executed:
# Check if there are any custom marshaling implementations in the entire codebase
find backend -name "*.go" -type f -exec rg -l "MarshalJSON|UnmarshalJSON" {} \;Repository: GenerateNU/toggo
Length of output: 42
🏁 Script executed:
# Check the database schema or migrations to understand how dates are stored
find . -name "*.go" -path "*/migrations/*" -o -name "*migration*" | head -10Repository: GenerateNU/toggo
Length of output: 130
🏁 Script executed:
# Check the migration files to see how dates are stored in the database
ls -la backend/internal/migrations/ | head -20Repository: GenerateNU/toggo
Length of output: 1644
🏁 Script executed:
# Look at the migration schema for the trips table
rg "trips\|start_date\|end_date" backend/internal/migrations/ --type go -B 3 -A 3 | head -80Repository: GenerateNU/toggo
Length of output: 42
🏁 Script executed:
# Check if there's any custom date handling in the database layer or handlers
rg "StartDate\|EndDate" backend/internal --type go -B 2 -A 2 | grep -v "test\|mock" | head -100Repository: GenerateNU/toggo
Length of output: 42
🏁 Script executed:
# Check the create_trip.sql migration to see the schema
cat backend/internal/migrations/20260123213356_create_trip.sqlRepository: GenerateNU/toggo
Length of output: 999
🏁 Script executed:
# Look for any API handlers or services that use StartDate/EndDate
find backend -name "*.go" -type f -exec grep -l "StartDate\|EndDate" {} \; | grep -v mock | grep -v testRepository: GenerateNU/toggo
Length of output: 164
🏁 Script executed:
# Check one of the handlers to see how these dates are processed
rg "StartDate|EndDate" backend/internal/handlers --type go -B 5 -A 5 | head -50Repository: GenerateNU/toggo
Length of output: 125
🏁 Script executed:
# List the backend structure to find where handlers/routes are
ls -la backend/internal/ | grep -v totalRepository: GenerateNU/toggo
Length of output: 1205
🏁 Script executed:
# Search for HTTP handlers or routes that might use StartDate/EndDate
find backend -name "*.go" -type f -exec grep -l "CreateTrip\|UpdateTrip\|POST\|PUT" {} \; | head -10Repository: GenerateNU/toggo
Length of output: 1151
🏁 Script executed:
# Check the routes file if it exists
find backend -name "*route*" -o -name "*handler*" | head -10Repository: GenerateNU/toggo
Length of output: 172
🏁 Script executed:
# Look at the trips service to understand how dates are used
head -150 backend/internal/services/trips.go | cat -nRepository: GenerateNU/toggo
Length of output: 5475
🏁 Script executed:
# Check if there are other migrations that add start_date and end_date to trips
ls -1 backend/internal/migrations/ | xargs -I {} sh -c 'grep -l "start_date\|end_date\|alter.*trips" backend/internal/migrations/{} 2>/dev/null'Repository: GenerateNU/toggo
Length of output: 123
🏁 Script executed:
# Check the trip repository to see how dates are queried/stored
cat backend/internal/repository/trips.go | head -100Repository: GenerateNU/toggo
Length of output: 3452
🏁 Script executed:
# Look at the controllers to see how the API returns dates
grep -A 20 "CreateTrip\|UpdateTrip" backend/internal/controllers/trips.go | head -60Repository: GenerateNU/toggo
Length of output: 1897
🏁 Script executed:
# Check the migration file that adds trip dates
cat backend/internal/migrations/20260401000000_add_trip_dates.sqlRepository: GenerateNU/toggo
Length of output: 362
🏁 Script executed:
# Look for any test files that show how dates are being used/expected
find backend -name "*trip*test*" -o -name "*test*trip*" | head -5Repository: GenerateNU/toggo
Length of output: 144
🏁 Script executed:
# Check if there's a utility or helper for date handling
rg "date\|Date" backend/internal/utilities --type go -lRepository: GenerateNU/toggo
Length of output: 42
🏁 Script executed:
# Check the trips test file to see how dates are being tested
cat backend/internal/tests/trips_test.go | head -150Repository: GenerateNU/toggo
Length of output: 3185
🏁 Script executed:
# Search for any JSON marshaling or API tests that show the actual output format
rg "start_date\|end_date" backend/internal/tests --type go -B 3 -A 3 | head -60Repository: GenerateNU/toggo
Length of output: 42
🏁 Script executed:
# Check if there's any documentation or API examples that show expected date format
find . -name "*.md" -o -name "*.yaml" -o -name "*.yml" | xargs grep -l "start_date\|end_date" 2>/dev/null | head -5Repository: GenerateNU/toggo
Length of output: 87
🏁 Script executed:
# Look at the OpenAPI/Swagger docs if available
head -200 backend/docs/docs.go | grep -A 5 -B 5 "start_date\|end_date"Repository: GenerateNU/toggo
Length of output: 42
🏁 Script executed:
# Check if there are any integration tests or examples that show actual JSON output
find . -name "*.json" -o -name "examples*" | head -10Repository: GenerateNU/toggo
Length of output: 425
🏁 Script executed:
# Check the swagger documentation for start_date and end_date format
grep -A 10 -B 5 "start_date\|end_date" backend/docs/swagger.yaml | head -60Repository: GenerateNU/toggo
Length of output: 1141
🏁 Script executed:
# Also check swagger.json
grep -A 5 -B 5 "start_date" backend/docs/swagger.json | head -40Repository: GenerateNU/toggo
Length of output: 1099
🏁 Script executed:
# Look for DateRange pattern from activity.go in the models again to understand if it's used
rg "DateRange" backend/internal --type go -B 2 -A 5Repository: GenerateNU/toggo
Length of output: 6909
Use a date-only type for start_date and end_date to prevent timezone day shifts in API responses.
The database schema stores these as DATE type, but the model uses *time.Time. Go's default JSON marshaling converts time.Time to RFC 3339 format (e.g., "2006-01-02T15:04:05Z07:00"), which can shift the calendar day by one due to timezone offset. The codebase already has a precedent for this: the DateRange type in activity.go uses string fields with ISO 8601 date format. Create a custom Date type with json.Marshaler and json.Unmarshaler implementations to serialize/deserialize as "YYYY-MM-DD" in UTC.
Affects lines 16-17, 28-29, 38-39, 68-69, 81-82.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@backend/internal/models/trips.go` around lines 16 - 17, Replace the pointer
time.Time fields StartDate and EndDate in the Trips model with a custom Date
type (e.g., type Date struct) that serializes to/from "YYYY-MM-DD" for JSON and
avoids timezone shifts; implement json.Marshaler and json.Unmarshaler on that
Date to emit/parse ISO date-only strings, and also implement sql.Scanner and
driver.Valuer so Bun can read/write the DATE column; update all usages
(StartDate, EndDate and any other trip/date fields called out) to use *Date
instead of *time.Time, matching the DateRange string-style precedent in
activity.go.
| if req.StartDate != nil && req.EndDate != nil && !req.EndDate.After(*req.StartDate) { | ||
| return nil, errs.BadRequest(errors.New("end date must be after start date")) | ||
| } |
There was a problem hiding this comment.
Partial update may violate date ordering constraint.
This validation only checks when both StartDate and EndDate are provided in the update request. A partial update could set end_date before an existing start_date (or vice versa) because the service does not fetch the current trip values to cross-validate.
Example: Trip has start_date=2026-04-10. User sends end_date=2026-04-05. Validation passes since req.StartDate is nil, resulting in end_date < start_date in the database.
Proposed fix
Fetch the existing trip before validation and merge with request values:
+ // Fetch existing trip for cross-validation of partial updates
+ existingTrip, err := s.Trip.Find(ctx, tripID)
+ if err != nil {
+ return nil, err
+ }
+
+ effectiveStartDate := existingTrip.StartDate
+ if req.StartDate != nil {
+ effectiveStartDate = req.StartDate
+ }
+ effectiveEndDate := existingTrip.EndDate
+ if req.EndDate != nil {
+ effectiveEndDate = req.EndDate
+ }
+
+ if effectiveStartDate != nil && effectiveEndDate != nil && !effectiveEndDate.After(*effectiveStartDate) {
- if req.StartDate != nil && req.EndDate != nil && !req.EndDate.After(*req.StartDate) {
return nil, errs.BadRequest(errors.New("end date must be after start date"))
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@backend/internal/services/trips.go` around lines 230 - 232, The current
validation only compares req.StartDate and req.EndDate when both are present, so
partial updates can break ordering; before that check in trips.go, load the
existing trip (e.g., via the service/repo method used elsewhere such as
GetByID/GetTrip) and merge current values with the incoming request values (use
existingTrip.StartDate/EndDate when req.StartDate or req.EndDate is nil) and
then validate that mergedStart and mergedEnd satisfy
mergedEnd.After(mergedStart); update the code paths that return errs.BadRequest
to use the merged dates so partial updates cannot produce end_date < start_date.
| { | ||
| "type": "object", | ||
| "properties": { | ||
| "profile_picture_url": { "type": "string" }, |
There was a problem hiding this comment.
Allow profile_picture_url to be nullable to match backend responses.
Line 4 currently requires a string, but backend/internal/models/comment_reactions.go uses *string for profile_picture_url. A null value from the API will violate this schema.
Proposed fix
- "profile_picture_url": { "type": "string" },
+ "profile_picture_url": { "anyOf": [{ "type": "string" }, { "type": "null" }] },📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "profile_picture_url": { "type": "string" }, | |
| "profile_picture_url": { "anyOf": [{ "type": "string" }, { "type": "null" }] }, |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@frontend/schemas/modelsCommentReactionUser.json` at line 4, The JSON schema
for profile_picture_url currently requires a string but the backend model uses a
pointer (*string) allowing null; update the schema entry for
"profile_picture_url" in frontend/schemas/modelsCommentReactionUser.json to
accept nulls (e.g., make the type allow "null" or set nullable true) so it
matches backend/internal/models/comment_reactions.go's *string behavior and
prevents validation errors from null API responses.
| "time_of_day": { | ||
| "enum": ["morning", "afternoon", "evening"], | ||
| "allOf": [ | ||
| { | ||
| "type": "string", | ||
| "enum": ["morning", "afternoon", "evening"], | ||
| "x-enum-varnames": [ | ||
| "ActivityTimeOfDayMorning", | ||
| "ActivityTimeOfDayAfternoon", | ||
| "ActivityTimeOfDayEvening" | ||
| ], | ||
| "x-readme-ref-name": "models.ActivityTimeOfDay" | ||
| } | ||
| ] | ||
| }, |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if other activity request schemas use the same allOf pattern
fd -e json . frontend/schemas | xargs grep -l "time_of_day" | xargs grep -l "allOf" 2>/dev/null || echo "No other schemas use allOf for time_of_day"
# Compare structure in update request schema
cat frontend/schemas/modelsUpdateActivityRequest.json 2>/dev/null | grep -A 15 "time_of_day" || echo "modelsUpdateActivityRequest.json not found or no time_of_day field"Repository: GenerateNU/toggo
Length of output: 593
🏁 Script executed:
#!/bin/bash
# Check the time_of_day structure in modelsActivity.json
echo "=== modelsActivity.json time_of_day ==="
fd -e json -name "modelsActivity.json" frontend/schemas -exec cat {} \; 2>/dev/null | grep -A 15 "time_of_day" || echo "Not found"
echo -e "\n=== modelsSearchActivitiesResult.json time_of_day ==="
fd -e json -name "modelsSearchActivitiesResult.json" frontend/schemas -exec cat {} \; 2>/dev/null | grep -A 15 "time_of_day" || echo "Not found"
echo -e "\n=== List all JSON schema files with 'Activity' in name ==="
fd -e json -name "*Activity*.json" frontend/schemasRepository: GenerateNU/toggo
Length of output: 482
🏁 Script executed:
#!/bin/bash
# Fix fd syntax - look for files with Activity in the name
echo "=== All Activity-related JSON files in frontend/schemas ==="
fd "Activity" frontend/schemas --type f --extension json
echo -e "\n=== Search for all time_of_day occurrences in frontend/schemas ==="
rg "time_of_day" frontend/schemas -A 12Repository: GenerateNU/toggo
Length of output: 7128
Remove unnecessary allOf wrapper and deduplicate enum in time_of_day field.
The time_of_day field uses an allOf wrapper with the enum duplicated at lines 46 and 50. Other activity schemas—modelsActivity.json, modelsActivityAPIResponse.json, modelsSearchActivitiesResult.json, and modelsActivityCursorPageResult.json—all define this field with a simpler structure that omits allOf. Align the request schema with this pattern to maintain consistency:
Proposed simplified structure
"time_of_day": {
- "enum": ["morning", "afternoon", "evening"],
- "allOf": [
- {
- "type": "string",
- "enum": ["morning", "afternoon", "evening"],
- "x-enum-varnames": [
- "ActivityTimeOfDayMorning",
- "ActivityTimeOfDayAfternoon",
- "ActivityTimeOfDayEvening"
- ],
- "x-readme-ref-name": "models.ActivityTimeOfDay"
- }
- ]
+ "type": "string",
+ "enum": ["morning", "afternoon", "evening"],
+ "x-enum-varnames": [
+ "ActivityTimeOfDayMorning",
+ "ActivityTimeOfDayAfternoon",
+ "ActivityTimeOfDayEvening"
+ ],
+ "x-readme-ref-name": "models.ActivityTimeOfDay"
},Note: modelsUpdateActivityRequest.json uses the same allOf pattern and should be updated identically.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "time_of_day": { | |
| "enum": ["morning", "afternoon", "evening"], | |
| "allOf": [ | |
| { | |
| "type": "string", | |
| "enum": ["morning", "afternoon", "evening"], | |
| "x-enum-varnames": [ | |
| "ActivityTimeOfDayMorning", | |
| "ActivityTimeOfDayAfternoon", | |
| "ActivityTimeOfDayEvening" | |
| ], | |
| "x-readme-ref-name": "models.ActivityTimeOfDay" | |
| } | |
| ] | |
| }, | |
| "time_of_day": { | |
| "type": "string", | |
| "enum": ["morning", "afternoon", "evening"], | |
| "x-enum-varnames": [ | |
| "ActivityTimeOfDayMorning", | |
| "ActivityTimeOfDayAfternoon", | |
| "ActivityTimeOfDayEvening" | |
| ], | |
| "x-readme-ref-name": "models.ActivityTimeOfDay" | |
| }, |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@frontend/schemas/modelsCreateActivityRequest.json` around lines 45 - 59,
Remove the redundant allOf wrapper and duplicated enum in the time_of_day
property: replace the current object that nests type/enum inside allOf with a
single schema entry that directly defines "type": "string", the "enum":
["morning","afternoon","evening"], and the x-enum-varnames/x-readme-ref-name
metadata; apply the same change to the corresponding time_of_day field in
modelsUpdateActivityRequest.json so both request schemas match the simpler
pattern used by modelsActivity.json, modelsActivityAPIResponse.json,
modelsSearchActivitiesResult.json, and modelsActivityCursorPageResult.json.
| "end_date": { "type": "string" }, | ||
| "name": { "type": "string", "minLength": 1 }, | ||
| "start_date": { "type": "string" } |
There was a problem hiding this comment.
Constrain trip date fields to ISO date format in the schema.
Lines 9 and 11 should use format: "date"; currently any string passes schema validation.
Proposed fix
- "end_date": { "type": "string" },
+ "end_date": { "type": "string", "format": "date" },
@@
- "start_date": { "type": "string" }
+ "start_date": { "type": "string", "format": "date" }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@frontend/schemas/modelsCreateTripRequest.json` around lines 9 - 11, Update
the JSON schema for trip date fields so they validate ISO dates: modify the
"start_date" and "end_date" properties in modelsCreateTripRequest.json to
include "format": "date" in addition to "type": "string" (e.g., keep the "name"
constraints unchanged) so the schema enforces ISO date format validation for
those fields.
There was a problem hiding this comment.
@coderabbitai What is the established pattern? Do other dates currently use string? Or stricter validation?
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check how date fields are defined across all frontend schema files
rg -n '"date"' frontend/schemas/ --type json -C2
echo "---"
# Also check for format: date usage
rg -n 'format' frontend/schemas/ --type json -C2
echo "---"
# Check other date fields like created_at, updated_at
rg -n 'created_at|updated_at|_date' frontend/schemas/ --type json -C1
Length of output: 30913
@aahiltn, the pattern is clear and consistent. Every date-only field in this codebase (e.g., activity start/end ranges in modelsDateRange.json, modelsActivity.json, modelsCreateActivityRequest.json, etc.) uses the stricter form:
{
"description": "ISO 8601 date format (YYYY-MM-DD)",
"type": "string",
"format": "date",
"example": "2024-01-01"
}Plain { "type": "string" } is only used for timestamp fields like created_at and updated_at.
The new start_date/end_date fields in modelsCreateTripRequest.json (and the same fields added to modelsUpdateTripRequest.json, modelsTrip.json, modelsTripAPIResponse.json, modelsSearchTripsResult.json, modelsTripCursorPageResult.json) are inconsistent with this established pattern. The fix applies across all six of those files:
"end_date": {
"description": "ISO 8601 date format (YYYY-MM-DD)",
"type": "string",
"format": "date",
"example": "2024-01-05"
},
"start_date": {
"description": "ISO 8601 date format (YYYY-MM-DD)",
"type": "string",
"format": "date",
"example": "2024-01-01"
}🧠 Learnings used
Learnt from: in-mai-space
Repo: GenerateNU/toggo PR: 100
File: frontend/schemas/modelsUpdateUserRequest.json:6-6
Timestamp: 2026-01-27T23:34:50.227Z
Learning: In the frontend of the toggo project, timezone values are automatically retrieved from device settings using `Intl.DateTimeFormat().resolvedOptions().timeZone` rather than being user-entered, so client-side schema validation for timezone format is not critical since the browser API returns valid IANA timezone strings.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@backend/internal/tests/trips_test.go`:
- Around line 530-548: The test currently only checks for existence of
"start_date" and "end_date" after creating a trip; update the assertions to
verify the actual values match the input payload (similar to TestTripCurrency).
After you create the trip and capture tripID (resp["id"]), in the GET request
chain (the testkit.New(...).Request(...).AssertStatus(...)) replace or augment
AssertFieldExists("start_date")/AssertFieldExists("end_date") with
AssertField("start_date", expectedStart) and AssertField("end_date",
expectedEnd), where expectedStart/expectedEnd are the original date strings used
when calling the creation endpoint (or extracted from the creation request
variables), so the GET response is validated against the exact expected values.
- Around line 609-625: Add a new subtest in trips_test.go (similar to the
existing t.Run "end date before start date is rejected on create") that
constructs a CreateTripRequest where StartDate and EndDate are the same (set
both to startDate), sends the POST to "/api/v1/trips" via
testkit.New(...).Request(...), and asserts http.StatusBadRequest; also assert
the validation error message contains "end date must be after start date" to
document that same-day trips are intentionally rejected.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 06629ed1-8ec3-4dd9-bf61-ddf918bc4cc9
📒 Files selected for processing (1)
backend/internal/tests/trips_test.go
| }). | ||
| AssertStatus(http.StatusCreated). | ||
| AssertFieldExists("start_date"). | ||
| AssertFieldExists("end_date"). | ||
| GetBody() | ||
|
|
||
| tripID := resp["id"].(string) | ||
|
|
||
| // Dates persist on GET | ||
| testkit.New(t). | ||
| Request(testkit.Request{ | ||
| App: app, | ||
| Route: fmt.Sprintf("/api/v1/trips/%s", tripID), | ||
| Method: testkit.GET, | ||
| UserID: &ownerID, | ||
| }). | ||
| AssertStatus(http.StatusOK). | ||
| AssertFieldExists("start_date"). | ||
| AssertFieldExists("end_date") |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Consider asserting actual date values, not just field existence.
The test verifies that start_date and end_date fields exist but does not confirm the returned values match the input. A serialization or storage bug could produce incorrect dates while this test passes. Compare with TestTripCurrency which asserts specific values like AssertField("currency", "EUR").
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@backend/internal/tests/trips_test.go` around lines 530 - 548, The test
currently only checks for existence of "start_date" and "end_date" after
creating a trip; update the assertions to verify the actual values match the
input payload (similar to TestTripCurrency). After you create the trip and
capture tripID (resp["id"]), in the GET request chain (the
testkit.New(...).Request(...).AssertStatus(...)) replace or augment
AssertFieldExists("start_date")/AssertFieldExists("end_date") with
AssertField("start_date", expectedStart) and AssertField("end_date",
expectedEnd), where expectedStart/expectedEnd are the original date strings used
when calling the creation endpoint (or extracted from the creation request
variables), so the GET response is validated against the exact expected values.
| t.Run("end date before start date is rejected on create", func(t *testing.T) { | ||
| testkit.New(t). | ||
| Request(testkit.Request{ | ||
| App: app, | ||
| Route: "/api/v1/trips", | ||
| Method: testkit.POST, | ||
| UserID: &ownerID, | ||
| Body: models.CreateTripRequest{ | ||
| Name: "Bad Date Trip", | ||
| BudgetMin: 100, | ||
| BudgetMax: 500, | ||
| StartDate: &endDate, // end before start | ||
| EndDate: &startDate, | ||
| }, | ||
| }). | ||
| AssertStatus(http.StatusBadRequest) | ||
| }) |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for the date validation logic in the service
ast-grep --pattern $'if $_ != nil && $_ != nil && !$_.After($_) {
$$$
}'Repository: GenerateNU/toggo
Length of output: 628
🏁 Script executed:
# Search for tests that might cover same-day or equal-date scenarios
rg -A 5 -B 5 "StartDate.*EndDate|EndDate.*StartDate" backend/internal/tests/trips_test.goRepository: GenerateNU/toggo
Length of output: 42
🏁 Script executed:
# Check if there are any tests with equal dates (dates on same day)
rg "StartDate.*EndDate\s*\}" backend/internal/tests/trips_test.go -A 2 -B 2Repository: GenerateNU/toggo
Length of output: 42
🏁 Script executed:
# Look for any spec or requirements files that define trip date behavior
fd -e md -e txt -e go | xargs rg -l "same.day|same-day|equal.*date" 2>/dev/null | head -20Repository: GenerateNU/toggo
Length of output: 42
🏁 Script executed:
# Check the trips service for any comments about date requirements
sed -n '55,75p' backend/internal/services/trips.go
sed -n '225,245p' backend/internal/services/trips.goRepository: GenerateNU/toggo
Length of output: 1513
🏁 Script executed:
# Get a comprehensive view of all date-related tests in the trips_test.go file
grep -n "test.*[Dd]ate\|StartDate\|EndDate" backend/internal/tests/trips_test.go | head -30Repository: GenerateNU/toggo
Length of output: 411
🏁 Script executed:
# Look at the lines around the validation test to see the full context
sed -n '600,650p' backend/internal/tests/trips_test.goRepository: GenerateNU/toggo
Length of output: 1373
Same-day trips are intentionally unsupported.
The service validation explicitly requires EndDate.After(StartDate) with the error message "end date must be after start date". Current tests cover valid dates (start before end) and invalid dates (end before start), but do not explicitly test the equal-date edge case. Consider adding a test case where startDate == endDate to document that same-day trips are intentionally rejected.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@backend/internal/tests/trips_test.go` around lines 609 - 625, Add a new
subtest in trips_test.go (similar to the existing t.Run "end date before start
date is rejected on create") that constructs a CreateTripRequest where StartDate
and EndDate are the same (set both to startDate), sends the POST to
"/api/v1/trips" via testkit.New(...).Request(...), and asserts
http.StatusBadRequest; also assert the validation error message contains "end
date must be after start date" to document that same-day trips are intentionally
rejected.
| ADD COLUMN start_date DATE, | ||
| ADD COLUMN end_date DATE; | ||
|
|
||
| CREATE INDEX idx_trips_dates ON trips(start_date, end_date); |
There was a problem hiding this comment.
do we have search functionality that would need this index? i dont remember
|
|
||
| /** | ||
| * @description Retrieves paginated activities for a trip, optionally filtered by category | ||
| * @description Retrieves paginated activities for a trip, optionally filtered by category, time of day, and/or date |
There was a problem hiding this comment.
im sure these docs will be regenerated but are they true? I don't think you touched activities in this one
There was a problem hiding this comment.
i think Amogh forgot to generate docs for his PR
Description
Required for differentiation between past and upcoming trips. Also a part of the onboarding Figma.
How has this been tested?
Checklist
Features
Improvements
Infra
Author Contribution