Compare commits

...

10 Commits

@ -13,6 +13,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrainingSvc", "src\Training
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IdentitySvc", "src\IdentitySvc\IdentitySvc.csproj", "{74C8ACD5-5DC4-4466-8846-B552FF131304}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UserSvc", "src\UserSvc\UserSvc.csproj", "{07EAA60A-E3AD-4875-B355-8A4577BC4A87}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -38,11 +40,16 @@ Global
{74C8ACD5-5DC4-4466-8846-B552FF131304}.Debug|Any CPU.Build.0 = Debug|Any CPU
{74C8ACD5-5DC4-4466-8846-B552FF131304}.Release|Any CPU.ActiveCfg = Release|Any CPU
{74C8ACD5-5DC4-4466-8846-B552FF131304}.Release|Any CPU.Build.0 = Release|Any CPU
{07EAA60A-E3AD-4875-B355-8A4577BC4A87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{07EAA60A-E3AD-4875-B355-8A4577BC4A87}.Debug|Any CPU.Build.0 = Debug|Any CPU
{07EAA60A-E3AD-4875-B355-8A4577BC4A87}.Release|Any CPU.ActiveCfg = Release|Any CPU
{07EAA60A-E3AD-4875-B355-8A4577BC4A87}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{54BE8DE8-08BD-429F-BCCA-3363A879D922} = {2A7200CA-F40B-4715-8726-4ED30C785FA4}
{BF49B348-4188-4AC7-9ED4-5837F4B3BCD2} = {2A7200CA-F40B-4715-8726-4ED30C785FA4}
{F16873D3-6511-48AA-B74E-8B13D5F20F20} = {2A7200CA-F40B-4715-8726-4ED30C785FA4}
{74C8ACD5-5DC4-4466-8846-B552FF131304} = {2A7200CA-F40B-4715-8726-4ED30C785FA4}
{07EAA60A-E3AD-4875-B355-8A4577BC4A87} = {2A7200CA-F40B-4715-8726-4ED30C785FA4}
EndGlobalSection
EndGlobal

@ -10,7 +10,7 @@ public class CreateExerciceTemplateDto
public string? Description { get; set; } = default;
public ETarget? Target { get; set; } = ETarget.None;
public ETarget? Target { get; set; } = ETarget.NONE;
public string? ImageUrl { get; set; } = "images/default.jpg";

@ -29,7 +29,7 @@ public class DbInitializer
Id = Guid.NewGuid().ToString(),
Name = "Squat",
Description = "Squat is a compound exercise that targets the lower body, primarily the quadriceps, hamstrings, and glutes.",
Target = ETarget.Legs,
Target = ETarget.LEGS,
ImageUrl = "images/squat.jpg",
VideoUrl = "https://www.youtube.com/watch?v=dQw4w9WgXcQ&ab_channel=RickAstley",
},
@ -38,7 +38,7 @@ public class DbInitializer
Id = Guid.NewGuid().ToString(),
Name = "Bench Press",
Description = "Bench Press is a compound exercise that primarily targets the chest, shoulders, and triceps.",
Target = ETarget.Chest,
Target = ETarget.CHEST,
ImageUrl = "images/bench_press.jpg",
VideoUrl = "https://www.youtube.com/watch?v=dQw4w9WgXcQ&ab_channel=RickAstley",
},
@ -47,7 +47,7 @@ public class DbInitializer
Id = Guid.NewGuid().ToString(),
Name = "Deadlift",
Description = "Deadlift is a compound exercise that primarily targets the back, glutes, and hamstrings.",
Target = ETarget.Back,
Target = ETarget.BACK,
ImageUrl = "images/deadlift.jpg",
VideoUrl = "https://www.youtube.com/watch?v=dQw4w9WgXcQ&ab_channel=RickAstley",
},
@ -56,7 +56,7 @@ public class DbInitializer
Id = Guid.NewGuid().ToString(),
Name = "Shoulder Press",
Description = "Shoulder Press is a compound exercise that primarily targets the shoulders and triceps.",
Target = ETarget.Arms,
Target = ETarget.ARMS,
ImageUrl = "images/shoulder_press.jpg",
VideoUrl = "https://www.youtube.com/watch?v=dQw4w9WgXcQ&ab_channel=RickAstley",
},
@ -65,7 +65,7 @@ public class DbInitializer
Id = Guid.NewGuid().ToString(),
Name = "Running on Treadmill",
Description = "Running on Treadmill is a cardiovascular exercise that primarily targets the legs and improves overall fitness.",
Target = ETarget.Cardio,
Target = ETarget.CARDIO,
ImageUrl = "images/running_treadmill.jpg",
VideoUrl = "https://www.youtube.com/watch?v=dQw4w9WgXcQ&ab_channel=RickAstley",
},

