Demo Mode: you're exploring a live BackupMGR panel with sample data. Everything is read-only. Get BackupMGR →

License Key Required

No license key entered. Enter or update your key with php artisan news:license <key>, or purchase one at scriptgain.com.

Show

admin.constituents.show

Status Shipped Default Shipped File resources/views/admin/constituents/show.blade.php
admin.constituents.show 372 lines
Not Checked Yet

Optional. Shown in the version history so the next person knows why.

Saving runs the same check. An invalid template is refused, not stored.

Compiled PHP

What Blade turns your template into. This is what the syntax check parses.

Loading…

Available Variables And Components

A guide to what this template can use, derived from the shipped source. Click any item to insert it at your cursor. It is a helpful reference, not a runtime guarantee.

Always Available

Shared with the admin panel by the staff layout.
Validation error bag. Always present. Pairs with @error('field').
The admin sidebar navigation structure.
Sub-items of the currently open nav group.
Breadcrumb trail for the current page.
Signed-in staffer's initials, for the avatar.
Signed-in staffer's name.
Signed-in staffer's email address.
The staffer's role, e.g. "Administrator".
True when the signed-in staffer is an administrator.
Number of open service requests, for the badge.
Number of unread form submissions, for the badge.
The configured admin-shell width class.
URL of the uploaded site logo, or null.
URL of the uploaded favicon, or null.

In This Template

Counts.
Default Occurred At.
A collection of departments.
Directions.
Dispatch.
Duplicates.
Interaction Types.
Record.
Requests.
Submissions.
Timeline.

Drop any of these in. Click to insert the opening tag at your cursor.

General

type, info, title
initials, src, name, size, md
color, neutral, dot
action, label, Record, modal
variant, primary, size, md, href, …
title, subtitle, padding, flush
name, action, method, POST, title, …
action, name, title, message, confirm, …
href, icon, danger
align, right, width
icon, folder, title, description
label, for, hint, error, required
href, icon, title, variant, secondary, …
name
type, text
name, title, subtitle, icon, tone, …
href, icon, active
title, subtitle, icon, back
title, subtitle, href, linkLabel
ids
id, label, Row
items
label, value, icon, trend, trendColor, …
color, neutral, pulse, label
name
flush
tabs, default
name, checked, label, description

Admin Panel

title, message, icon, folder, href, …
tree, active, rootLabel, rootHref
title, subtitle, icon, edit, action, …
title, icon, folder, subtitle, records, …
search, placeholder, createHref, createLabel
edit, delete, preview, name, title, …
record, kind, Page

Layouts

title, shellMaxWidth
title, description, heroless, maxWidth

Records

name, action, reference, trigger, icon

Site (Public)

href, title, description, icon, meta, …
title, message, icon, folder
title, subtitle, eyebrow, icon, crumbs, …
supportEmail, supportPhone
disclaimer, takedownContact, retentionDays, compact
title, subtitle, href, linkLabel, tone, …
maxWidth

Common Blade

Print a value, safely escaped. The default choice.
Print raw HTML. Only for content you trust.
Show something conditionally.
Loop over a collection.
Loop, with a fallback when the collection is empty.
Show a validation message for a field.
A small block of PHP. Never on line 1. Keep logic out of templates.
A comment that never reaches the browser.

Civic Helpers

Build a URL to a named route, e.g. a department page.
Link to a single news post.
Turn a stored upload path into a public URL.
A cache-busted URL for a bundled asset.
Read a config value, e.g. the site width class.
Build an absolute URL to a path.

No History Yet

Every save, revert, and reset of this template is recorded here, with a one-click way back to any of them.

The Template That Shipped With The Product

Read only. This is what Reset To Default puts back.

