First Commit
This commit is contained in:
Executable
+157
@@ -0,0 +1,157 @@
|
||||
{% extends "layouts/dashboard.twig" %}
|
||||
|
||||
{% block title %}{{ title }} - {{ platformName }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container-fluid px-4">
|
||||
<h1 class="mt-4">{{ title }}</h1>
|
||||
<ol class="breadcrumb mb-4">
|
||||
<li class="breadcrumb-item"><a href="{{ url('admin/dashboard') }}">{{ __('dashboard.title') }}</a></li>
|
||||
<li class="breadcrumb-item active">{{ __('contact.admin.title') }}</li>
|
||||
</ol>
|
||||
|
||||
<div class="mb-4">
|
||||
<div class="btn-group" role="group">
|
||||
<a href="{{ url('admin/contacts?status=all') }}" class="btn {{ current_status == 'all' ? 'btn-primary' : 'btn-outline-primary' }}">
|
||||
{{ __('contact.admin.statuses.all') }}
|
||||
</a>
|
||||
<a href="{{ url('admin/contacts?status=unread') }}" class="btn {{ current_status == 'unread' ? 'btn-primary' : 'btn-outline-primary' }}">
|
||||
{{ __('contact.admin.statuses.unread') }}
|
||||
</a>
|
||||
<a href="{{ url('admin/contacts?status=read') }}" class="btn {{ current_status == 'read' ? 'btn-primary' : 'btn-outline-primary' }}">
|
||||
{{ __('contact.admin.statuses.read') }}
|
||||
</a>
|
||||
<a href="{{ url('admin/contacts?status=new') }}" class="btn {{ current_status == 'new' ? 'btn-primary' : 'btn-outline-primary' }}">
|
||||
{{ __('contact.admin.statuses.new') }}
|
||||
</a>
|
||||
<a href="{{ url('admin/contacts?status=in_progress') }}" class="btn {{ current_status == 'in_progress' ? 'btn-primary' : 'btn-outline-primary' }}">
|
||||
{{ __('contact.admin.statuses.in_progress') }}
|
||||
</a>
|
||||
<a href="{{ url('admin/contacts?status=resolved') }}" class="btn {{ current_status == 'resolved' ? 'btn-primary' : 'btn-outline-primary' }}">
|
||||
{{ __('contact.admin.statuses.resolved') }}
|
||||
</a>
|
||||
<a href="{{ url('admin/contacts?status=closed') }}" class="btn {{ current_status == 'closed' ? 'btn-primary' : 'btn-outline-primary' }}">
|
||||
{{ __('contact.admin.statuses.closed') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<i class="bi bi-envelope me-1"></i>
|
||||
{{ __('contact.admin.list_title') }}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ __('contact.admin.columns.name') }}</th>
|
||||
<th>{{ __('contact.admin.columns.email') }}</th>
|
||||
<th>{{ __('contact.admin.columns.subject') }}</th>
|
||||
<th>{{ __('contact.admin.columns.status') }}</th>
|
||||
<th>{{ __('contact.admin.columns.date') }}</th>
|
||||
<th>{{ __('contact.admin.columns.actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for contact in contacts %}
|
||||
<tr class="{{ not contact.isRead() ? 'table-primary' : '' }}">
|
||||
<td>
|
||||
{% if not contact.isRead() %}
|
||||
<i class="bi bi-envelope-fill text-primary me-1"></i>
|
||||
{% else %}
|
||||
<i class="bi bi-envelope-open text-muted me-1"></i>
|
||||
{% endif %}
|
||||
{{ contact.contacts_name }}
|
||||
</td>
|
||||
<td>{{ contact.contacts_email }}</td>
|
||||
<td>{{ contact.contacts_subject }}</td>
|
||||
<td>
|
||||
{% set statusColors = {
|
||||
'new': 'primary',
|
||||
'in_progress': 'warning',
|
||||
'resolved': 'success',
|
||||
'closed': 'secondary'
|
||||
} %}
|
||||
<span class="badge bg-{{ statusColors[contact.contacts_status] ?? 'secondary' }}">
|
||||
{{ __('contact.admin.statuses.' ~ contact.contacts_status) }}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ contact.formatted_created_at }}</td>
|
||||
<td>
|
||||
<a href="{{ url('admin/contacts/' ~ contact.contacts_id) }}" class="btn btn-info btn-sm" title="{{ __('contact.admin.actions.view') }}">
|
||||
<i class="bi bi-eye"></i>
|
||||
</a>
|
||||
<button type="button" class="btn btn-sm {{ contact.isRead() ? 'btn-secondary' : 'btn-success' }}"
|
||||
onclick="toggleReadStatus({{ contact.contacts_id }})"
|
||||
title="{{ contact.isRead() ? __('contact.admin.actions.mark_unread') : __('contact.admin.actions.mark_read') }}">
|
||||
<i class="bi {{ contact.isRead() ? 'bi-envelope' : 'bi-envelope-check' }}"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-danger btn-sm"
|
||||
onclick="deleteContact({{ contact.contacts_id }})"
|
||||
title="{{ __('contact.admin.actions.delete') }}">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="6" class="text-center">{{ __('contact.admin.no_messages') }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function toggleReadStatus(id) {
|
||||
fetch(`{{ url('admin/contacts/') }}${id}/toggle-read`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
location.reload();
|
||||
} else {
|
||||
alert(data.message || '{{ __("contact.admin.error_occurred") }}');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
alert('{{ __("contact.admin.error_occurred") }}');
|
||||
});
|
||||
}
|
||||
|
||||
function deleteContact(id) {
|
||||
if (confirm("{{ __('contact.admin.confirm_delete') }}")) {
|
||||
fetch(`{{ url('admin/contacts/') }}${id}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
location.reload();
|
||||
} else {
|
||||
alert(data.message || '{{ __("contact.admin.error_occurred") }}');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
alert('{{ __("contact.admin.error_occurred") }}');
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
Executable
+212
@@ -0,0 +1,212 @@
|
||||
{% extends "layouts/dashboard.twig" %}
|
||||
|
||||
{% block title %}{{ title }} - {{ platformName }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container-fluid px-4">
|
||||
<h1 class="mt-4">{{ title }}</h1>
|
||||
<ol class="breadcrumb mb-4">
|
||||
<li class="breadcrumb-item"><a href="{{ url('admin/dashboard') }}">{{ __('dashboard.title') }}</a></li>
|
||||
<li class="breadcrumb-item"><a href="{{ url('admin/contacts') }}">{{ __('contact.admin.title') }}</a></li>
|
||||
<li class="breadcrumb-item active">{{ contact.contacts_subject }}</li>
|
||||
</ol>
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<i class="bi bi-envelope me-1"></i>
|
||||
{{ __('contact.admin.details_title') }}
|
||||
</div>
|
||||
<div>
|
||||
{% set statusColors = {
|
||||
'new': 'primary',
|
||||
'in_progress': 'warning',
|
||||
'resolved': 'success',
|
||||
'closed': 'secondary'
|
||||
} %}
|
||||
<span class="badge bg-{{ statusColors[contact.contacts_status] ?? 'secondary' }}">
|
||||
{{ __('contact.admin.statuses.' ~ contact.contacts_status) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label fw-bold">{{ __('contact.admin.fields.name') }}</label>
|
||||
<div class="col-sm-10">
|
||||
<p class="form-control-plaintext">{{ contact.contacts_name }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label fw-bold">{{ __('contact.admin.fields.email') }}</label>
|
||||
<div class="col-sm-10">
|
||||
<p class="form-control-plaintext">
|
||||
<a href="mailto:{{ contact.contacts_email }}">{{ contact.contacts_email }}</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if contact.contacts_phone %}
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label fw-bold">{{ __('contact.admin.fields.phone') }}</label>
|
||||
<div class="col-sm-10">
|
||||
<p class="form-control-plaintext">{{ contact.contacts_phone }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label fw-bold">{{ __('contact.admin.fields.subject') }}</label>
|
||||
<div class="col-sm-10">
|
||||
<p class="form-control-plaintext">{{ contact.contacts_subject }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label fw-bold">{{ __('contact.admin.fields.message') }}</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="border rounded p-3 bg-light">
|
||||
{{ contact.contacts_message|nl2br }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label fw-bold">{{ __('contact.admin.fields.response') }}</label>
|
||||
<div class="col-sm-10">
|
||||
<form action="{{ url('admin/contacts/' ~ contact.contacts_id ~ '/response') }}" method="POST">
|
||||
<div class="mb-3">
|
||||
<textarea class="form-control" id="response" name="response" rows="5" placeholder="{{ __('contact.admin.placeholders.response') }}">{{ contact.contacts_response }}</textarea>
|
||||
</div>
|
||||
<div class="text-end">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="bi bi-reply me-1"></i> {{ __('contact.admin.actions.save_response') }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label fw-bold">{{ __('contact.admin.fields.ip_address') }}</label>
|
||||
<div class="col-sm-10">
|
||||
<p class="form-control-plaintext">{{ contact.contacts_ip_address }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label fw-bold">{{ __('contact.admin.fields.date') }}</label>
|
||||
<div class="col-sm-10">
|
||||
<p class="form-control-plaintext">{{ contact.formatted_created_at }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label fw-bold">{{ __('contact.admin.columns.status') }}</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="btn-group" role="group">
|
||||
<button type="button" class="btn btn-sm dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
{{ __('contact.admin.statuses.' ~ contact.contacts_status) }}
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="#" onclick="updateStatus('new')">{{ __('contact.admin.statuses.new') }}</a></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="updateStatus('in_progress')">{{ __('contact.admin.statuses.in_progress') }}</a></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="updateStatus('resolved')">{{ __('contact.admin.statuses.resolved') }}</a></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="updateStatus('closed')">{{ __('contact.admin.statuses.closed') }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-10 offset-sm-2">
|
||||
<button type="button" class="btn btn-secondary me-2" onclick="toggleReadStatus()">
|
||||
<i class="bi {{ contact.isRead() ? 'bi-envelope' : 'bi-envelope-check' }}"></i>
|
||||
{{ contact.isRead() ? __('contact.admin.actions.mark_unread') : __('contact.admin.actions.mark_read') }}
|
||||
</button>
|
||||
<a href="{{ url('admin/contacts') }}" class="btn btn-outline-secondary">
|
||||
<i class="bi bi-arrow-left"></i> {{ __('contact.admin.actions.back') }}
|
||||
</a>
|
||||
<button type="button" class="btn btn-danger float-end" onclick="deleteContact()">
|
||||
<i class="bi bi-trash"></i> {{ __('contact.admin.actions.delete') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
function updateStatus(status) {
|
||||
fetch(`{{ url('admin/contacts/') }}{{ contact.contacts_id }}/status`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
status: status
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
location.reload();
|
||||
} else {
|
||||
alert(data.message || '{{ __("contact.admin.error_occurred") }}');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
alert('{{ __("contact.admin.error_occurred") }}');
|
||||
});
|
||||
}
|
||||
|
||||
function toggleReadStatus() {
|
||||
fetch(`{{ url('admin/contacts/') }}{{ contact.contacts_id }}/toggle-read`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
location.reload();
|
||||
} else {
|
||||
alert(data.message || '{{ __("contact.admin.error_occurred") }}');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
alert('{{ __("contact.admin.error_occurred") }}');
|
||||
});
|
||||
}
|
||||
|
||||
function deleteContact() {
|
||||
if (confirm("{{ __('contact.admin.confirm_delete') }}")) {
|
||||
fetch(`{{ url('admin/contacts/') }}{{ contact.contacts_id }}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
window.location.href = '{{ url("admin/contacts") }}';
|
||||
} else {
|
||||
alert(data.message || '{{ __("contact.admin.error_occurred") }}');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
alert('{{ __("contact.admin.error_occurred") }}');
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user