Yōten: A social tracker for your language learning journey built on the atproto.

feat(new-study-session): add query params for prefilled data

Signed-off-by: brookjeynes <me@brookjeynes.dev>

+63 -7
+10
internal/server/handlers/study-session.go
··· 435 435 return resource.Status != db.Deleted 436 436 }) 437 437 438 + queryParams := views.NewStudySessionQueryParams{ 439 + LanguageCode: r.URL.Query().Get("language_code"), 440 + DurationHours: r.URL.Query().Get("duration_hours"), 441 + DurationMinutes: r.URL.Query().Get("duration_minutes"), 442 + DurationSeconds: r.URL.Query().Get("duration_seconds"), 443 + Description: r.URL.Query().Get("description"), 444 + ActivityId: r.URL.Query().Get("activity_id"), 445 + } 446 + 438 447 views.NewStudySessionPage(views.NewStudySessionPageParams{ 439 448 User: user, 440 449 Profile: profile, 441 450 Activities: activeActivities, 442 451 Resources: activeResources, 443 452 SortedLanguages: profile.Languages, 453 + QueryParams: queryParams, 444 454 }).Render(r.Context(), w) 445 455 case http.MethodPost: 446 456 newStudySession, err := h.parseStudySessionForm(r)
+43 -7
internal/server/views/new-study-session.templ
··· 1 1 package views 2 2 3 3 import ( 4 + "fmt" 5 + 6 + "strconv" 4 7 "yoten.app/internal/server/views/layouts" 5 8 "yoten.app/internal/server/views/partials" 6 9 ) ··· 11 14 12 15 if len(params.Profile.Languages) == 1 { 13 16 initialLangCode = string(params.Profile.Languages[0].Code) 17 + } 18 + 19 + activityName := "Select an activity" 20 + if params.QueryParams.ActivityId != "" { 21 + activityId, err := strconv.ParseInt(params.QueryParams.ActivityId, 10, 64) 22 + if err == nil { 23 + for _, a := range params.Activities { 24 + if int64(a.ID) == activityId { 25 + activityName = a.Name 26 + } 27 + } 28 + } 14 29 } 15 30 }} 16 31 @layouts.Base(layouts.BaseParams{Title: "new study session"}) { ··· 279 294 <p class="font-medium text-sm">Duration</p> 280 295 <div class="flex gap-2"> 281 296 <div class="flex flex-col gap-1 w-full"> 282 - <div x-data="{ hours: 0, maxHours: 24 }"> 297 + {{ 298 + hoursStr := params.QueryParams.DurationHours 299 + hours := "0" 300 + if hoursStr != "" { 301 + hours = hoursStr 302 + } 303 + }} 304 + <div x-data={ fmt.Sprintf("{ hours: %s, maxHours: 60 }", hours) }> 283 305 <input 284 306 type="number" 285 307 id="duration-hours" ··· 295 317 <label for="duration-minutes" class="text-xs text-text-muted">Hours</label> 296 318 </div> 297 319 <div class="flex flex-col gap-1 w-full"> 298 - <div x-data="{ minutes: 0, maxMinutes: 60 }"> 320 + {{ 321 + minutesStr := params.QueryParams.DurationMinutes 322 + minutes := "0" 323 + if minutesStr != "" { 324 + minutes = minutesStr 325 + } 326 + }} 327 + <div x-data={ fmt.Sprintf("{ minutes: %s, maxMinutes: 60 }", minutes) }> 299 328 <input 300 329 type="number" 301 330 id="duration-minutes" ··· 311 340 <label for="duration-minutes" class="text-xs text-text-muted">Minutes</label> 312 341 </div> 313 342 <div class="flex flex-col gap-1 w-full"> 314 - <div x-data="{ seconds: 0, maxSeconds: 60 }"> 343 + {{ 344 + secondsStr := params.QueryParams.DurationSeconds 345 + seconds := "0" 346 + if secondsStr != "" { 347 + seconds = secondsStr 348 + } 349 + }} 350 + <div x-data={ fmt.Sprintf("{ seconds: %s, maxSeconds: 60 }", seconds) }> 315 351 <input 316 352 type="number" 317 353 id="duration-seconds" ··· 366 402 > 367 403 Description (optional) 368 404 </label> 369 - <div x-data="{ text: '' }"> 405 + <div x-data={ fmt.Sprintf("{ text: '%s' }", templ.EscapeString(params.QueryParams.Description)) }> 370 406 <textarea 371 407 x-model="text" 372 408 id="description" ··· 413 449 414 450 activitiesSearchQuery: '', 415 451 activities: {{ params.Activities }} || [], 416 - selectedActivityName: 'Select an activity', 417 - selectedActivityId: '', 452 + selectedActivityName: {{ activityName }}, 453 + selectedActivityId: {{ params.QueryParams.ActivityId }}, 418 454 activitiesIsOpen: false, 419 455 420 456 resourcesSearchQuery: '', ··· 423 459 selectedResourceId: '', 424 460 resourcesIsOpen: false, 425 461 426 - selectedLanguage: {{ initialLangCode }} || '', 462 + selectedLanguage: {{ params.QueryParams.LanguageCode }} || {{ initialLangCode }} || '', 427 463 428 464 get filteredActivities() { 429 465 if (this.activitiesSearchQuery === '') {
+10
internal/server/views/views.go
··· 44 44 45 45 type NotFoundPageParams struct{} 46 46 47 + type NewStudySessionQueryParams struct { 48 + LanguageCode string 49 + DurationHours string 50 + DurationMinutes string 51 + DurationSeconds string 52 + Description string 53 + ActivityId string 54 + } 55 + 47 56 type NewStudySessionPageParams struct { 48 57 // The current logged in user. 49 58 User *types.User ··· 51 60 Activities []db.Activity 52 61 Resources []db.Resource 53 62 SortedLanguages []db.Language 63 + QueryParams NewStudySessionQueryParams 54 64 } 55 65 56 66 type EditStudySessionPageParams struct {