Added Feedback section.

This commit is contained in:
2024-04-23 19:30:56 +05:00
parent 491249c8d8
commit 8c353a49b7
44 changed files with 1050 additions and 0 deletions

View File

@@ -1,5 +1,6 @@
@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,700;1,400;1,700&display=swap');
@import "reset";
@import "forms";
html,
body {

View File

@@ -0,0 +1,86 @@
.form-block {
padding: 10px 0;
label {
display: block;
font-size: 16px;
font-weight: 600;
padding-bottom: 7px;
color: #000;
span {
font-size: 14px;
font-weight: 400;
color: #555;
}
}
.form-control {
display: block;
width: 100%;
padding: 6px 12px;
border-radius: 6px;
border: 1px solid #ddd;
}
.form-control.is-invalid {
border-color: #dc3545;
}
.form-control:focus,
.form-control:focus-visible {
outline: 2px solid #006ce7;
}
.invalid-feedback {
display: block;
padding: 7px 10px;
color: #dc3545;
font-size: 14px;
border: 1px solid #dc3545;
border-radius: 6px;
margin-top: 10px;
margin-bottom: 10px;
}
}
.button {
background: #006ce7;
border: 1px solid #002452;
border-radius: 6px;
cursor: pointer;
font-weight: 600;
font-size: 16px;
padding: 14px 24px;
color: #fff;
}
.button:hover {
opacity: 0.8;
border-color: #006ce7;
color: #ccc;
}
.captcha-service-kor-elf {
position: relative;
z-index: 10;
}
.alert {
border-radius: 6px;
font-size: 16px;
padding: 14px 24px;
ul {
padding: 0;
margin: 0;
list-style: none;
}
}
.alert.alert-success {
border: 1px solid #0a6f4d;
color: #0a6f4d;
}
.alert.alert-danger {
border: 1px solid #dc3545;
color: #dc3545;
}

View File

@@ -26,6 +26,22 @@
</li>
@endcan
@can('viewAny', \App\Models\ProjectFeedback::class)
<li @class([
'nav-item',
'active' => request()->route()->named('admin.feedbacks.*'),
])>
<a href="{{ route('admin.feedbacks.index') }}" class="nav-link">
<span class="sidebar-icon">
<svg class="icon icon-xs me-2" data-slot="icon" fill="none" stroke-width="1.5" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M8.625 12a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0H8.25m4.125 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0H12m4.125 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0h-.375M21 12c0 4.556-4.03 8.25-9 8.25a9.764 9.764 0 0 1-2.555-.337A5.972 5.972 0 0 1 5.41 20.97a5.969 5.969 0 0 1-.474-.065 4.48 4.48 0 0 0 .978-2.025c.09-.457-.133-.901-.467-1.226C3.93 16.178 3 14.189 3 12c0-4.556 4.03-8.25 9-8.25s9 3.694 9 8.25Z"></path>
</svg>
</span>
<span class="sidebar-text">{{ __('admin-sections.Feedback') }}</span>
</a>
</li>
@endcan
@can('viewAny', \App\Models\User::class)
<li @class([
'nav-item',

View File

@@ -0,0 +1,37 @@
@section('meta_title', __('admin-sections.Feedback'))
@section('h1', __('admin-sections.Feedback'))
<x-admin.layout>
<div class="card border-0 shadow mb-4">
<div class="card-body">
<div class="table-responsive">
<table class="table table-centered table-nowrap mb-0 rounded">
<thead class="thead-light">
<tr>
<th class="border-0">{{ __('admin-sections.Project') }}</th>
<th class="border-0" style="width: 100%;">{{ __('site.attributes.message') }}</th>
<th class="border-0">{{ __('site.attributes.name') }}</th>
<th class="border-0">{{ __('site.attributes.email') }}</th>
</tr>
</thead>
<tbody>
@foreach($feedbacks as $feedback)
<tr>
<td>{{ $feedback->project->name }}</td>
<td>{!! $feedback->message !!}</td>
<td>
<p>{{ $feedback->name }}</p>
<p><strong>IP:</strong> {{ $feedback->ip }}</p>
<p><strong>UserAgent:</strong> {{ $feedback->user_agent }}</p>
</td>
<td>{{ $feedback->email }}</td>
</tr>
@endforeach
</tbody>
</table>
<div class="card-footer border-0">
{{ $feedbacks->links() }}
</div>
</div>
</div>
</div>
</x-admin.layout>

View File

@@ -0,0 +1,36 @@
@section('meta_title', __('admin-sections.Project') . ': ' . $project->name . ' - ' . __('admin-sections.Feedback'))
@section('h1', __('admin-sections.Project') . ': ' . $project->name)
<x-admin.layout>
<div class="card border-0 shadow mb-4">
<div class="card-body">
<h3 id="category" class="mb-4">{{ __('admin-sections.Feedback') }}</h3>
<div class="table-responsive">
<table class="table table-centered table-nowrap mb-0 rounded">
<thead class="thead-light">
<tr>
<th class="border-0" style="width: 100%;">{{ __('site.attributes.message') }}</th>
<th class="border-0">{{ __('site.attributes.name') }}</th>
<th class="border-0">{{ __('site.attributes.email') }}</th>
</tr>
</thead>
<tbody>
@foreach($feedbacks as $feedback)
<tr>
<td>{!! $feedback->message !!}</td>
<td>
<p>{{ $feedback->name }}</p>
<p><strong>IP:</strong> {{ $feedback->ip }}</p>
<p><strong>UserAgent:</strong> {{ $feedback->user_agent }}</p>
</td>
<td>{{ $feedback->email }}</td>
</tr>
@endforeach
</tbody>
</table>
<div class="card-footer border-0">
{{ $feedbacks->links() }}
</div>
</div>
</div>
</div>
</x-admin.layout>

View File

@@ -48,6 +48,18 @@
</td>
</tr>
@endcan
@can('viewAny', \App\Models\ProjectFeedback::class)
<tr>
<td>
<a href="{{ route('admin.projects.feedbacks.index', ['project' => $project->id]) }}" class="fw-bold">
<svg width="16" height="16" class="align-text-top" data-slot="icon" fill="none" stroke-width="1.5" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M8.625 12a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0H8.25m4.125 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0H12m4.125 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0h-.375M21 12c0 4.556-4.03 8.25-9 8.25a9.764 9.764 0 0 1-2.555-.337A5.972 5.972 0 0 1 5.41 20.97a5.969 5.969 0 0 1-.474-.065 4.48 4.48 0 0 0 .978-2.025c.09-.457-.133-.901-.467-1.226C3.93 16.178 3 14.189 3 12c0-4.556 4.03-8.25 9-8.25s9 3.694 9 8.25Z"></path>
</svg>
{{ __('admin-sections.Feedback') }}
</a>
</td>
</tr>
@endcan
</tbody>
</table>
</div>

View File

@@ -0,0 +1,12 @@
<div class="form-block">
<label for="form-input-{{ $requestName }}">
{{ $title }}
@if($attributes->get('required'))
<span>{{ $websiteTranslations->translate('site.required field') }}</span>
@endif
</label>
<input id="form-input-{{ $requestName }}" class="form-control @error($requestName) is-invalid @enderror" name="{{ $name }}" type="{{ $type }}" @if($type !== 'password') value="{{ $value }}" @endif {{ $attributes }}>
@error($requestName)
<span class="invalid-feedback">{{ $message }}</span>
@enderror
</div>

View File

@@ -0,0 +1,36 @@
<div class="form-block">
<label for="form-textarea-wysiwyg-{{ $requestName }}">
{{ $title }}
@if($attributes->get('required'))
<span>{{ $websiteTranslations->translate('site.required field') }}</span>
@endif
</label>
<textarea class="form-control textarea-tinymce @error($requestName) is-invalid @enderror" name="{{ $name }}" id="form-textarea-wysiwyg-{{ $requestName }}" rows="3">{{ $value }}</textarea>
@error($requestName)
<span class="invalid-feedback">{{ $message }}</span>
@enderror
</div>
@pushOnce('scripts')
<script src="{{ asset('/build/tinymce/tinymce.min.js') }}" referrerpolicy="origin"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
tinymce.init({
selector: '.textarea-tinymce',
@if(in_array(app()->getLocale(), ['ru'], true))
language: '{{ app()->getLocale() }}',
@endif
license_key: '{{ $tinymceLicenseKey }}',
plugins: 'emoticons lists table',
toolbar: 'bold italic | bullist numlist table | emoticons',
menubar: false,
mobile: {
menubar: false,
plugins: 'emoticons lists table',
toolbar: 'bold italic bullist numlist table emoticons',
},
referrer_policy: 'origin',
});
});
</script>
@endpushonce

View File

@@ -37,11 +37,16 @@
<div class="menu__title">{{ __('site.Menu') }}</div>
<ul>
<li><a href="{{ \App\Enums\Site\ProjectSection::Home->url($project, $websiteTranslations->getLanguage()) }}" @class(['active' => request()->route()->named(['home', 'language.home', 'project.home', 'project.language.home'])])>{{ $websiteTranslations->translate('site.About project') }}</a></li>
<li><a href="{{ \App\Enums\Site\ProjectSection::Feedback->url($project, $websiteTranslations->getLanguage()) }}" @class(['active' => request()->route()->named(['feedback', 'language.feedback', 'project.feedback', 'project.language.feedback'])])>{{ $websiteTranslations->translate('site.Feedback') }}</a></li>
</ul>
</nav>
<div class="section-container">
<div class="content">
<h1>@yield('h1', '')</h1>
@includeWhen($errors->any(), 'layout.site._errors', ['errors' => $errors->all()])
@includeWhen(Session::has('success'), 'layout.site._success', ['success' => Session::get('success')])
{{ $slot }}
</div>
<footer class="footer">
@@ -51,5 +56,6 @@
</div>
</div>
@vite('resources/site/js/app.js')
@stack('scripts')
</body>
</html>

View File

@@ -0,0 +1,7 @@
<div class="alert alert-danger">
<ul>
@foreach($errors as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>

View File

@@ -0,0 +1,3 @@
<div class="alert alert-success">
{{ $success }}
</div>

View File

@@ -0,0 +1,22 @@
@section('meta_title', $websiteTranslations->translate('site.Feedback'))
@section('h1', $websiteTranslations->translate('site.Feedback'))
<x-site.layout :project="$project" :websiteTranslations="$websiteTranslations">
@if(Session::has('success') !== true)
<form method="post" action="{{ \App\Enums\Site\ProjectSection::FeedbackSend->url($project, $websiteTranslations->getLanguage()) }}">
@csrf
<x-site.forms.input :title="$websiteTranslations->translate('site.attributes.name')" :websiteTranslations="$websiteTranslations" name="name" type="text" value="" autofocus />
<x-site.forms.input :title="$websiteTranslations->translate('site.attributes.email')" :websiteTranslations="$websiteTranslations" name="email" type="text" value="" />
<x-site.forms.textarea-wysiwyg :title="$websiteTranslations->translate('site.attributes.message')" :websiteTranslations="$websiteTranslations" required name="message" value="" />
<div class="form-block">
@captcha
@error('captcha-verified')
<span class="invalid-feedback">{{ $message }}</span>
@enderror
</div>
<div class="form-block">
<button class="button" type="submit">{{ $websiteTranslations->translate('site.Feedback-send') }}</button>
</div>
</form>
@endif
</x-site.layout>