whole project pushed

This commit is contained in:
2025-08-23 16:13:20 +03:30
parent 1cbde63229
commit 76a1e32e34
36 changed files with 1798 additions and 315 deletions

View File

@ -0,0 +1,300 @@
@model IEnumerable<boilerplate.Models.Client>
@{
ViewBag.Title = "مدیریت مشتریان";
Layout = "~/Views/_PanelSideBar.cshtml";
var currentUser = Session["User"] as boilerplate.Models.User;
}
<div class="card card-custom">
<div class="card-header">
<h3 class="card-title">@ViewBag.Title</h3>
<div class="card-toolbar">
<button type="button" class="btn btn-success font-weight-bolder mr-2" onclick="exportClients(event)">
<i class="fa fa-file-excel"></i>
خروجی اکسل
</button>
<button type="button" class="btn btn-primary font-weight-bolder" data-toggle="modal" data-target="#importModal">
<i class="fa fa-file-import"></i>
ورود از اکسل
</button>
</div>
</div>
<div class="card-body">
<table class="table table-hover">
<thead>
<tr>
<th>نام</th>
<th>نام خانوادگی</th>
<th>شماره تلفن</th>
<th>نام کاربری</th>
<th>ایمیل</th>
<th>عملیات</th>
</tr>
</thead>
<tbody>
@foreach (var client in Model)
{
<tr id="client-row-@client.Client_Id">
<td data-prop="Client_Name">@client.Client_Name</td>
<td data-prop="Client_LastName">@client.Client_LastName</td>
<td data-prop="Client_PhoneNumber">@client.Client_PhoneNumber</td>
<td data-prop="Client_UserName">@client.Client_UserName</td>
<td data-prop="Client_Email">@client.Client_Email</td>
<td>
<button class="btn btn-sm btn-clean btn-icon" title="ویرایش" onclick="openEditModal(@client.Client_Id)">
<i class="fa fa-edit text-primary"></i>
</button>
<button class="btn btn-sm btn-clean btn-icon" title="حذف" onclick="deleteClient(@client.Client_Id)">
<i class="fa fa-trash text-danger"></i>
</button>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<!-- Modal for Excel Upload -->
<div class="modal fade" id="importModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">ورود مشتریان از فایل اکسل</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p>فایل اکسل خود را انتخاب کنید. ستون‌ها باید به ترتیب زیر باشند: نام، نام خانوادگی، شماره تلفن، نام کاربری، ایمیل.</p>
<input type="file" id="excelFileInput" class="form-control-file" accept=".xlsx" />
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">انصراف</button>
<button type="button" class="btn btn-primary" id="importButton" onclick="importClients(event)">بارگذاری</button>
</div>
</div>
</div>
</div>
<!-- *** ADDED: Modal for Editing a Client *** -->
<div class="modal fade" id="editClientModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">ویرایش اطلاعات مشتری</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form id="editClientForm">
<input type="hidden" id="editClientId" />
<div class="form-group">
<label>نام</label>
<input type="text" id="editClientName" class="form-control" />
</div>
<div class="form-group">
<label>نام خانوادگی</label>
<input type="text" id="editClientLastName" class="form-control" />
</div>
<div class="form-group">
<label>شماره تلفن</label>
<input type="text" id="editClientPhone" class="form-control" />
</div>
<div class="form-group">
<label>نام کاربری</label>
<input type="text" id="editClientUsername" class="form-control" />
</div>
<div class="form-group">
<label>ایمیل</label>
<input type="email" id="editClientEmail" class="form-control" />
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">انصراف</button>
<button type="button" class="btn btn-primary" id="saveChangesBtn" onclick="saveChanges()">ذخیره تغییرات</button>
</div>
</div>
</div>
</div>
@section Script {
<script>
const authData = {
UserId: @(currentUser?.User_Id ?? 0),
Token: "@(currentUser?.User_Token ?? "")"
};
// *** FIXED: Re-added the full logic for importClients ***
function importClients(event) {
const fileInput = document.getElementById('excelFileInput');
if (fileInput.files.length === 0) {
toastr.error("لطفاً یک فایل اکسل انتخاب کنید.");
return;
}
const formData = new FormData();
formData.append("Auth", JSON.stringify(authData));
formData.append("ExcelFile", fileInput.files[0]);
const importBtn = event.target;
importBtn.disabled = true;
importBtn.innerHTML = '<span class="spinner-border spinner-border-sm"></span> در حال بارگذاری...';
fetch('/api/Client/Import', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.Status === "Success") {
toastr.success(data.Message || "فایل با موفقیت بارگذاری شد.");
setTimeout(() => location.reload(), 2000);
} else {
toastr.error("خطا در بارگذاری فایل: " + (data.Message || data.Status));
}
})
.catch(error => {
toastr.error("خطا در برقراری ارتباط با سرور.");
})
.finally(() => {
importBtn.disabled = false;
importBtn.innerHTML = 'بارگذاری';
$('#importModal').modal('hide');
});
}
// *** FIXED: Re-added the full logic for exportClients ***
function exportClients(event) {
const exportBtn = event.target;
exportBtn.disabled = true;
exportBtn.innerHTML = '<span class="spinner-border spinner-border-sm"></span> در حال آماده سازی...';
fetch('/api/Client/Export', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(authData)
})
.then(response => {
if (response.ok) return response.blob();
throw new Error('Network response was not ok.');
})
.then(blob => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = `Clients_${new Date().toISOString().slice(0, 10)}.xlsx`;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
toastr.success("فایل اکسل آماده دانلود است.");
})
.catch(error => {
toastr.error("خطا در ساخت فایل اکسل.");
})
.finally(() => {
exportBtn.disabled = false;
exportBtn.innerHTML = '<i class="fa fa-file-excel"></i> خروجی اکسل';
});
}
// Function to open the edit modal and fetch client data
function openEditModal(clientId) {
fetch(`/api/Client/Get/${clientId}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(authData)
})
.then(response => response.json())
.then(client => {
$('#editClientId').val(client.Client_Id);
$('#editClientName').val(client.Client_Name);
$('#editClientLastName').val(client.Client_LastName);
$('#editClientPhone').val(client.Client_PhoneNumber);
$('#editClientUsername').val(client.Client_UserName);
$('#editClientEmail').val(client.Client_Email);
$('#editClientModal').modal('show');
})
.catch(error => toastr.error("خطا در دریافت اطلاعات مشتری."));
}
// Function to save the changes from the edit modal
function saveChanges() {
const saveBtn = document.getElementById('saveChangesBtn');
saveBtn.disabled = true;
saveBtn.innerHTML = '<span class="spinner-border spinner-border-sm"></span> در حال ذخیره...';
const clientData = {
Client_Id: parseInt($('#editClientId').val()),
Client_Name: $('#editClientName').val(),
Client_LastName: $('#editClientLastName').val(),
Client_PhoneNumber: $('#editClientPhone').val(),
Client_UserName: $('#editClientUsername').val(),
Client_Email: $('#editClientEmail').val()
};
const updateModel = {
Auth: authData,
Client: clientData
};
fetch('/api/Client/Update', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(updateModel)
})
.then(response => response.json())
.then(data => {
if (data.Status === "Success") {
toastr.success("اطلاعات مشتری با موفقیت ویرایش شد.");
const row = $(`#client-row-${clientData.Client_Id}`);
row.find('[data-prop="Client_Name"]').text(clientData.Client_Name);
row.find('[data-prop="Client_LastName"]').text(clientData.Client_LastName);
row.find('[data-prop="Client_PhoneNumber"]').text(clientData.Client_PhoneNumber);
row.find('[data-prop="Client_UserName"]').text(clientData.Client_UserName);
row.find('[data-prop="Client_Email"]').text(clientData.Client_Email);
$('#editClientModal').modal('hide');
} else {
toastr.error("خطا در ویرایش: " + (data.Message || data.Status));
}
})
.catch(error => toastr.error("خطا در برقراری ارتباط با سرور."))
.finally(() => {
saveBtn.disabled = false;
saveBtn.innerHTML = 'ذخیره تغییرات';
});
}
// JavaScript function to delete a client
function deleteClient(clientId) {
if (!confirm("آیا از حذف این مشتری مطمئن هستید؟")) {
return;
}
const deleteAuthData = { ...authData, Id: clientId };
fetch('/api/Client/Delete', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(deleteAuthData)
})
.then(response => response.json())
.then(data => {
if (data.Status === "Success") {
toastr.success("مشتری با موفقیت حذف شد.");
$("#client-row-" + clientId).fadeOut(500, function() { $(this).remove(); });
} else {
toastr.error("خطا در حذف مشتری: " + (data.Message || data.Status));
}
})
.catch(error => {
toastr.error("خطا در برقراری ارتباط با سرور.");
});
}
</script>
}