301 lines
13 KiB
Plaintext
301 lines
13 KiB
Plaintext
@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">×</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">×</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>
|
|
}
|