Files
AggloSign/backend/resources/views/admin/campaigns/form.blade.php
T
2026-10-02 13:06:14 +02:00

167 lines
9.6 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')
@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
<header class="page-head">
<div>
<a class="back" href="{{ route('admin.campaigns.index') }}"><x-icon name="chevron-left" :size="16" />Campagnes</a>
<div class="page-title">
<h1>{{ $campaign->exists ? $campaign->name : 'Nouvelle campagne' }}</h1>
@if ($status)
<span class="badge {{ ['running' => 'ok', 'inactive' => 'warn', 'ended' => 'off'][$status] ?? '' }}">{{ \App\Models\Campaign::STATUSES[$status] }}</span>
@endif
</div>
</div>
</header>
@if ($locked)
<div class="alert notice" role="note">
<x-icon name="info" />
<div>Cette campagne est active : seul un administrateur peut la modifier.</div>
</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 class="bare" @disabled($locked)>
<div class="split">
<div class="card">
<h2>Bannière</h2>
<label for="name" style="margin-top:0">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 class="dropzone" data-dropzone style="margin-top:10px">
<input type="file" id="image_file" name="image_file" accept="image/png,image/jpeg,image/gif" aria-label="Nouvelle image">
<x-icon name="cloud-upload" :size="24" />
<span data-prompt>… ou glissez une nouvelle image ici, ou <u>parcourez vos fichiers</u></span>
<span class="dropzone-name" data-name hidden></span>
<span class="muted">PNG, JPEG ou GIF</span>
</label>
<p class="hint">Visez 600 px de large et moins de 100 Ko : les destinataires la téléchargent à chaque ouverture du message.</p>
<img id="thumb" class="preview-img" alt="" hidden>
<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="hint">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="hint">Vide : largeur réelle de l'image, plafonnée à 600 px.</p>
</div>
<div class="card">
<h2>Diffusion</h2>
<div class="field-row">
<div>
<label for="starts_at" style="margin-top:0">Début</label>
<input type="datetime-local" id="starts_at" name="starts_at" required value="{{ old('starts_at', $local($campaign->starts_at)) }}">
</div>
<div>
<label for="ends_at" style="margin-top:0">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="hint">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="hint">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="switch" style="margin-top:16px">
<input type="checkbox" name="active" value="1" @checked(old('active', $campaign->active))>
<span class="switch-track"></span><strong>Campagne active</strong>
</label>
<p class="hint">Désactivée, la bannière n'est jamais insérée, même pendant la période.</p>
@else
<p class="hint" 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"><x-icon name="save" />{{ $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>Bannière enregistrée</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', 'class' => 'short'])
</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 = ''; file.dispatchEvent(new Event('change')); });
file.addEventListener('change', () => {
if (!file.files.length) return fromLibrary();
select.value = '';
width.placeholder = 'auto';
show(URL.createObjectURL(file.files[0]));
});
fromLibrary();
})();
</script>
@endpush