package handlers import ( "database/sql" "html/template" "log" "net/http" "strconv" ory "github.com/ory/client-go" "decor-by-hannahs/internal/db" ) type BookingWithService struct { ID int64 ServiceName string ServiceDescription string ServicePriceCents int32 ServiceOption string EventType string EventDate string Address string Notes string Status string CreatedAt string } type ProfileData struct { Authenticated bool Email string DisplayName string ID string ActivePage string Bookings []BookingWithService OrySettingsURL string OryLoginURL string } func ProfileHandler(q *db.Queries, tmpl *template.Template, oryClient *ory.APIClient) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { oryAPIURL := getOryAPIURL() pd := ProfileData{ ActivePage: "profile", OryLoginURL: "/login", OrySettingsURL: oryAPIURL + "/ui/settings", } cookies := r.Header.Get("Cookie") session, _, err := oryClient.FrontendAPI.ToSession(r.Context()).Cookie(cookies).Execute() if err == nil && session != nil && session.Active != nil && *session.Active { email := getEmailFromSession(session) if email != "" { oryID := sql.NullString{String: session.Identity.Id, Valid: true} user, err := q.GetUserByOryID(r.Context(), oryID) if err != nil { user, err = q.CreateUser(r.Context(), db.CreateUserParams{ Email: email, OryIdentityID: oryID, }) if err != nil { log.Printf("Failed to create user: %v", err) } else { log.Printf("Created new user: %s (ID: %d)", email, user.ID) } } if err == nil { pd.Authenticated = true pd.Email = user.Email pd.ID = strconv.FormatInt(user.ID, 10) pd.DisplayName = user.Email bookings, err := q.ListBookingsWithServiceByUser(r.Context(), sql.NullInt64{Int64: user.ID, Valid: true}) if err != nil { log.Printf("Error fetching bookings: %v", err) } else { for _, b := range bookings { pd.Bookings = append(pd.Bookings, BookingWithService{ ID: b.ID, ServiceName: b.ServiceName, ServiceDescription: nullStringToString(b.ServiceDescription), ServicePriceCents: b.ServicePriceCents, ServiceOption: nullStringToString(b.ServiceOption), EventType: nullStringToString(b.EventType), EventDate: b.EventDate.Format("January 2, 2006"), Address: nullStringToString(b.Address), Notes: nullStringToString(b.Notes), Status: nullStringToString(b.Status), CreatedAt: b.CreatedAt.Time.Format("Jan 2, 2006"), }) } } } } } if err := tmpl.ExecuteTemplate(w, "profile.tmpl", pd); err != nil { http.Error(w, "failed to render profile", http.StatusInternalServerError) return } } } func getEmailFromSession(session *ory.Session) string { if session.Identity.Traits == nil { return "" } traits, ok := session.Identity.Traits.(map[string]interface{}) if !ok { return "" } email, ok := traits["email"].(string) if !ok { return "" } return email }