Files
Berufsschule_HAM/src/Views/Home/Assets.cshtml

346 lines
15 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
@using Microsoft.AspNetCore.Mvc.Localization
@using Berufsschule_HAM.Models
@model HomeIndexViewModel
@inject IViewLocalizer T
@{
ViewData["Title"] = T["Assets"];
}
<div class="container py-4">
<h2 class="mb-3">@T["Assets"]</h2>
<div class="mb-4 d-flex flex-wrap gap-2">
<button class="btn btn-outline-primary" data-bs-toggle="modal" data-bs-target="#createAssetModal">
@T["Create asset"]
</button>
</div>
<div class="table-responsive">
<table class="table table-striped align-middle">
<thead>
<tr>
<th>@T["Owner"]</th>
<th>@T["Asset ID"]</th>
<th>@T["Asset Name"]</th>
<th>@T["Location"]</th>
<th>@T["Action"]</th>
</tr>
</thead>
<tbody>
@{
foreach (AssetsTableViewModel assetsTableViewModel in Model.AssetsTableViewModels)
{
<tr>
<td>@assetsTableViewModel.UserUID</td>
<td>@assetsTableViewModel.AssetCn</td>
<td>@assetsTableViewModel.AssetName</td>
<td>@assetsTableViewModel.LocationName</td>
<td>
<div class="d-flex gap-2">
<button class="btn btn-sm btn-primary">@T["Update"]</button>
<button class="btn btn-sm btn-danger btn-delete"
data-asset-id="@assetsTableViewModel.AssetCn"
data-bs-toggle="modal"
data-bs-target="#deleteModal">
🗑️ @T["Delete"]
</button>
</div>
</td>
</tr>
}
}
</tbody>
</table>
</div>
</div>
<!-- Asset Delete Confirmation Modal -->
<div class="modal fade" id="deleteModal" tabindex="-1" aria-labelledby="deleteModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header bg-danger text-white">
<h5 class="modal-title" id="deleteModalLabel">Confirm Delete</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p>Are you sure you want to delete the asset <strong id="assetName"></strong> (ID: <span id="assetId"></span>)?</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<form id="deleteForm" method="post" action="">
<button type="submit" class="btn btn-danger">Yes, Delete</button>
</form>
</div>
</div>
</div>
</div>
<script>
function createToastContainer() {
const container = document.createElement('div');
container.id = 'toastContainer';
container.className = 'toast-container position-fixed bottom-0 end-0 p-3';
document.body.appendChild(container);
return container;
}
// Simple toast helper
function showToast(message, type) {
const toastContainer = document.getElementById('toastContainer') || createToastContainer();
const toast = document.createElement('div');
toast.className = `toast align-items-center text-white bg-${type} border-0`;
toast.role = 'alert';
toast.innerHTML = `
<div class="d-flex">
<div class="toast-body">${message}</div>
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
</div>
`;
toastContainer.appendChild(toast);
const bsToast = new bootstrap.Toast(toast, { delay: 3000 });
bsToast.show();
toast.addEventListener('hidden.bs.toast', () => toast.remove());
}
document.addEventListener('DOMContentLoaded', () => {
const deleteModal = document.getElementById('deleteModal');
let currentButton = null; // The delete button that opened the modal
deleteModal.addEventListener('show.bs.modal', event => {
currentButton = event.relatedTarget; // Button that triggered the modal
const assetId = currentButton.getAttribute('data-asset-id');
const assetName = currentButton.getAttribute('data-asset-name');
deleteModal.querySelector('#assetId').textContent = assetId;
deleteModal.querySelector('#assetName').textContent = assetName;
// Store the delete URL for later use
deleteModal.querySelector('#deleteForm').dataset.url = `/Assets/Delete?cn=${assetId}`;
});
// Handle submit of deleteForm via fetch()
const deleteForm = document.getElementById('deleteForm');
deleteForm.addEventListener('submit', async e => {
e.preventDefault();
const url = deleteForm.dataset.url;
const assetId = deleteModal.querySelector('#assetId').textContent;
try {
const response = await fetch(url, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}//,
//body: JSON.stringify({ id: assetId }) // Use this for Post requests with [FromBody] parameters like in /Groups/Update
});
const result = await response.json();
if (result.success) {
// Close the modal
const modal = bootstrap.Modal.getInstance(deleteModal);
modal.hide();
// Remove the row from the table
const row = currentButton.closest('tr');
row.classList.add('table-danger');
setTimeout(() => row.remove(), 300);
showToast('Asset deleted successfully', 'success');
} else {
showToast(`${result.reason}: ${result.exception || 'Unknown error'}`, 'danger');
}
} catch (error) {
console.error(error);
showToast('Error contacting server', 'danger');
}
});
});
</script>
<!-- Asset Create Modal -->
<div class="modal fade" id="createAssetModal" tabindex="-1" aria-labelledby="createAssetModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered">
<div class="modal-content">
<div class="modal-header bg-primary text-white">
<h5 class="modal-title" id="createAssetModalLabel">@T["Create Asset"]</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form id="createAssetForm">
<div class="modal-body">
<div class="row g-3">
<!-- Basic Info -->
<div class="col-md-6">
<label class="form-label">@T["Asset ID (Cn)"] *</label>
<input type="text" class="form-control" name="Cn" required />
</div>
<div class="col-md-6">
<label class="form-label">@T["Name"]</label>
<input type="text" class="form-control" name="Name" />
</div>
<div class="col-md-6">
<label class="form-label">@T["Location"]</label>
<input type="text" class="form-control" name="Location" />
</div>
<div class="col-md-6">
<label class="form-label">@T["Owner"]</label>
<input type="text" class="form-control" name="Owner" />
</div>
<div class="col-md-6">
<label class="form-label">@T["Serial Number"]</label>
<input type="text" class="form-control" name="SerialNumber" />
</div>
<hr class="my-3" />
<!-- Description Section -->
<h6 class="fw-bold">@T["Description"]</h6>
<div class="col-md-6">
<label class="form-label">@T["Type"]</label>
<input type="text" class="form-control" name="Description.Type" />
</div>
<div class="col-md-6">
<label class="form-label">@T["Make"]</label>
<input type="text" class="form-control" name="Description.Make" />
</div>
<div class="col-md-6">
<label class="form-label">@T["Model"]</label>
<input type="text" class="form-control" name="Description.Model" />
</div>
<!-- Attributes Section -->
<div class="col-12 mt-3">
<div class="d-flex justify-content-between align-items-center mb-2">
<h6 class="fw-bold mb-0">@T["Attributes"]</h6>
</div>
<div id="attributesContainer" class="d-flex flex-column gap-2">
<!-- Dynamic attribute rows will appear here -->
</div>
<button type="button" class="btn btn-sm btn-outline-success mt-3" id="addAttributeBtn">
@T["Add Attribute"]
</button>
</div>
<hr class="my-3" />
<!-- Purchase Info -->
<h6 class="fw-bold">@T["Purchase Information"]</h6>
<div class="col-md-6">
<label class="form-label">@T["Purchase Date"]</label>
<input type="date" class="form-control" name="Description.Purchase.PurchaseDate" />
</div>
<div class="col-md-6">
<label class="form-label">@T["Purchase Value"]</label>
<input type="text" class="form-control" name="Description.Purchase.PurchaseValue" />
</div>
<div class="col-md-6">
<label class="form-label">@T["Purchased At"]</label>
<input type="text" class="form-control" name="Description.Purchase.PurchasedAt" />
</div>
<div class="col-md-6">
<label class="form-label">@T["Purchased By"]</label>
<input type="text" class="form-control" name="Description.Purchase.PurchasedBy" />
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">@T["Cancel"]</button>
<button type="submit" class="btn btn-primary">@T["Create"]</button>
</div>
</form>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const attributesContainer = document.getElementById('attributesContainer');
const addAttributeBtn = document.getElementById('addAttributeBtn');
addAttributeBtn.addEventListener('click', () => {
const row = document.createElement('div');
row.className = 'd-flex gap-2 align-items-center attribute-row';
row.innerHTML = `
<input type="text" class="form-control" placeholder="Attribute name" data-attr-name />
<input type="text" class="form-control" placeholder="Attribute value" data-attr-value />
<button type="button" class="btn btn-outline-danger btn-sm btn-remove-attribute">✖</button>
`;
attributesContainer.appendChild(row);
});
attributesContainer.addEventListener('click', (e) => {
if (e.target.classList.contains('btn-remove-attribute')) {
e.target.closest('.attribute-row').remove();
}
});
const createForm = document.getElementById('createAssetForm');
const originalHandler = createForm.onsubmit;
createForm.addEventListener('submit', (e) => {
const formData = new FormData(createForm);
const jsonData = {};
for (const [key, value] of formData.entries()) {
if (!value) continue;
const keys = key.split('.');
let target = jsonData;
for (let i = 0; i < keys.length - 1; i++) {
target[keys[i]] = target[keys[i]] || {};
target = target[keys[i]];
}
target[keys[keys.length - 1]] = value;
}
const attributes = {};
document.querySelectorAll('#attributesContainer .attribute-row').forEach(row => {
const name = row.querySelector('[data-attr-name]').value.trim();
const value = row.querySelector('[data-attr-value]').value.trim();
if (name) attributes[name] = value;
});
if (Object.keys(attributes).length > 0) {
jsonData.Description = jsonData.Description || {};
jsonData.Description.Attributes = attributes;
}
e.preventDefault();
fetch('/Assets/Create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(jsonData)
})
.then(res => res.json())
.then(result => {
const createModalEl = document.getElementById('createAssetModal');
if (result.success) {
bootstrap.Modal.getInstance(createModalEl).hide();
createForm.reset();
attributesContainer.innerHTML = '';
showToast('Asset created successfully', 'success');
} else {
showToast(`${result.reason || 'Error creating asset'}`, 'danger');
}
})
.catch(err => {
console.error(err);
showToast('Error contacting server', 'danger');
});
});
});
</script>