Added an appointment cancellation button
This commit is contained in:
parent
5c536e0c0b
commit
fce6e92d9d
@ -25,6 +25,7 @@ use App\Application;
|
|||||||
use App\Appointment;
|
use App\Appointment;
|
||||||
use App\Exceptions\InvalidAppointmentException;
|
use App\Exceptions\InvalidAppointmentException;
|
||||||
use App\Exceptions\InvalidAppointmentStatusException;
|
use App\Exceptions\InvalidAppointmentStatusException;
|
||||||
|
use App\Http\Requests\CancelAppointmentRequest;
|
||||||
use App\Http\Requests\SaveNotesRequest;
|
use App\Http\Requests\SaveNotesRequest;
|
||||||
use App\Services\AppointmentService;
|
use App\Services\AppointmentService;
|
||||||
use App\Services\MeetingNoteService;
|
use App\Services\MeetingNoteService;
|
||||||
@ -61,7 +62,7 @@ class AppointmentController extends Controller
|
|||||||
/**
|
/**
|
||||||
* @throws AuthorizationException
|
* @throws AuthorizationException
|
||||||
*/
|
*/
|
||||||
public function updateAppointment(Application $application, $status): RedirectResponse
|
public function updateAppointment(Application $application, string $status): RedirectResponse
|
||||||
{
|
{
|
||||||
$this->authorize('update', $application->appointment);
|
$this->authorize('update', $application->appointment);
|
||||||
|
|
||||||
@ -78,10 +79,32 @@ class AppointmentController extends Controller
|
|||||||
->back()
|
->back()
|
||||||
->with('error', $ex->getMessage());
|
->with('error', $ex->getMessage());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deleteAppointment(CancelAppointmentRequest $request, Application $application)
|
||||||
|
{
|
||||||
|
$this->authorize('update', $application->appointment);
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
$this->appointmentService->deleteAppointment($application, $request->reason);
|
||||||
|
|
||||||
|
return redirect()
|
||||||
|
->back()
|
||||||
|
->with('success', __('Appointment cancelled.'));
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (\Exception $ex) {
|
||||||
|
return redirect()
|
||||||
|
->back()
|
||||||
|
->with('error', $ex->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function saveNotes(SaveNotesRequest $request, Application $application)
|
public function saveNotes(SaveNotesRequest $request, Application $application)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
30
app/Http/Requests/CancelAppointmentRequest.php
Normal file
30
app/Http/Requests/CancelAppointmentRequest.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class CancelAppointmentRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'reason' => 'string|required'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
78
app/Notifications/AppointmentCancelled.php
Normal file
78
app/Notifications/AppointmentCancelled.php
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Notifications;
|
||||||
|
|
||||||
|
use App\Application;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Notifications\Messages\MailMessage;
|
||||||
|
use Illuminate\Notifications\Notification;
|
||||||
|
|
||||||
|
class AppointmentCancelled extends Notification
|
||||||
|
{
|
||||||
|
use Queueable;
|
||||||
|
|
||||||
|
private $application;
|
||||||
|
private $reason;
|
||||||
|
private $appointmentDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new notification instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(Application $app, Carbon $appointmentDate, $reason)
|
||||||
|
{
|
||||||
|
$this->application = $app;
|
||||||
|
$this->reason = $reason;
|
||||||
|
$this->appointmentDate = $appointmentDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the notification's delivery channels.
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function via($notifiable)
|
||||||
|
{
|
||||||
|
return ['mail'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the mail representation of the notification.
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||||
|
*/
|
||||||
|
public function toMail($notifiable)
|
||||||
|
{
|
||||||
|
// TODO: Switch to HTML & Blade.
|
||||||
|
|
||||||
|
return (new MailMessage)
|
||||||
|
->from(config('notification.sender.address'), config('notification.sender.name'))
|
||||||
|
->subject(config('app.name').' - Interview Cancelled')
|
||||||
|
->greeting("Hi " . explode(' ', $this->application->user->name, 2)[0] . ",")
|
||||||
|
->line('The interview that was previously scheduled with you has been cancelled by a staff member.')
|
||||||
|
->line('Date & time of the old appointment: '.$this->appointmentDate)
|
||||||
|
->line('Your appointment was cancelled for the following reason: ' . $this->reason)
|
||||||
|
->line('A staff member may contact you to reschedule within a new timeframe - you may also let us know of a date and time that suits you.')
|
||||||
|
->line('Your application will be automatically rejected within 7 days if an interview is not scheduled.')
|
||||||
|
->action('View ongoing applications', url(route('showUserApps')))
|
||||||
|
->line('Thank you!');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the array representation of the notification.
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function toArray($notifiable)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -64,11 +64,11 @@ class AppointmentScheduled extends Notification implements ShouldQueue
|
|||||||
{
|
{
|
||||||
return (new MailMessage)
|
return (new MailMessage)
|
||||||
->from(config('notification.sender.address'), config('notification.sender.name'))
|
->from(config('notification.sender.address'), config('notification.sender.name'))
|
||||||
->subject(config('app.name').' - Interview scheduled')
|
->subject(config('app.name').' - Interview Scheduled')
|
||||||
->line('A voice interview has been scheduled for you @ '.$this->appointment->appointmentDate.'.')
|
->line('A voice interview has been scheduled for you @ '.$this->appointment->appointmentDate.'.')
|
||||||
->line('With the following details: '.$this->appointment->appointmentDescription)
|
->line('With the following details: '.$this->appointment->appointmentDescription)
|
||||||
->line('This meeting will take place @ '.$this->appointment->appointmentLocation.'. You will receive an email soon with details on how to join this meeting.')
|
->line('This meeting will take place @ '.$this->appointment->appointmentLocation.'. You will receive an email soon with details on how to join this meeting.')
|
||||||
->line('You are expected to show up at least 5 minutes before the scheduled date.')
|
->line('Please join a public voice channel (or another platform if specified) at around this time.')
|
||||||
->action('Sign in', url(route('login')))
|
->action('Sign in', url(route('login')))
|
||||||
->line('Thank you!');
|
->line('Thank you!');
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ use App\Application;
|
|||||||
use App\Appointment;
|
use App\Appointment;
|
||||||
use App\Exceptions\InvalidAppointmentStatusException;
|
use App\Exceptions\InvalidAppointmentStatusException;
|
||||||
use App\Notifications\ApplicationMoved;
|
use App\Notifications\ApplicationMoved;
|
||||||
|
use App\Notifications\AppointmentCancelled;
|
||||||
use App\Notifications\AppointmentScheduled;
|
use App\Notifications\AppointmentScheduled;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
@ -25,6 +26,15 @@ class AppointmentService
|
|||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules an appointment for the provided application.
|
||||||
|
*
|
||||||
|
* @param Application $application The target application.
|
||||||
|
* @param Carbon $appointmentDate The appointment's date and time.
|
||||||
|
* @param string $appointmentDescription The appointment description.
|
||||||
|
* @param string $appointmentLocation The appointment location.
|
||||||
|
* @return bool Whether the appointment was scheduled.
|
||||||
|
*/
|
||||||
public function createAppointment(Application $application, Carbon $appointmentDate, $appointmentDescription, $appointmentLocation)
|
public function createAppointment(Application $application, Carbon $appointmentDate, $appointmentDescription, $appointmentLocation)
|
||||||
{
|
{
|
||||||
$appointment = Appointment::create([
|
$appointment = Appointment::create([
|
||||||
@ -46,6 +56,32 @@ class AppointmentService
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancels an appointment for the provided application.
|
||||||
|
*
|
||||||
|
* @param Application $application The target application.
|
||||||
|
* @param string $reason The reason for cancelling the appointment.
|
||||||
|
* @throws \Exception Thrown when there's no appointment to cancel
|
||||||
|
*/
|
||||||
|
public function deleteAppointment(Application $application, string $reason): bool
|
||||||
|
{
|
||||||
|
if (!empty($application->appointment))
|
||||||
|
{
|
||||||
|
$application->user->notify(new AppointmentCancelled($application, Carbon::parse($application->appointment->appointmentDate), $reason));
|
||||||
|
$application->appointment->delete();
|
||||||
|
|
||||||
|
$application->setStatus('STAGE_INTERVIEW');
|
||||||
|
|
||||||
|
Log::info('User '.Auth::user()->name.' cancelled an appointment with '.$application->user->name.' for application ID'.$application->id);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \Exception("This application doesn't have an appointment!");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the appointment with the new $status.
|
* Updates the appointment with the new $status.
|
||||||
* It also sets the application's status to peer approval.
|
* It also sets the application's status to peer approval.
|
||||||
|
@ -67,12 +67,37 @@
|
|||||||
@method('PATCH')
|
@method('PATCH')
|
||||||
<button type="submit" class="btn btn-danger">{{__('messages.view_app.deny_confirm_btn')}}</button>
|
<button type="submit" class="btn btn-danger">{{__('messages.view_app.deny_confirm_btn')}}</button>
|
||||||
</form>
|
</form>
|
||||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">{{__('messages.modal_close')}}</button>
|
|
||||||
|
|
||||||
</x-slot>
|
</x-slot>
|
||||||
|
|
||||||
</x-modal>
|
</x-modal>
|
||||||
|
|
||||||
|
|
||||||
|
<x-modal id="cancelAppointmentModal" modal-label="cancelAppointmentModalLabel" modal-title="{{__('Cancel appointment?')}}" include-close-button="true">
|
||||||
|
|
||||||
|
<div class="alert alert-warning">
|
||||||
|
<p class="text-bold"><i class="fas fa-exclamation-triangle"></i> {{ __('Caution') }}</p>
|
||||||
|
|
||||||
|
<p>{{__('Are you sure you want to cancel this appointment? The user will be notified of this via email, and you will be able to reschedule.')}}</p>
|
||||||
|
<p>{{ __('Before you can cancel this appointment, you\'ll need to provide a reason in writing. ') }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form id="confirmCancelAppointment" method="POST" action="{{ route('deleteAppointment', ['application' => $application->id]) }}">
|
||||||
|
@method('DELETE')
|
||||||
|
@csrf
|
||||||
|
<div class="input-group mb-3">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text"><i class="fas fa-comment"></i></span>
|
||||||
|
</div>
|
||||||
|
<input type="text" name="reason" id="reason" class="form-control" placeholder="{{ __('Cancellation reason...') }}" required>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<x-slot name="modalFooter">
|
||||||
|
<button type="button" class="btn btn-warning" onclick="$('#confirmCancelAppointment').submit()"><i class="fas fa-calendar-times""></i> {{ __('Finish cancelling appointment') }}</button>
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
</x-modal>
|
||||||
|
|
||||||
@endhasrole
|
@endhasrole
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@ -290,12 +315,13 @@
|
|||||||
<form style="white-space: nowrap;display:inline-block" class="footer-button" action="{{route('updateAppointment', ['application' => $application->id, 'status' => 'concluded'])}}" method="POST">
|
<form style="white-space: nowrap;display:inline-block" class="footer-button" action="{{route('updateAppointment', ['application' => $application->id, 'status' => 'concluded'])}}" method="POST">
|
||||||
@csrf
|
@csrf
|
||||||
@method('PATCH')
|
@method('PATCH')
|
||||||
<button type="submit" class="btn btn-success">{{__('messages.view_app.finish_meeting')}}</button>
|
<button type="submit" class="btn btn-success btn-sm"><i class="fas fa-check"></i> {{__('messages.view_app.finish_meeting')}}</button>
|
||||||
</form>
|
</form>
|
||||||
|
<button type="button" class="btn btn-danger btn-sm" onclick="$('#cancelAppointmentModal').modal('show')"><i class="far fa-calendar-times"></i> {{__('Cancel meeting')}}</button>
|
||||||
@endcan
|
@endcan
|
||||||
|
|
||||||
@can('applications.vote')
|
@can('applications.vote')
|
||||||
<button class="btn btn-warning mr-3" onclick="$('#notes').modal('show')">{{__('messages.view_app.view_notes')}}</button>
|
<button class="btn btn-warning mr-3 btn-sm" onclick="$('#notes').modal('show')"><i class="fas fa-clipboard"></i> {{__('messages.view_app.view_notes')}}</button>
|
||||||
@endcan
|
@endcan
|
||||||
|
|
||||||
</x-slot>
|
</x-slot>
|
||||||
|
19
resources/views/vendor/mail/html/button.blade.php
vendored
Normal file
19
resources/views/vendor/mail/html/button.blade.php
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<table class="action" align="center" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
||||||
|
<tr>
|
||||||
|
<td align="center">
|
||||||
|
<table width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation">
|
||||||
|
<tr>
|
||||||
|
<td align="center">
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" role="presentation">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="{{ $url }}" class="button button-{{ $color ?? 'primary' }}" target="_blank" rel="noopener">{{ $slot }}</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
11
resources/views/vendor/mail/html/footer.blade.php
vendored
Normal file
11
resources/views/vendor/mail/html/footer.blade.php
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<table class="footer" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation">
|
||||||
|
<tr>
|
||||||
|
<td class="content-cell" align="center">
|
||||||
|
{{ Illuminate\Mail\Markdown::parse($slot) }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
11
resources/views/vendor/mail/html/header.blade.php
vendored
Normal file
11
resources/views/vendor/mail/html/header.blade.php
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<tr>
|
||||||
|
<td class="header">
|
||||||
|
<a href="{{ $url }}" style="display: inline-block;">
|
||||||
|
@if (trim($slot) === 'Laravel')
|
||||||
|
<img src="{{ config('adminlte.logo_img') }}" height="100px" style="border-radius: 100px" class="logo" alt="App Logo">
|
||||||
|
@else
|
||||||
|
{{ $slot }}
|
||||||
|
@endif
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
56
resources/views/vendor/mail/html/layout.blade.php
vendored
Normal file
56
resources/views/vendor/mail/html/layout.blade.php
vendored
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
<meta name="color-scheme" content="light">
|
||||||
|
<meta name="supported-color-schemes" content="light">
|
||||||
|
<style>
|
||||||
|
@media only screen and (max-width: 600px) {
|
||||||
|
.inner-body {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 500px) {
|
||||||
|
.button {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<table class="wrapper" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
||||||
|
<tr>
|
||||||
|
<td align="center">
|
||||||
|
<table class="content" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
||||||
|
{{ $header ?? '' }}
|
||||||
|
|
||||||
|
<!-- Email Body -->
|
||||||
|
<tr>
|
||||||
|
<td class="body" width="100%" cellpadding="0" cellspacing="0">
|
||||||
|
<table class="inner-body" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation">
|
||||||
|
<!-- Body content -->
|
||||||
|
<tr>
|
||||||
|
<td class="content-cell">
|
||||||
|
{{ Illuminate\Mail\Markdown::parse($slot) }}
|
||||||
|
|
||||||
|
{{ $subcopy ?? '' }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{{ $footer ?? '' }}
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
27
resources/views/vendor/mail/html/message.blade.php
vendored
Normal file
27
resources/views/vendor/mail/html/message.blade.php
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
@component('mail::layout')
|
||||||
|
{{-- Header --}}
|
||||||
|
@slot('header')
|
||||||
|
@component('mail::header', ['url' => config('app.url')])
|
||||||
|
<img src="{{ config('adminlte.logo_img') }}" height="100px" style="border-radius: 10px" alt="gamesclub official logo">
|
||||||
|
@endcomponent
|
||||||
|
@endslot
|
||||||
|
|
||||||
|
{{-- Body --}}
|
||||||
|
{{ $slot }}
|
||||||
|
|
||||||
|
{{-- Subcopy --}}
|
||||||
|
@isset($subcopy)
|
||||||
|
@slot('subcopy')
|
||||||
|
@component('mail::subcopy')
|
||||||
|
{{ $subcopy }}
|
||||||
|
@endcomponent
|
||||||
|
@endslot
|
||||||
|
@endisset
|
||||||
|
|
||||||
|
{{-- Footer --}}
|
||||||
|
@slot('footer')
|
||||||
|
@component('mail::footer')
|
||||||
|
© {{ date('Y') }} {{ config('app.name') }}. @lang('All rights reserved.')
|
||||||
|
@endcomponent
|
||||||
|
@endslot
|
||||||
|
@endcomponent
|
14
resources/views/vendor/mail/html/panel.blade.php
vendored
Normal file
14
resources/views/vendor/mail/html/panel.blade.php
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<table class="panel" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
||||||
|
<tr>
|
||||||
|
<td class="panel-content">
|
||||||
|
<table width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
||||||
|
<tr>
|
||||||
|
<td class="panel-item">
|
||||||
|
{{ Illuminate\Mail\Markdown::parse($slot) }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
7
resources/views/vendor/mail/html/subcopy.blade.php
vendored
Normal file
7
resources/views/vendor/mail/html/subcopy.blade.php
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<table class="subcopy" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
{{ Illuminate\Mail\Markdown::parse($slot) }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
3
resources/views/vendor/mail/html/table.blade.php
vendored
Normal file
3
resources/views/vendor/mail/html/table.blade.php
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<div class="table">
|
||||||
|
{{ Illuminate\Mail\Markdown::parse($slot) }}
|
||||||
|
</div>
|
290
resources/views/vendor/mail/html/themes/default.css
vendored
Normal file
290
resources/views/vendor/mail/html/themes/default.css
vendored
Normal file
@ -0,0 +1,290 @@
|
|||||||
|
/* Base */
|
||||||
|
|
||||||
|
body,
|
||||||
|
body *:not(html):not(style):not(br):not(tr):not(code) {
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif,
|
||||||
|
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
-webkit-text-size-adjust: none;
|
||||||
|
background-color: #ffffff;
|
||||||
|
color: #718096;
|
||||||
|
height: 100%;
|
||||||
|
line-height: 1.4;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
p,
|
||||||
|
ul,
|
||||||
|
ol,
|
||||||
|
blockquote {
|
||||||
|
line-height: 1.4;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #3869d4;
|
||||||
|
}
|
||||||
|
|
||||||
|
a img {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Typography */
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
color: #3d4852;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.5em;
|
||||||
|
margin-top: 0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.sub {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Layout */
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
-premailer-cellpadding: 0;
|
||||||
|
-premailer-cellspacing: 0;
|
||||||
|
-premailer-width: 100%;
|
||||||
|
background-color: #edf2f7;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
-premailer-cellpadding: 0;
|
||||||
|
-premailer-cellspacing: 0;
|
||||||
|
-premailer-width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header */
|
||||||
|
|
||||||
|
.header {
|
||||||
|
padding: 25px 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header a {
|
||||||
|
color: #3d4852;
|
||||||
|
font-size: 19px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Logo */
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
height: 75px;
|
||||||
|
max-height: 75px;
|
||||||
|
width: 75px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Body */
|
||||||
|
|
||||||
|
.body {
|
||||||
|
-premailer-cellpadding: 0;
|
||||||
|
-premailer-cellspacing: 0;
|
||||||
|
-premailer-width: 100%;
|
||||||
|
background-color: #edf2f7;
|
||||||
|
border-bottom: 1px solid #edf2f7;
|
||||||
|
border-top: 1px solid #edf2f7;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inner-body {
|
||||||
|
-premailer-cellpadding: 0;
|
||||||
|
-premailer-cellspacing: 0;
|
||||||
|
-premailer-width: 570px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-color: #e8e5ef;
|
||||||
|
border-radius: 2px;
|
||||||
|
border-width: 1px;
|
||||||
|
box-shadow: 0 2px 0 rgba(0, 0, 150, 0.025), 2px 4px 0 rgba(0, 0, 150, 0.015);
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0;
|
||||||
|
width: 570px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Subcopy */
|
||||||
|
|
||||||
|
.subcopy {
|
||||||
|
border-top: 1px solid #e8e5ef;
|
||||||
|
margin-top: 25px;
|
||||||
|
padding-top: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subcopy p {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Footer */
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
-premailer-cellpadding: 0;
|
||||||
|
-premailer-cellspacing: 0;
|
||||||
|
-premailer-width: 570px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0;
|
||||||
|
text-align: center;
|
||||||
|
width: 570px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer p {
|
||||||
|
color: #b0adc5;
|
||||||
|
font-size: 12px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer a {
|
||||||
|
color: #b0adc5;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tables */
|
||||||
|
|
||||||
|
.table table {
|
||||||
|
-premailer-cellpadding: 0;
|
||||||
|
-premailer-cellspacing: 0;
|
||||||
|
-premailer-width: 100%;
|
||||||
|
margin: 30px auto;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table th {
|
||||||
|
border-bottom: 1px solid #edeff2;
|
||||||
|
margin: 0;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table td {
|
||||||
|
color: #74787e;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 18px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-cell {
|
||||||
|
max-width: 100vw;
|
||||||
|
padding: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Buttons */
|
||||||
|
|
||||||
|
.action {
|
||||||
|
-premailer-cellpadding: 0;
|
||||||
|
-premailer-cellspacing: 0;
|
||||||
|
-premailer-width: 100%;
|
||||||
|
margin: 30px auto;
|
||||||
|
padding: 0;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
-webkit-text-size-adjust: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #fff;
|
||||||
|
display: inline-block;
|
||||||
|
overflow: hidden;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-blue,
|
||||||
|
.button-primary {
|
||||||
|
background-color: #2d3748;
|
||||||
|
border-bottom: 8px solid #2d3748;
|
||||||
|
border-left: 18px solid #2d3748;
|
||||||
|
border-right: 18px solid #2d3748;
|
||||||
|
border-top: 8px solid #2d3748;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-green,
|
||||||
|
.button-success {
|
||||||
|
background-color: #48bb78;
|
||||||
|
border-bottom: 8px solid #48bb78;
|
||||||
|
border-left: 18px solid #48bb78;
|
||||||
|
border-right: 18px solid #48bb78;
|
||||||
|
border-top: 8px solid #48bb78;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-red,
|
||||||
|
.button-error {
|
||||||
|
background-color: #e53e3e;
|
||||||
|
border-bottom: 8px solid #e53e3e;
|
||||||
|
border-left: 18px solid #e53e3e;
|
||||||
|
border-right: 18px solid #e53e3e;
|
||||||
|
border-top: 8px solid #e53e3e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Panels */
|
||||||
|
|
||||||
|
.panel {
|
||||||
|
border-left: #2d3748 solid 4px;
|
||||||
|
margin: 21px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-content {
|
||||||
|
background-color: #edf2f7;
|
||||||
|
color: #718096;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-content p {
|
||||||
|
color: #718096;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-item {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-item p:last-of-type {
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Utilities */
|
||||||
|
|
||||||
|
.break-all {
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
1
resources/views/vendor/mail/text/button.blade.php
vendored
Normal file
1
resources/views/vendor/mail/text/button.blade.php
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{{ $slot }}: {{ $url }}
|
1
resources/views/vendor/mail/text/footer.blade.php
vendored
Normal file
1
resources/views/vendor/mail/text/footer.blade.php
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{{ $slot }}
|
1
resources/views/vendor/mail/text/header.blade.php
vendored
Normal file
1
resources/views/vendor/mail/text/header.blade.php
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
[{{ $slot }}]({{ $url }})
|
9
resources/views/vendor/mail/text/layout.blade.php
vendored
Normal file
9
resources/views/vendor/mail/text/layout.blade.php
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{!! strip_tags($header) !!}
|
||||||
|
|
||||||
|
{!! strip_tags($slot) !!}
|
||||||
|
@isset($subcopy)
|
||||||
|
|
||||||
|
{!! strip_tags($subcopy) !!}
|
||||||
|
@endisset
|
||||||
|
|
||||||
|
{!! strip_tags($footer) !!}
|
27
resources/views/vendor/mail/text/message.blade.php
vendored
Normal file
27
resources/views/vendor/mail/text/message.blade.php
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
@component('mail::layout')
|
||||||
|
{{-- Header --}}
|
||||||
|
@slot('header')
|
||||||
|
@component('mail::header', ['url' => config('app.url')])
|
||||||
|
{{ config('app.name') }}
|
||||||
|
@endcomponent
|
||||||
|
@endslot
|
||||||
|
|
||||||
|
{{-- Body --}}
|
||||||
|
{{ $slot }}
|
||||||
|
|
||||||
|
{{-- Subcopy --}}
|
||||||
|
@isset($subcopy)
|
||||||
|
@slot('subcopy')
|
||||||
|
@component('mail::subcopy')
|
||||||
|
{{ $subcopy }}
|
||||||
|
@endcomponent
|
||||||
|
@endslot
|
||||||
|
@endisset
|
||||||
|
|
||||||
|
{{-- Footer --}}
|
||||||
|
@slot('footer')
|
||||||
|
@component('mail::footer')
|
||||||
|
© {{ date('Y') }} {{ config('app.name') }}. @lang('All rights reserved.')
|
||||||
|
@endcomponent
|
||||||
|
@endslot
|
||||||
|
@endcomponent
|
1
resources/views/vendor/mail/text/panel.blade.php
vendored
Normal file
1
resources/views/vendor/mail/text/panel.blade.php
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{{ $slot }}
|
1
resources/views/vendor/mail/text/subcopy.blade.php
vendored
Normal file
1
resources/views/vendor/mail/text/subcopy.blade.php
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{{ $slot }}
|
1
resources/views/vendor/mail/text/table.blade.php
vendored
Normal file
1
resources/views/vendor/mail/text/table.blade.php
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{{ $slot }}
|
62
resources/views/vendor/notifications/email.blade.php
vendored
Normal file
62
resources/views/vendor/notifications/email.blade.php
vendored
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
@component('mail::message')
|
||||||
|
{{-- Greeting --}}
|
||||||
|
@if (! empty($greeting))
|
||||||
|
# {{ $greeting }}
|
||||||
|
@else
|
||||||
|
@if ($level === 'error')
|
||||||
|
# @lang('Whoops!')
|
||||||
|
@else
|
||||||
|
# @lang('Hello!')
|
||||||
|
@endif
|
||||||
|
@endif
|
||||||
|
|
||||||
|
{{-- Intro Lines --}}
|
||||||
|
@foreach ($introLines as $line)
|
||||||
|
{{ $line }}
|
||||||
|
|
||||||
|
@endforeach
|
||||||
|
|
||||||
|
{{-- Action Button --}}
|
||||||
|
@isset($actionText)
|
||||||
|
<?php
|
||||||
|
switch ($level) {
|
||||||
|
case 'success':
|
||||||
|
case 'error':
|
||||||
|
$color = $level;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$color = 'primary';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
@component('mail::button', ['url' => $actionUrl, 'color' => $color])
|
||||||
|
{{ $actionText }}
|
||||||
|
@endcomponent
|
||||||
|
@endisset
|
||||||
|
|
||||||
|
{{-- Outro Lines --}}
|
||||||
|
@foreach ($outroLines as $line)
|
||||||
|
{{ $line }}
|
||||||
|
|
||||||
|
@endforeach
|
||||||
|
|
||||||
|
{{-- Salutation --}}
|
||||||
|
@if (! empty($salutation))
|
||||||
|
{{ $salutation }}
|
||||||
|
@else
|
||||||
|
@lang('Regards'),<br>
|
||||||
|
{{ config('app.name') }}
|
||||||
|
@endif
|
||||||
|
|
||||||
|
{{-- Subcopy --}}
|
||||||
|
@isset($actionText)
|
||||||
|
@slot('subcopy')
|
||||||
|
@lang(
|
||||||
|
"If you're having trouble clicking the \":actionText\" button, copy and paste the URL below\n".
|
||||||
|
'into your web browser:',
|
||||||
|
[
|
||||||
|
'actionText' => $actionText,
|
||||||
|
]
|
||||||
|
) <span class="break-all">[{{ $displayableActionUrl }}]({{ $actionUrl }})</span>
|
||||||
|
@endslot
|
||||||
|
@endisset
|
||||||
|
@endcomponent
|
@ -166,6 +166,9 @@ Route::group(['prefix' => LaravelLocalization::setLocale(), 'middleware' => ['lo
|
|||||||
|
|
||||||
Route::patch('update/appointments/{application}/{status}', [AppointmentController::class, 'updateAppointment'])
|
Route::patch('update/appointments/{application}/{status}', [AppointmentController::class, 'updateAppointment'])
|
||||||
->name('updateAppointment');
|
->name('updateAppointment');
|
||||||
|
|
||||||
|
Route::delete('delete/appointments/{application}', [AppointmentController::class, 'deleteAppointment'])
|
||||||
|
->name('deleteAppointment');
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::group(['prefix' => 'apply', 'middleware' => ['eligibility', 'passwordredirect']], function () {
|
Route::group(['prefix' => 'apply', 'middleware' => ['eligibility', 'passwordredirect']], function () {
|
||||||
@ -310,6 +313,7 @@ Route::group(['prefix' => LaravelLocalization::setLocale(), 'middleware' => ['lo
|
|||||||
->name('devTools');
|
->name('devTools');
|
||||||
|
|
||||||
|
|
||||||
|
Route::post('/applications/force-approval', [DevToolsController::class, 'forceApprovalEvent']);
|
||||||
Route::post('/applications/force-approval', [DevToolsController::class, 'forceApprovalEvent'])
|
Route::post('/applications/force-approval', [DevToolsController::class, 'forceApprovalEvent'])
|
||||||
->name('devForceApprovalEvent');
|
->name('devForceApprovalEvent');
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user