<x-layouts.app :title="$record->name">
    <x-page-header :title="$record->name" icon="users"
                   subtitle="Resident Record. Staff Only.">
        <x-slot:actions>
            <x-button variant="secondary" icon="chevron-left" :href="route('constituents.index')">Back To Residents</x-button>
            <x-button variant="secondary" icon="edit" :href="route('constituents.edit', $record)">Edit Record</x-button>
            <span x-data @click="$dispatch('open-modal', 'log-contact')" class="inline-flex">
                <x-button icon="phone">Log A Contact</x-button>
            </span>
        </x-slot:actions>
    </x-page-header>

    {{-- Identity strip --}}
    <x-card>
        <div class="flex flex-wrap items-start gap-5">
            <x-avatar size="lg" :initials="$record->initials()" :name="$record->name" />

            <div class="min-w-0 flex-1">
                <div class="flex flex-wrap items-center gap-2">
                    <h2 class="text-lg font-semibold text-slate-900">{{ $record->name }}</h2>
                    @if ($record->do_not_contact)
                        <x-badge color="danger" dot>Do Not Contact</x-badge>
                    @endif
                    @if ($record->user)
                        <x-badge color="info" dot>Has An Account</x-badge>
                    @endif
                    @foreach ($record->tagList() as $tag)
                        <x-badge color="neutral">{{ $tag }}</x-badge>
                    @endforeach
                </div>

                <dl class="mt-4 grid gap-4 sm:grid-cols-2 lg:grid-cols-4 text-sm">
                    <div class="flex items-start gap-2.5">
                        <span class="mt-0.5 inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-brand-50 text-brand-600 ring-1 ring-brand-200">
                            <x-icon name="envelope" class="w-4 h-4" />
                        </span>
                        <div class="min-w-0">
                            <dt class="text-xs font-medium uppercase tracking-wide text-slate-400">Email</dt>
                            <dd class="mt-0.5 truncate text-slate-900">{{ $record->email ?: 'Not On File' }}</dd>
                        </div>
                    </div>
                    <div class="flex items-start gap-2.5">
                        <span class="mt-0.5 inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-brand-50 text-brand-600 ring-1 ring-brand-200">
                            <x-icon name="phone" class="w-4 h-4" />
                        </span>
                        <div class="min-w-0">
                            <dt class="text-xs font-medium uppercase tracking-wide text-slate-400">Phone</dt>
                            <dd class="mt-0.5 truncate text-slate-900">{{ $record->phone ?: 'Not On File' }}</dd>
                        </div>
                    </div>
                    <div class="flex items-start gap-2.5">
                        <span class="mt-0.5 inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-brand-50 text-brand-600 ring-1 ring-brand-200">
                            <x-icon name="map-pin" class="w-4 h-4" />
                        </span>
                        <div class="min-w-0">
                            <dt class="text-xs font-medium uppercase tracking-wide text-slate-400">Mailing Address</dt>
                            <dd class="mt-0.5 text-slate-900">
                                @forelse ($record->addressLines() as $line)
                                    <span class="block truncate">{{ $line }}</span>
                                @empty
                                    Not On File
                                @endforelse
                            </dd>
                        </div>
                    </div>
                    <div class="flex items-start gap-2.5">
                        <span class="mt-0.5 inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-brand-50 text-brand-600 ring-1 ring-brand-200">
                            <x-icon name="clock" class="w-4 h-4" />
                        </span>
                        <div class="min-w-0">
                            <dt class="text-xs font-medium uppercase tracking-wide text-slate-400">Last Contact</dt>
                            <dd class="mt-0.5 truncate text-slate-900">
                                {{ $record->last_interaction_at?->format(config('news.date_format')) ?? 'Never' }}
                            </dd>
                        </div>
                    </div>
                </dl>
            </div>
        </div>
    </x-card>

    <div class="section-divider my-6"></div>

    <x-tabs :tabs="[
        'timeline' => ['label' => 'Timeline', 'icon' => 'clock', 'count' => $timeline->count()],
        'requests' => ['label' => 'Service Requests', 'icon' => 'bolt', 'count' => $counts['requests']],
        'submissions' => ['label' => 'Form Submissions', 'icon' => 'clipboard', 'count' => $counts['submissions']],
        'details' => ['label' => 'Details And Notes', 'icon' => 'file-text'],
        'merge' => ['label' => 'Merge Duplicates', 'icon' => 'copy', 'count' => $duplicates->count()],
    ]">

        {{-- ---------------------------------------------------------------
             Timeline: the whole point of the record. Service requests, form
             submissions and staff-logged contact in one chronological list.
        ---------------------------------------------------------------- --}}
        <x-tab-panel name="timeline">
            <x-card title="Everything On File" subtitle="Newest first. Filed online and logged by staff, together.">
                @if ($timeline->count())
                    <ol class="relative space-y-6 border-l border-slate-200 pl-6">
                        @foreach ($timeline as $entry)
                            <li class="relative">
                                <span class="absolute -left-[2.1rem] mt-0.5 inline-flex h-7 w-7 items-center justify-center rounded-lg bg-white text-brand-600 ring-1 ring-brand-200 shadow-sm">
                                    <x-icon :name="$entry['icon']" class="w-4 h-4" />
                                </span>
                                <div class="flex flex-wrap items-center gap-2">
                                    <span class="text-xs font-semibold uppercase tracking-wide text-slate-400">{{ $entry['kind'] }}</span>
                                    @if ($entry['badge'])
                                        <x-badge :color="$entry['badge']['color']" dot>{{ $entry['badge']['label'] }}</x-badge>
                                    @endif
                                    <span class="text-xs text-slate-400">
                                        {{ $entry['at']->format(config('news.date_format') . ', ' . config('news.time_format')) }}
                                    </span>
                                </div>
                                <p class="mt-1 font-medium text-slate-900">
                                    @if ($entry['href'])
                                        <a href="{{ $entry['href'] }}" class="hover:text-brand-700">{{ $entry['title'] }}</a>
                                    @else
                                        {{ $entry['title'] }}
                                    @endif
                                </p>
                                @if ($entry['summary'])
                                    <p class="mt-1 whitespace-pre-line text-sm text-slate-600">{{ $entry['summary'] }}</p>
                                @endif
                                <div class="mt-1.5 flex flex-wrap items-center gap-2 text-xs text-slate-500">
                                    @foreach ($entry['meta'] as $meta)
                                        <span class="rounded-full bg-slate-100 px-2 py-0.5">{{ $meta }}</span>
                                    @endforeach
                                    @if ($entry['actor'])
                                        <span>Logged By {{ $entry['actor'] }}</span>
                                    @endif
                                </div>
                            </li>
                        @endforeach
                    </ol>
                @else
                    <x-empty-state icon="clock" title="Nothing On File Yet"
                                   description="This resident has not filed anything, and no staff contact has been logged against the record." />
                @endif
            </x-card>
        </x-tab-panel>

        {{-- Service requests --}}
        <x-tab-panel name="requests">
            <x-card flush title="Service Requests" subtitle="Everything this resident reported from the public site.">
                @if ($requests->count())
                    <x-table flush>
                        <caption class="sr-only">Service Requests Filed By {{ $record->name }}</caption>
                        <thead>
                            <tr>
                                <th scope="col">Reference</th>
                                <th scope="col">Category</th>
                                <th scope="col">Location</th>
                                <th scope="col">Department</th>
                                <th scope="col">Status</th>
                                <th scope="col">Filed</th>
                                <th scope="col" class="text-right">Actions</th>
                            </tr>
                        </thead>
                        <tbody>
                            @foreach ($requests as $request)
                                <tr>
                                    <td class="font-medium text-slate-900 tabular">{{ $request->reference }}</td>
                                    <td>{{ $request->category }}</td>
                                    <td class="text-slate-600">{{ $request->location_text ?: '–' }}</td>
                                    <td>{{ $request->department?->name ?? 'Unassigned' }}</td>
                                    <td><x-badge :color="$request->statusColor()" dot>{{ $request->statusLabel() }}</x-badge></td>
                                    <td class="text-slate-500">{{ $request->created_at->format(config('news.date_format')) }}</td>
                                    <td class="text-right">
                                        <x-button size="sm" variant="secondary" :href="route('service-requests.show', $request)">Open</x-button>
                                    </td>
                                </tr>
                            @endforeach
                        </tbody>
                    </x-table>
                @else
                    <x-admin.empty icon="bolt" title="No Service Requests"
                                   message="Nothing has been reported under this record." />
                @endif
            </x-card>
        </x-tab-panel>

        {{-- Form submissions --}}
        <x-tab-panel name="submissions">
            <x-card flush title="Form Submissions" subtitle="Forms this resident filled in on the public site.">
                @if ($submissions->count())
                    <x-table flush>
                        <caption class="sr-only">Form Submissions By {{ $record->name }}</caption>
                        <thead>
                            <tr>
                                <th scope="col">Form</th>
                                <th scope="col">Received</th>
                                <th scope="col">Status</th>
                                <th scope="col" class="text-right">Actions</th>
                            </tr>
                        </thead>
                        <tbody>
                            @foreach ($submissions as $submission)
                                <tr>
                                    <td class="font-medium text-slate-900">{{ $submission->form?->name ?? 'Deleted Form' }}</td>
                                    <td class="text-slate-500">{{ $submission->created_at->format(config('news.date_format') . ', ' . config('news.time_format')) }}</td>
                                    <td>
                                        @if ($submission->isUnread())
                                            <x-badge color="warn" dot>Unread</x-badge>
                                        @else
                                            <x-badge color="success" dot>Read</x-badge>
                                        @endif
                                    </td>
                                    <td class="text-right">
                                        <x-button size="sm" variant="secondary" :href="route('submissions.show', $submission)">Open</x-button>
                                    </td>
                                </tr>
                            @endforeach
                        </tbody>
                    </x-table>
                @else
                    <x-admin.empty icon="clipboard" title="No Form Submissions"
                                   message="This resident has not submitted any of the town's online forms." />
                @endif
            </x-card>
        </x-tab-panel>

        {{-- Details and notes --}}
        <x-tab-panel name="details">
            <div class="grid gap-6 lg:grid-cols-3">
                <x-card class="lg:col-span-2" title="Staff Notes" subtitle="Internal. Never shown to the resident.">
                    @if ($record->notes)
                        <p class="whitespace-pre-line text-sm text-slate-700">{{ $record->notes }}</p>
                    @else
                        <p class="text-sm text-slate-500">No Notes Recorded Yet.</p>
                    @endif
                </x-card>

                <x-card title="Record Details">
                    <dl class="space-y-3 text-sm">
                        <div class="flex items-start justify-between gap-3">
                            <dt class="text-slate-500">Record Created</dt>
                            <dd class="text-right text-slate-900">{{ $record->created_at->format(config('news.date_format')) }}</dd>
                        </div>
                        <div class="flex items-start justify-between gap-3">
                            <dt class="text-slate-500">Last Updated</dt>
                            <dd class="text-right text-slate-900">{{ $record->updated_at->format(config('news.date_format')) }}</dd>
                        </div>
                        <div class="flex items-start justify-between gap-3">
                            <dt class="text-slate-500">Created From</dt>
                            <dd class="text-right text-slate-900">{{ $record->source }}</dd>
                        </div>
                        <div class="flex items-start justify-between gap-3">
                            <dt class="text-slate-500">Linked Account</dt>
                            <dd class="text-right text-slate-900">{{ $record->user?->name ?? 'None' }}</dd>
                        </div>
                        <div class="flex items-start justify-between gap-3">
                            <dt class="text-slate-500">Staff Logged Contacts</dt>
                            <dd class="text-right text-slate-900 tabular">{{ $counts['interactions'] }}</dd>
                        </div>
                    </dl>

                    <div class="section-divider mt-5 pt-5">
                        <x-button variant="secondary" icon="edit" :href="route('constituents.edit', $record)" class="w-full">Edit This Record</x-button>
                    </div>
                </x-card>
            </div>
        </x-tab-panel>

        {{-- Merge duplicates --}}
        <x-tab-panel name="merge">
            <x-card title="Merge A Duplicate Into This Record"
                    subtitle="Residents file under slightly different names and email addresses. Merging moves every request, submission and logged contact onto this record, then removes the duplicate.">
                @if ($duplicates->count())
                    <ul class="divide-y divide-slate-100">
                        @foreach ($duplicates as $duplicate)
                            <li class="flex flex-wrap items-center justify-between gap-3 py-3">
                                <div class="flex items-center gap-3 min-w-0">
                                    <x-avatar size="sm" :initials="$duplicate->initials()" :name="$duplicate->name" />
                                    <div class="min-w-0">
                                        <a href="{{ route('constituents.show', $duplicate) }}"
                                           class="block truncate font-medium text-slate-900 hover:text-brand-700">{{ $duplicate->name }}</a>
                                        <p class="truncate text-xs text-slate-500">
                                            {{ $duplicate->email ?: 'No Email' }}
                                            @if ($duplicate->phone) &middot; {{ $duplicate->phone }} @endif
                                        </p>
                                    </div>
                                </div>
                                <span x-data @click="$dispatch('open-modal', 'merge-{{ $duplicate->id }}')" class="inline-flex">
                                    <x-button variant="secondary" size="sm" icon="copy">Merge Into This Record</x-button>
                                </span>

                                {{-- Modal confirm, never a native dialog. Carries the
                                     duplicate id, so the form is written out here
                                     rather than reusing the generic confirm helper. --}}
                                <x-modal :name="'merge-' . $duplicate->id" title="Merge These Two Records?"
                                         icon="warning" tone="warn" maxWidth="max-w-md">
                                    Everything filed by <span class="font-semibold">{{ $duplicate->name }}</span> moves onto
                                    <span class="font-semibold">{{ $record->name }}</span>. Blank fields on this record are filled
                                    in from the duplicate, and the duplicate is then deleted. This cannot be undone.
                                    <x-slot:footer>
                                        <x-button variant="secondary" size="sm"
                                                  x-on:click="$dispatch('close-modal', 'merge-{{ $duplicate->id }}')">Cancel</x-button>
                                        <form method="POST" action="{{ route('constituents.merge', $record) }}">
                                            @csrf
                                            <input type="hidden" name="duplicate_id" value="{{ $duplicate->id }}">
                                            <x-button size="sm" type="submit" icon="copy">Merge Records</x-button>
                                        </form>
                                    </x-slot:footer>
                                </x-modal>
                            </li>
                        @endforeach
                    </ul>
                @else
                    <x-empty-state icon="copy" title="No Likely Duplicates Found"
                                   description="Nothing on file looks like the same person. Matching is on shared phone numbers and similar names." />
                @endif
            </x-card>
        </x-tab-panel>
    </x-tabs>

    {{-- Log a contact. A modal so the detail page never grows a long scroll. --}}
    <x-modal name="log-contact" title="Log A Contact" icon="phone"
             subtitle="Record a phone call, counter visit, email or letter against this resident."
             maxWidth="max-w-xl">
        <form method="POST" action="{{ route('constituents.interactions.store', $record) }}" class="space-y-4" id="log-contact-form">
            @csrf

            <div class="grid gap-4 sm:grid-cols-2">
                <x-field label="Kind Of Contact" for="type" required :error="$errors->first('type')">
                    <x-select id="type" name="type" required>
                        @foreach ($interactionTypes as $key => $meta)
                            <option value="{{ $key }}">{{ $meta['label'] }}</option>
                        @endforeach
                    </x-select>
                </x-field>

                <x-field label="Direction" for="direction" required :error="$errors->first('direction')">
                    <x-select id="direction" name="direction" required>
                        @foreach ($directions as $key => $label)
                            <option value="{{ $key }}">{{ $label }}</option>
                        @endforeach
                    </x-select>
                </x-field>

                <x-field label="When It Happened" for="occurred_at" required :error="$errors->first('occurred_at')">
                    <x-input type="datetime-local" id="occurred_at" name="occurred_at" required
                             :value="$defaultOccurredAt" />
                </x-field>

                <x-field label="Department" for="interaction_department" :error="$errors->first('department_id')">
                    <x-select id="interaction_department" name="department_id">
                        <option value="">Not Department Specific</option>
                        @foreach ($departments as $department)
                            <option value="{{ $department->id }}">{{ $department->name }}</option>
                        @endforeach
                    </x-select>
                </x-field>
            </div>

            <x-field label="Subject" for="subject" hint="Optional. A short line staff will scan later."
                     :error="$errors->first('subject')">
                <x-input id="subject" name="subject" maxlength="200" placeholder="Called about the water bill" />
            </x-field>

            <x-field label="What Was Said" for="note" required :error="$errors->first('note')">
                <textarea id="note" name="note" rows="4" required maxlength="5000"
                          class="block w-full rounded-lg border-0 px-3 py-2 text-sm text-slate-900 ring-1 ring-inset ring-slate-300 focus:ring-2 focus:ring-inset focus:ring-brand-500"></textarea>
            </x-field>
        </form>

        <x-slot:footer>
            <x-button variant="secondary" size="sm" x-on:click="$dispatch('close-modal', 'log-contact')">Cancel</x-button>
            <x-button size="sm" icon="check" type="submit" form="log-contact-form">Save Contact</x-button>
        </x-slot:footer>
    </x-modal>
</x-layouts.app>

Blade In One Screen

The directives you will use most.

{{ $variable }}
Print a value, escaped. Safe by default.
{!! $html !!}
Print raw HTML. Only for content you trust.
@if / @else / @endif
Show something conditionally.
@foreach / @endforeach
Loop over a collection.
<x-card>
Use a shared component. Every component in Shared Components is available.
{{-- comment --}}
A comment that never reaches the browser.

House Rules

Follow these and your edits will survive updates.

  • Never start line 1 with @php. Blade mis-parses it and the page fails. The editor refuses to save it.
  • Keep logic out of templates. If you need a calculation, it belongs in a composer or component class, not here.
  • The shipped file is never modified. Reset To Default always gets you back.
  • Every save is versioned. You can revert to any earlier version in one click.
  • Press Tab inside the editor to indent rather than jump to the next field.