[Profile] Editable profile (avatar + resume) + role-based profile dropdown menu
CI/CD / CI · dotnet build (push) Successful in 44s
CI/CD / Deploy · hamkadr (push) Successful in 57s

Every user gets a full editable profile at /Me/Profile: name, role, city, specialty/title, license, years, bio + avatar image upload + resume upload (PDF/image). Avatar/resume stored in-DB on User (migration, 5 nullable columns). Endpoints: /avatar/{id} (public) and /resume/{id} (owner, admin, or an employer who received that user's application). Nav: replaced the scattered action links with an avatar button + dropdown listing all of the user's pages by role (profile, کارجو panel, alerts, preferences, notifications; employer panel; admin panel + settings; logout) — shows the avatar image or initials; collapses into the burger menu on mobile; closes on outside-click.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-04 21:49:40 +03:30
parent 167d263560
commit e633463906
9 changed files with 1689 additions and 15 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,71 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace JobsMedical.Web.Migrations
{
/// <inheritdoc />
public partial class UserProfileMedia : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<byte[]>(
name: "Avatar",
table: "Users",
type: "bytea",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "AvatarContentType",
table: "Users",
type: "character varying(100)",
maxLength: 100,
nullable: true);
migrationBuilder.AddColumn<byte[]>(
name: "Resume",
table: "Users",
type: "bytea",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "ResumeContentType",
table: "Users",
type: "character varying(120)",
maxLength: 120,
nullable: true);
migrationBuilder.AddColumn<string>(
name: "ResumeFileName",
table: "Users",
type: "character varying(200)",
maxLength: 200,
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Avatar",
table: "Users");
migrationBuilder.DropColumn(
name: "AvatarContentType",
table: "Users");
migrationBuilder.DropColumn(
name: "Resume",
table: "Users");
migrationBuilder.DropColumn(
name: "ResumeContentType",
table: "Users");
migrationBuilder.DropColumn(
name: "ResumeFileName",
table: "Users");
}
}
}
@@ -817,6 +817,13 @@ namespace JobsMedical.Web.Migrations
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<byte[]>("Avatar")
.HasColumnType("bytea");
b.Property<string>("AvatarContentType")
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.Property<string>("BanReason")
.HasMaxLength(300)
.HasColumnType("character varying(300)");
@@ -839,6 +846,17 @@ namespace JobsMedical.Web.Migrations
.HasMaxLength(20)
.HasColumnType("character varying(20)");
b.Property<byte[]>("Resume")
.HasColumnType("bytea");
b.Property<string>("ResumeContentType")
.HasMaxLength(120)
.HasColumnType("character varying(120)");
b.Property<string>("ResumeFileName")
.HasMaxLength(200)
.HasColumnType("character varying(200)");
b.Property<int>("Role")
.HasColumnType("integer");