Implemented user settings view

This commit is contained in:
2025-11-23 13:57:02 +01:00
parent 1c311d6e31
commit c554af9479
8 changed files with 286 additions and 18 deletions

View File

@@ -1 +1,132 @@
<h3>Empty view lol</h3>
@using Microsoft.AspNetCore.Mvc.Localization
@using Berufsschule_HAM.Models
@model UserSettingsModel
@inject IViewLocalizer T
@inject IConfiguration Configuration
@{
ViewData["Title"] = T["User settings"];
string barcodeType = Configuration["BarcodeType"] ?? "EAN13";
}
<form id="updateSettings" method="post" asp-controller="Settings" asp-action="User">
<h4 class="fw-bold">@T["Account"]</h4>
<div class="row g-3 mb-3">
<div class="col-md-4">
<label class="form-label" for="username">@T["Username"]</label>
<input type="text" id="username" class="form-control" value="@Model.userModel.Uid" readonly/>
</div>
<div class="col-md-4">
<label class="form-label" for="password">@T["Password"]</label>
<input type="password" id="password" name="Password" class="form-control" />
</div>
</div>
<div class="row g-3 mb-3">
<div class="col-md-4">
<label class="form-label" for="updatePhotoFile">@T["Photo"]</label>
<input type="file" id="updatePhotoFile" accept="image/*" class="form-control" />
<input type="hidden" id="updateJpegPhoto" name="Image" />
<div class="mt-2 text-center">
<img id="updatePhotoPreview" src="" alt="Preview" class="img-thumbnail" style="max-height: 150px; display: none;" />
</div>
</div>
</div>
<h4 class="fw-bold">@T["Personal data"]</h4>
<div class="row g-3 mb-3">
<div class="col-md-1">
<label class="form-label" for="title">@T["Title"]</label>
<input type="text" id="title" class="form-control" value="@Model.userModel.Title" readonly/>
</div>
<div class="col-md-4">
<label class="form-label" for="name">@T["Name"]</label>
<input type="text" id="name" class="form-control" value="@Model.userModel.Cn" readonly/>
</div>
<div class="col-md-4">
<label class="form-label" for="surname">@T["Surname"]</label>
<input type="text" id="surname" class="form-control" value="@Model.userModel.Sn" readonly/>
</div>
</div>
<div class="row g-3 mb-3">
<div class="col-md-2">
<label class="form-label" for="birthdate">@T["Birth date"]</label>
<input type="text" id="birthdate" class="form-control" value="@Model.userModel.Description?.BirthDate" readonly/>
</div>
<div class="col-md-4">
<label class="form-label" for="address">@T["Address"]</label>
<input type="text" id="address" class="form-control" value="@Model.userModel.Description?.BirthDate" readonly/>
</div>
<div class="col-md-3">
<label class="form-label" for="workplace">@T["Workplace"]</label>
<input type="text" id="workplace" class="form-control" value="@Model.userModel.Description?.Workplace" readonly/>
</div>
</div>
<div class="row g-3 mb-3">
<div class="col-md-12">
<button type="submit" class="btn btn-warning float-end mt-3">@T["Apply settings"]</button>
</div>
</div>
</form>
<script defer>
document.addEventListener('DOMContentLoaded', () => {
const photoInput = document.getElementById('updatePhotoFile');
const photoPreview = document.getElementById('updatePhotoPreview');
const photoHidden = document.getElementById('updateJpegPhoto');
const updateForm = document.getElementById('updateSettings');
updateForm.addEventListener('submit', async e => {
e.preventDefault();
const password = updateForm.querySelector('#password').value;
if (password != null && password.length > 0 && !validatePassword(password)) {
showToast('@T["Password must be at least 8 characters long and include upper, lower, number, and special character"]', 'danger');
return;
}
const url = `/Settings/User`;
const dataFromEntries = Object.fromEntries(new FormData(updateForm).entries());
var data = unflatten(dataFromEntries);
try {
const response = await fetch(url, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(data)
});
const result = await response.json();
if (result.Success) {
showToast('@T["Settings updated successfully"]', 'success');
let userDropdown = document.getElementById("userDropdown");
userDropdown.children[0].src = userDropdown.children[0].src + "&cachebuster=" + Date.now(); // Force refresh user image
photoHidden.value = "";
photoPreview.src = "";
photoPreview.style.display = 'none';
updateForm.reset();
} else {
showToast(`${result.reason}: ${result.exception || '@T["Unknown error"]'}`, 'danger');
}
} catch (error) {
console.error(error);
showToast('@T["Error contacting server"]', 'danger');
}
});
photoInput.addEventListener('change', () => {
const file = photoInput.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = e => {
const base64 = e.target.result.split(',')[1]; // strip data:image/jpeg;base64,
photoHidden.value = base64;
photoPreview.src = e.target.result;
photoPreview.style.display = 'block';
};
reader.readAsDataURL(file);
});
});
</script>