@ -2,9 +2,10 @@ namespace Shared.Enum;
public enum EGoal
{
None,
MuscleGain,
WeightLoss,
Endurance,
Strength,
NONE,
MUSCLE_GAIN,
WEIGHT_LOSS,
MASS_GAIN,
IMPROVE_STAMINA,
KEEP_FIT,
}

@ -0,0 +1,11 @@
namespace Shared.Enum;
public enum EHealthProblem
{
NONE,
ARTHROSIS,
MIGRAINE,
BACK_PAIN,
ASTHMA,
DIABETES
}

@ -0,0 +1,11 @@
namespace Shared.Enum;
public enum ESleepLevel
{
NONE,
EXCELLENT,
GOOD,
BAD,
VERY_BAD,
TERRIBLE,
}

@ -0,0 +1,16 @@
namespace Shared.Enum;
public enum ESport
{
NONE,
FOOTBALL,
BASKETBALL,
HANDBALL,
TENNIS,
WALKING,
RUNNING,
SKATING,
BIKING,
YOGA,
ELSE,
}

@ -0,0 +1,10 @@
namespace Shared.Enum;
public enum ESportLevel
{
NONE,
VERY_SPORTY,
SPORTY,
BEGINNER,
NOT_SPORTY,
}

@ -2,10 +2,10 @@ namespace Shared.Enum;
public enum ETarget
{
None,
Legs,
Arms,
Back,
Cardio,
Chest,
NONE,
LEGS,
ARMS,
BACK,
CARDIO,
CHEST,
}

@ -26,7 +26,7 @@ public class TrainingDbInitializer
Id = Guid.NewGuid().ToString(),
Name = "Squat",
Description = "Squat is a compound exercise that targets the lower body, primarily the quadriceps, hamstrings, and glutes.",
Target = Shared.Enum.ETarget.Legs,
Target = Shared.Enum.ETarget.LEGS,
ImageUrl = "images/squat.jpg",
VideoUrl = "https://www.youtube.com/watch?v=dQw4w9WgXcQ&ab_channel=RickAstley",
},
@ -35,7 +35,7 @@ public class TrainingDbInitializer
Id = Guid.NewGuid().ToString(),
Name = "Bench Press",
Description = "Bench Press is a compound exercise that primarily targets the chest, shoulders, and triceps.",
Target = Shared.Enum.ETarget.Chest,
Target = Shared.Enum.ETarget.CHEST,
ImageUrl = "images/bench_press.jpg",
VideoUrl = "https://www.youtube.com/watch?v=dQw4w9WgXcQ&ab_channel=RickAstley",
},
@ -44,7 +44,7 @@ public class TrainingDbInitializer
Id = Guid.NewGuid().ToString(),
Name = "Deadlift",
Description = "Deadlift is a compound exercise that primarily targets the back, glutes, and hamstrings.",
Target = Shared.Enum.ETarget.Back,
Target = Shared.Enum.ETarget.BACK,
ImageUrl = "images/deadlift.jpg",
VideoUrl = "https://www.youtube.com/watch?v=dQw4w9WgXcQ&ab_channel=RickAstley",
},
@ -53,7 +53,7 @@ public class TrainingDbInitializer
Id = Guid.NewGuid().ToString(),
Name = "Shoulder Press",
Description = "Shoulder Press is a compound exercise that primarily targets the shoulders and triceps.",
Target = Shared.Enum.ETarget.Arms,
Target = Shared.Enum.ETarget.ARMS,
ImageUrl = "images/shoulder_press.jpg",
VideoUrl = "https://www.youtube.com/watch?v=dQw4w9WgXcQ&ab_channel=RickAstley",
},
@ -62,7 +62,7 @@ public class TrainingDbInitializer
Id = Guid.NewGuid().ToString(),
Name = "Running on Treadmill",
Description = "Running on Treadmill is a cardiovascular exercise that primarily targets the legs and improves overall fitness.",
Target = Shared.Enum.ETarget.Cardio,
Target = Shared.Enum.ETarget.CARDIO,
ImageUrl = "images/running_treadmill.jpg",
VideoUrl = "https://www.youtube.com/watch?v=dQw4w9WgXcQ&ab_channel=RickAstley",
},

