feat(profile): role-aware nav + avatar menu + full editable profile
Build backend images / build content-svc (push) Failing after 1m59s
Build backend images / build file-svc (push) Failing after 3m18s
Build backend images / build gateway (push) Failing after 3m28s
Build backend images / build identity-svc (push) Failing after 2m1s
Build backend images / build notification-svc (push) Failing after 4m45s
Build backend images / build render-svc (push) Failing after 5m18s
Build backend images / build studio-svc (push) Failing after 2m12s

Navigation:
- UserMenu (avatar + role-aware dropdown: Dashboard, Admin Panel for admins,
  Profile, Sign out) replaces Sign In/Try Free when logged in (desktop + mobile).
- Real avatars in dashboard sidebar + a new admin-shell profile section.
- Shared Avatar primitive (image with initials fallback). SiteChrome excludes /admin.

Profile (data-collection surface for future AI video generation):
- SettingsProfile rebuilt: avatar upload + slogan, about, company, website,
  country, national code, birthdate, gender. No resume builder (per scope change).
- /api/profile forwards all fields; new user-scoped /api/profile/upload (avatar →
  MinIO via file-svc, sets avatar). Identity UpdateUserRequest/UserResponse widened
  (country/national/method); no DB migration (columns already exist).
- fa+en strings; verified GET/PATCH round-trip + logged-in SSR render.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-05 00:34:25 +03:30
parent 718564bce4
commit d4fee8d1d7
21 changed files with 659 additions and 116 deletions
@@ -488,7 +488,9 @@ public class AuthService(
u.IsAdmin, u.IsTenantAdmin, u.RegisterMode.ToString(),
u.LastActiveDate, u.BalanceMinor, u.AffiliateBalanceMinor,
u.LoyaltyScore, u.DailyRemainRenderCount, u.MaxDailyRenderCount,
u.ParallelRenderingCeiling, u.UsedStorageBytes, u.RegisterDate
u.ParallelRenderingCeiling, u.UsedStorageBytes, u.RegisterDate,
u.Slogan, u.AboutMe, u.CompanyName, u.WebsiteName,
u.BirthDate, u.Gender?.ToString(), u.NationalCode, u.CountryCode
);
internal static TenantResponse MapTenantResponse(Tenant t) => new(
@@ -33,6 +33,9 @@ public class UserService(IdentityDbContext db) : IUserService
if (request.SmsTellMe.HasValue) user.SmsTellMe = request.SmsTellMe.Value;
if (request.PushTellMe.HasValue) user.PushTellMe = request.PushTellMe.Value;
if (request.TelegramTellMe.HasValue) user.TelegramTellMe = request.TelegramTellMe.Value;
if (request.CountryCode != null) user.CountryCode = request.CountryCode;
if (request.NationalCode != null) user.NationalCode = request.NationalCode;
if (request.MethodOfIntroduction != null) user.MethodOfIntroduction = request.MethodOfIntroduction;
user.UpdatedAt = DateTime.UtcNow;
await db.SaveChangesAsync();
@@ -11,7 +11,10 @@ public record UpdateUserRequest(
bool? EmailTellMe,
bool? SmsTellMe,
bool? PushTellMe,
bool? TelegramTellMe
bool? TelegramTellMe,
string? CountryCode = null,
string? NationalCode = null,
string? MethodOfIntroduction = null
);
public record SetAvatarRequest(Guid? AvatarId, string? AvatarUrl);
@@ -48,7 +48,16 @@ public record UserResponse(
int MaxDailyRenderCount,
int ParallelRenderingCeiling,
long UsedStorageBytes,
DateTime RegisterDate
DateTime RegisterDate,
// Profile data (collected over time; powers future AI video generation)
string? Slogan = null,
string? AboutMe = null,
string? CompanyName = null,
string? WebsiteName = null,
DateOnly? BirthDate = null,
string? Gender = null,
string? NationalCode = null,
string? CountryCode = null
);
public record BalanceResponse(