Files
AggloSign/backend/resources/views/admin/campaigns/form.blade.php
T

154 lines
9.0 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
@extends('layouts.app')
@section('title', ($campaign->exists ? $campaign->name : 'Nouvelle campagne').' — Signatures CABM')
@section('content')
@php
$isAdmin = auth()->user()->hasRole('admin');
$tz = config('signature.timezone');
$local = fn ($d) => $d?->timezone($tz)->format('Y-m-d\TH:i');
$currentImage = old('image_path', $campaign->image_path);
$currentImage = is_string($currentImage) ? $currentImage : null;
$inLibrary = $images->contains('name', $currentImage);
$checked = collect(old('groups', $selected))->map(fn ($id) => (int) $id)->all();
$status = $campaign->exists ? $campaign->status() : null;
@endphp
<div class="row" style="margin-bottom:16px">
<a href="{{ route('admin.campaigns.index') }}">← Campagnes</a>
<h1 style="margin:0 0 0 12px">{{ $campaign->exists ? $campaign->name : 'Nouvelle campagne' }}</h1>
@if ($status)
<span class="badge {{ ['running' => 'ok', 'inactive' => 'warn'][$status] ?? '' }}">{{ \App\Models\Campaign::STATUSES[$status] }}</span>
@endif
</div>
@if ($locked)
<div class="notice" role="note">Cette campagne est active : seul un administrateur peut la modifier.</div>
@endif
<form method="post" enctype="multipart/form-data"
action="{{ $campaign->exists ? route('admin.campaigns.update', $campaign) : route('admin.campaigns.store') }}">
@csrf
@if ($campaign->exists) @method('PUT') @endif
<fieldset @disabled($locked) style="border:0;margin:0;padding:0">
<div class="split">
<div class="card">
<h2>Bannière</h2>
<label for="name">Nom de la campagne</label>
<input type="text" id="name" name="name" maxlength="120" required value="{{ old('name', $campaign->name) }}" placeholder="ex. Collecte des encombrants — octobre">
<label for="image_path">Image</label>
<select id="image_path" name="image_path">
<option value="">— choisir dans la bibliothèque —</option>
@if ($currentImage && ! $inLibrary)
<option value="{{ $currentImage }}" selected>{{ $currentImage }} (introuvable)</option>
@endif
@foreach ($images as $img)
<option value="{{ $img['name'] }}" data-src="{{ asset('img/'.$img['name']) }}" data-width="{{ $img['width'] }}" @selected($currentImage === $img['name'])>
{{ $img['name'] }} — {{ $img['width'] }}×{{ $img['height'] }} px, {{ $img['kb'] }} Ko
</option>
@endforeach
</select>
<label for="image_file">… ou envoyer une nouvelle image (PNG, JPEG, GIF)</label>
<input type="file" id="image_file" name="image_file" accept="image/png,image/jpeg,image/gif">
<p class="muted">Visez 600 px de large et moins de 100 Ko : les destinataires la téléchargent à chaque ouverture du message.</p>
<img id="thumb" alt="" hidden style="max-width:100%;max-height:160px;border:1px solid var(--line);background:#fff">
<label for="alt_text">Texte alternatif</label>
<input type="text" id="alt_text" name="alt_text" maxlength="150" required value="{{ old('alt_text', $campaign->alt_text) }}" placeholder="ex. Collecte des encombrants : inscrivez-vous avant le 15 octobre">
<p class="muted">Affiché quand le destinataire bloque les images, et lu par les lecteurs d'écran. Résumez le message de la bannière.</p>
<label for="link_url">Lien au clic (facultatif)</label>
<input type="url" id="link_url" name="link_url" maxlength="255" value="{{ old('link_url', $campaign->link_url) }}" placeholder="https://www.beziers-mediterranee.fr/…">
<label for="width">Largeur d'affichage (px, facultatif)</label>
<input type="number" id="width" name="width" style="width:140px" min="100" max="800" value="{{ old('width', $width) }}" placeholder="auto">
<p class="muted">Vide : largeur réelle de l'image, plafonnée à 600 px.</p>
</div>
<div class="card">
<h2>Diffusion</h2>
<div class="row">
<div style="flex:1;min-width:200px">
<label for="starts_at">Début</label>
<input type="datetime-local" id="starts_at" name="starts_at" required value="{{ old('starts_at', $local($campaign->starts_at)) }}">
</div>
<div style="flex:1;min-width:200px">
<label for="ends_at">Fin</label>
<input type="datetime-local" id="ends_at" name="ends_at" required value="{{ old('ends_at', $local($campaign->ends_at)) }}">
</div>
</div>
<p class="muted">Heure de Paris. La bannière cesse d'être insérée à la fin ; les messages déjà envoyés la conservent.</p>
<label for="priority">Priorité</label>
<input class="small" type="number" id="priority" name="priority" min="0" max="1000" required value="{{ old('priority', $campaign->priority ?? 10) }}">
<p class="muted">Si plusieurs campagnes en cours concernent le même agent, la priorité la plus haute s'affiche.</p>
<fieldset>
<legend>Destinataires</legend>
<p class="muted" style="margin:0 0 6px">Aucune case cochée : tous les agents. Sinon, seuls les membres des groupes cochés.</p>
<div class="scroll">
@forelse ($groups as $g)
<label class="check">
<input type="checkbox" name="groups[]" value="{{ $g->id }}" @checked(in_array($g->id, $checked, true))>{{ $g->display_name }}
<span class="muted">({{ $g->members_count }})</span>
</label>
@empty
<span class="muted">Aucun groupe synchronisé.</span>
@endforelse
</div>
</fieldset>
@if ($isAdmin)
<input type="hidden" name="active" value="0">
<label class="check" style="margin-top:14px">
<input type="checkbox" name="active" value="1" @checked(old('active', $campaign->active))>Campagne active
</label>
<p class="muted">Décochée, la bannière n'est jamais insérée, même pendant la période.</p>
@else
<p class="muted" style="margin-top:14px">La campagne reste inactive tant qu'un administrateur ne l'a pas activée.</p>
@endif
</div>
</div>
<div class="row">
<button class="btn" type="submit">{{ $campaign->exists ? 'Enregistrer' : 'Créer la campagne' }}</button>
<a class="btn secondary" href="{{ route('admin.campaigns.index') }}">Annuler</a>
</div>
</fieldset>
</form>
@if ($campaign->exists)
<div class="card" style="margin-top:16px">
<h2>Rendu enregistré</h2>
<p class="muted">Tel qu'inséré à l'emplacement <code>{{ '{'.'{'.'{banniere}'.'}'.'}' }}</code> du template. Pour le voir dans une signature complète, ouvrez un agent dans l'onglet <a href="{{ route('admin.agents.index') }}">Agents</a>.</p>
@include('partials.signature-frame', ['html' => $bannerHtml, 'title' => 'Aperçu de la bannière'])
</div>
@endif
@endsection
@push('scripts')
<script>
(() => {
const select = document.getElementById('image_path');
const file = document.getElementById('image_file');
const thumb = document.getElementById('thumb');
const width = document.getElementById('width');
const show = (src) => { thumb.src = src; thumb.hidden = !src; };
const fromLibrary = () => {
const opt = select.selectedOptions[0];
show(opt && opt.dataset.src ? opt.dataset.src : '');
const natural = opt ? parseInt(opt.dataset.width, 10) : NaN;
width.placeholder = natural ? `auto (${Math.min(natural, 600)})` : 'auto';
};
select.addEventListener('change', () => { file.value = ''; fromLibrary(); });
file.addEventListener('change', () => {
if (!file.files.length) return fromLibrary();
select.value = '';
width.placeholder = 'auto';
show(URL.createObjectURL(file.files[0]));
});
fromLibrary();
})();
</script>
@endpush