@ -18,7 +18,7 @@ public class TrainingProgram : EntityBase
public string OwnerId { get; set; } = "";
public EGoal Goal { get; set; } = EGoal.MuscleGain;
public EGoal Goal { get; set; } = EGoal.NONE;
public EDifficulty Difficulty { get; set; } = EDifficulty.Beginner;

@ -0,0 +1,80 @@
using AutoMapper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using UserSvc.Entities;
using UserSvc.Data;
using UserSvc.DTOs;
namespace UserSvc.Controllers;
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
private readonly UserDbContext _context;
private readonly IMapper _mapper;
public UsersController(UserDbContext context, IMapper mapper)
{
_context = context;
_mapper = mapper;
}
[AllowAnonymous]
[HttpGet("{id}")]
public async Task<ActionResult<UserDto>> GetById(string id)
{
var user = await _context.Users.FindAsync(id);
if (user == null) return NotFound();
return _mapper.Map<UserDto>(user);
}
[AllowAnonymous]
[HttpGet]
public async Task<ActionResult<IEnumerable<UserDto>>> GetUsers()
{
var users = await _context.Users.ToListAsync();
return Ok(_mapper.Map<List<UserDto>>(users));
}
[AllowAnonymous]
[HttpPost]
public async Task<IActionResult> Create([FromBody] UserDto dto)
{
var user = _mapper.Map<User>(dto);
var userTest = await _context.Users.FindAsync(user.Id);
if (userTest != null) return Conflict("User already exists with this ID.");
_context.Users.Add(user);
await _context.SaveChangesAsync();
return CreatedAtAction(nameof(GetById), new { id = user.Id }, _mapper.Map<UserDto>(user));
}
[AllowAnonymous]
[HttpPut("{id}")]
public async Task<IActionResult> Update(string id, [FromBody] UpdateUserDto dto)
{
var user = await _context.Users.FindAsync(id);
if (user == null) return NotFound();
_mapper.Map(dto, user);
user.UpdatedAt = DateTime.UtcNow;
await _context.SaveChangesAsync();
return NoContent();
}
[AllowAnonymous]
[HttpDelete("{id}")]
public async Task<IActionResult> Delete(string id)
{
var user = await _context.Users.FindAsync(id);
if (user == null) return NotFound();
_context.Users.Remove(user);
await _context.SaveChangesAsync();
return NoContent();
}
}

