@@ -54,16 +54,14 @@ async def read_profile(
5454):
5555 # Load account emails
5656 account_emails = session .exec (
57- select (AccountEmail ).where (AccountEmail .account_id == user .account_id )
57+ select (AccountEmail )
58+ .where (AccountEmail .account_id == user .account_id )
59+ .order_by (AccountEmail .is_primary .desc ()) # type: ignore[union-attr]
5860 ).all () if user .account_id else []
5961
6062 return templates .TemplateResponse (
6163 request ,
6264 "users/profile.html" , {
63- "max_file_size_mb" : MAX_FILE_SIZE / (1024 * 1024 ), # Convert bytes to MB
64- "min_dimension" : MIN_DIMENSION ,
65- "max_dimension" : MAX_DIMENSION ,
66- "allowed_formats" : list (ALLOWED_CONTENT_TYPES .keys ()),
6765 "show_form" : show_form == "true" ,
6866 "user" : user ,
6967 "account_emails" : account_emails ,
@@ -72,6 +70,40 @@ async def read_profile(
7270 )
7371
7472
73+ @router .get ("/edit-form" )
74+ async def edit_profile_form (
75+ request : Request ,
76+ user : User = Depends (get_authenticated_user ),
77+ ):
78+ if not is_htmx_request (request ):
79+ return RedirectResponse (url = router .url_path_for ("read_profile" ), status_code = 303 )
80+ return templates .TemplateResponse (
81+ request ,
82+ "users/partials/profile_form.html" ,
83+ {
84+ "user" : user ,
85+ "max_file_size_mb" : MAX_FILE_SIZE / (1024 * 1024 ),
86+ "min_dimension" : MIN_DIMENSION ,
87+ "max_dimension" : MAX_DIMENSION ,
88+ "allowed_formats" : list (ALLOWED_CONTENT_TYPES .keys ()),
89+ },
90+ )
91+
92+
93+ @router .get ("/profile-display" )
94+ async def profile_display (
95+ request : Request ,
96+ user : User = Depends (get_authenticated_user ),
97+ ):
98+ if not is_htmx_request (request ):
99+ return RedirectResponse (url = router .url_path_for ("read_profile" ), status_code = 303 )
100+ return templates .TemplateResponse (
101+ request ,
102+ "users/partials/profile_display.html" ,
103+ {"user" : user },
104+ )
105+
106+
75107@router .post ("/update" , response_class = RedirectResponse )
76108async def update_profile (
77109 request : Request ,
@@ -80,8 +112,10 @@ async def update_profile(
80112 user : User = Depends (get_authenticated_user ),
81113 session : Session = Depends (get_session )
82114):
115+ avatar_changed = bool (avatar_file and avatar_file .filename )
116+
83117 # Handle avatar update
84- if avatar_file and avatar_file . filename :
118+ if avatar_changed :
85119 avatar_data = await avatar_file .read ()
86120 avatar_content_type = avatar_file .content_type
87121
@@ -107,18 +141,17 @@ async def update_profile(
107141 session .refresh (user )
108142
109143 if is_htmx_request (request ):
144+ if avatar_changed :
145+ # Avatar affects the navbar, which is outside the swap target.
146+ # Tell HTMX to do a full page refresh so everything updates.
147+ response = Response (status_code = 200 )
148+ response .headers ["HX-Refresh" ] = "true"
149+ return response
110150 response = templates .TemplateResponse (
111151 request ,
112152 "users/partials/profile_display.html" ,
113- {
114- "user" : user ,
115- "max_file_size_mb" : MAX_FILE_SIZE / (1024 * 1024 ),
116- "min_dimension" : MIN_DIMENSION ,
117- "max_dimension" : MAX_DIMENSION ,
118- "allowed_formats" : list (ALLOWED_CONTENT_TYPES .keys ()),
119- },
153+ {"user" : user },
120154 )
121- response .headers ["HX-Trigger" ] = "profileUpdated"
122155 return append_toast (response , request , templates , "Profile updated successfully." )
123156 return RedirectResponse (url = router .url_path_for ("read_profile" ), status_code = 303 )
124157
0 commit comments