@ -0,0 +1,21 @@
using Shared.Enum;
namespace UserSvc.DTOs;
public class UpdateUserDto
{
public string? Name { get; set; }
public string? Surname { get; set; }
public int? Age { get; set; }
public float? Weight { get; set; }
public float? Height { get; set; }
public bool? Sexe { get; set; }
public string? ProfilePict { get; set; }
public int? NbSessionWeek { get; set; }
public EGoal? Goal { get; set; }
public ESleepLevel? SleepLevel { get; set; }
public ESportLevel? SportLevel { get; set; }
public ESport? Sports { get; set; }
public EHealthProblem? HealthProblems { get; set; }
public string? Program { get; set; }
}

@ -0,0 +1,24 @@
using System.ComponentModel.DataAnnotations;
using Shared.Enum;
namespace UserSvc.DTOs;
public class UserDto
{
[Required]
public string Name { get; set; } = "Guest";
[Required]
public string Surname { get; set; } = "Gest";
public int Age { get; set; } = 0;
public float Weight { get; set; } = 0.0f;
public float Height { get; set; } = 0.0f;
public bool Sexe { get; set; } = true;
public string? ProfilePict { get; set; } = "https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_960_720.png";
public int NbSessionWeek { get; set; } = 1;
public EGoal Goal { get; set; } = EGoal.NONE;
public ESleepLevel SleepLevel { get; set; } = ESleepLevel.NONE;
public ESportLevel SportLevel { get; set; } = ESportLevel.NONE;
public List<ESport> Sports { get; set; } = [ ESport.NONE ];
public List<EHealthProblem> HealthProblems { get; set; } = [ EHealthProblem.NONE ];
public string? Program { get; set; } = null;
}

@ -0,0 +1,96 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using UserSvc.Data;
#nullable disable
namespace UserSvc.Data.Migrations
{
[DbContext(typeof(UserDbContext))]
[Migration("20250618084336_InitalCreate")]
partial class InitalCreate
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.17")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("UserSvc.Entities.User", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<int>("Age")
.HasColumnType("integer");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<int>("Goal")
.HasColumnType("integer");
b.Property<int[]>("HealthProblems")
.IsRequired()
.HasColumnType("integer[]");
b.Property<float>("Height")
.HasColumnType("real");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<int>("NbSessionWeek")
.HasColumnType("integer");
b.Property<string>("ProfilePict")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Program")
.HasColumnType("text");
b.Property<bool>("Sexe")
.HasColumnType("boolean");
b.Property<int>("SleepLevel")
.HasColumnType("integer");
b.Property<int>("SportLevel")
.HasColumnType("integer");
b.Property<int[]>("Sports")
.IsRequired()
.HasColumnType("integer[]");
b.Property<string>("Surname")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<float>("Weight")
.HasColumnType("real");
b.HasKey("Id");
b.HasIndex("Name", "Surname")
.IsUnique();
b.ToTable("Users");
});
#pragma warning restore 612, 618
}
}
}

@ -0,0 +1,55 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace UserSvc.Data.Migrations
{
/// <inheritdoc />
public partial class InitalCreate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Users",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
Name = table.Column<string>(type: "text", nullable: false),
Surname = table.Column<string>(type: "text", nullable: false),
Age = table.Column<int>(type: "integer", nullable: false),
Weight = table.Column<float>(type: "real", nullable: false),
Height = table.Column<float>(type: "real", nullable: false),
Sexe = table.Column<bool>(type: "boolean", nullable: false),
ProfilePict = table.Column<string>(type: "text", nullable: false),
NbSessionWeek = table.Column<int>(type: "integer", nullable: false),
Goal = table.Column<int>(type: "integer", nullable: false),
SleepLevel = table.Column<int>(type: "integer", nullable: false),
SportLevel = table.Column<int>(type: "integer", nullable: false),
Sports = table.Column<int[]>(type: "integer[]", nullable: false),
HealthProblems = table.Column<int[]>(type: "integer[]", nullable: false),
Program = table.Column<string>(type: "text", nullable: true),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Users", x => x.Id);
});
migrationBuilder.CreateIndex(
name: "IX_Users_Name_Surname",
table: "Users",
columns: new[] { "Name", "Surname" },
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Users");
}
}
}

@ -0,0 +1,93 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using UserSvc.Data;
#nullable disable
namespace UserSvc.Data.Migrations
{
[DbContext(typeof(UserDbContext))]
partial class UserDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.17")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("UserSvc.Entities.User", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<int>("Age")
.HasColumnType("integer");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<int>("Goal")
.HasColumnType("integer");
b.Property<int[]>("HealthProblems")
.IsRequired()
.HasColumnType("integer[]");
b.Property<float>("Height")
.HasColumnType("real");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<int>("NbSessionWeek")
.HasColumnType("integer");
b.Property<string>("ProfilePict")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Program")
.HasColumnType("text");
b.Property<bool>("Sexe")
.HasColumnType("boolean");
b.Property<int>("SleepLevel")
.HasColumnType("integer");
b.Property<int>("SportLevel")
.HasColumnType("integer");
b.Property<int[]>("Sports")
.IsRequired()
.HasColumnType("integer[]");
b.Property<string>("Surname")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<float>("Weight")
.HasColumnType("real");
b.HasKey("Id");
b.HasIndex("Name", "Surname")
.IsUnique();
b.ToTable("Users");
});
#pragma warning restore 612, 618
}
}
}

@ -0,0 +1,13 @@
using Microsoft.EntityFrameworkCore;
using UserSvc.Entities;
namespace UserSvc.Data;
public class UserDbContext : DbContext
{
public UserDbContext(DbContextOptions options) : base(options)
{
}
public DbSet<User> Users { get; set; }
}

@ -0,0 +1,29 @@
using Microsoft.EntityFrameworkCore;
using Shared.Entities;
using Shared.Enum;
namespace UserSvc.Entities;
[Index(nameof(Name), nameof(Surname), IsUnique = true)]
public class User : EntityBase
{
public string Name { get; set; } = "Gest";
public string Surname { get; set; } = "Gest";
public int Age { get; set; } = 0;
public float Weight { get; set; } = 0.0f;
public float Height { get; set; } = 0.0f;
public bool Sexe { get; set; } = true;
public string ProfilePict { get; set; } = "https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_960_720.png";
public int NbSessionWeek { get; set; } = 1;
public EGoal Goal { get; set; } = EGoal.NONE;
public ESleepLevel SleepLevel { get; set; } = ESleepLevel.NONE;
public ESportLevel SportLevel { get; set; } = ESportLevel.NONE;
public List<ESport> Sports { get; set; } = [];
public List<EHealthProblem> HealthProblems { get; set; } = [];
public string? Program { get; set; } = null;
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
}

@ -0,0 +1,20 @@
using UserSvc.Data;
using Microsoft.EntityFrameworkCore;
using AutoMapper;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddAutoMapper(typeof(Program));
builder.Services.AddDbContext<UserDbContext>(opt =>
{
opt.UseNpgsql(builder.Configuration.GetConnectionString("UserDb"));
});
var app = builder.Build();
//app.UseAuthorization();
app.MapControllers();
app.Run();

@ -0,0 +1,14 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://localhost:7004",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

@ -0,0 +1,17 @@
using AutoMapper;
using UserSvc.DTOs;
using UserSvc.Entities;
namespace UserSvc.RequestHelpers;
public class UserProfile : Profile
{
public UserProfile()
{
CreateMap<User, UserDto>();
CreateMap<UserDto, User>();
CreateMap<UpdateUserDto, User>()
.ForAllMembers(opt => opt.Condition((src, dest, srcMember) => srcMember != null));
CreateMap<User, UpdateUserDto>();
}
}

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.17" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.17">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.11" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,6 @@
@UserSvc_HostAddress = http://localhost:5025
GET {{UserSvc_HostAddress}}/weatherforecast/
Accept: application/json
###
Loading…
Cancel
Save