Files
backend_parkir/resources/views/setup/index.blade.php
T
pand03-CEOandClaude Sonnet 5 2a9b28581c Rapihin setup/member/lot-parking + fitur intercom, exclude WIP controller & file sampah dari git
Kumpulan perubahan yang udah numpuk di working tree: refactor Setup
(Gate/Vehicle/Member), rapihin memberin & stiker, service parking baru
(ParkingUtilsServices, NetworkService), model/migration lot-parking &
DHCP reservation, dan fitur baru Intercom (controller/model/migration/
view).

ReportTransaksiController versi lokal ini WIP (~90%, masih didebug) -
versi yang bener ada di server, jadi dikeluarin dari git (ditambahin
ke .gitignore) biar gak numpuk nindihin punya server pas git pull di
sana. Sekalian keluarin dump mentah tabel softseting (1.8MB, nyasar
ke-commit), file .bak, dan arsip ad-hoc (api.tgz, c.zip) yang emang
bukan source code.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01EAJc2mrpj2cSTe4oowLPzQ
2026-10-04 07:15:54 +07:00

604 lines
19 KiB
PHP

@extends('layouts.master')
@section('title', 'DHCP Reservations')
@section('content')
<div class="container-fluid py-4">
{{-- Header --}}
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<h4 class="mb-1">DHCP Reservations</h4>
<div class="text-muted small">Manage static DHCP leases by MAC address</div>
</div>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#reservationModal" onclick="openCreateModal()"><i class="bi bi-plus-lg me-1"></i> Add Reservation</button>
</div>
{{-- DHCP Server Card --}}
<div class="card border-0 shadow-sm mb-4">
<div class="card-body">
<div class="row align-items-center">
{{-- Server --}}
<div class="col-md-5">
<div class="d-flex align-items-center">
<div class="rounded-circle bg-success bg-opacity-10 d-flex align-items-center justify-content-center me-3" style="width:48px;height:48px;">
<i class="bi bi-hdd-network text-success fs-4"></i>
</div>
<div>
<div class="fw-semibold" id="dhcpServerHostname">DHCP LAB</div>
<div class="text-muted small"> <span id="dhcpServerIp">-</span>
<span class="mx-1">•</span>
<span id="dhcpServerInterface">-</span></div>
</div>
</div>
</div>
{{-- Status --}}
<div class="col-md-3 mt-3 mt-md-0">
<div class="small text-muted">Status</div>
<div class="mt-1">
@if($dhcpStatus['running'])
<span id="dhcpStatusBadge" class="badge rounded-pill bg-success bg-opacity-10 text-success">
<span
class="d-inline-block rounded-circle bg-success me-1"
style="width:7px;height:7px;"
></span>
Running
</span>
@else
<span id="dhcpStatusBadge" class="badge rounded-pill bg-danger bg-opacity-10 text-danger">
<span
class="d-inline-block rounded-circle bg-danger me-1"
style="width:7px;height:7px;"
></span>
Stopped
</span>
@endif
</div>
</div>
{{-- Reservations --}}
<div class="col-md-2 mt-3 mt-md-0">
<div class="small text-muted">
Reservations
</div>
<div class="fw-semibold mt-1" id="activeClients">
{{ $dhcpStatus['active_clients'] }}
<span class="text-muted fw-normal small">
active
</span>
</div>
</div>
{{-- Last Apply --}}
<div class="col-md-2 mt-3 mt-md-0">
<div class="small text-muted">
Last Applied
</div>
<div
class="fw-semibold mt-1"
id="lastApplied"
>
-
</div>
</div>
</div>
</div>
</div>
{{-- Filters --}}
<div class="card border-0 shadow-sm mb-3">
<div class="card-body py-3">
<div class="row g-2">
<div class="col-md-5">
<div class="input-group">
<span class="input-group-text bg-white">
<i class="bi bi-search"></i>
</span>
<input
type="text"
class="form-control form-control-sm border-start-0"
id="searchReservation"
placeholder="Search hostname, MAC or IP..."
>
</div>
</div>
<div class="col-md-3">
<select
class="form-select"
id="statusFilter"
>
<option value="">All Status</option>
<option value="active">Active</option>
<option value="disabled">Disabled</option>
</select>
</div>
</div>
</div>
</div>
{{-- Reservation Table --}}
<div class="card border-0 shadow-sm">
<div class="card-body p-0">
<div class="table-responsive">
<table
class="table table-hover align-middle mb-0"
id="reservationTable">
<thead class="table-light">
<tr>
<th class="px-4">Hostname</th>
<th>MAC Address</th>
<th>IP Address</th>
<th>Status</th>
<th class="text-end px-4"></th>
</tr>
</thead>
<tbody>
@forelse($reservations as $reservation)
<tr>
<td class="px-4">
<div class="fw-semibold">
{{ $reservation->hostname }}
</div>
@if(!empty($reservation->description))
<div class="text-muted small">
{{ $reservation->description }}
</div>
@endif
</td>
<td>
<code>{{ $reservation->mac_address }}</code>
</td>
<td>
<span class="fw-semibold">
{{ $reservation->ip_address }}
</span>
</td>
<td>
@if($reservation->enabled)
<span class="badge rounded-pill bg-success bg-opacity-10 text-success">
Active
</span>
@else
<span class="badge rounded-pill bg-secondary bg-opacity-10 text-secondary">
Disabled
</span>
@endif
</td>
<td class="text-end px-4">
<div class="btn-group">
<button
type="button"
class="btn btn-sm btn-light"
onclick="editReservation(
@js($reservation->id),
@js($reservation->hostname),
@js($reservation->mac_address),
@js($reservation->ip_address),
@js((bool) $reservation->enabled)
)"
>
<i class="bi bi-pencil"></i>
</button>
<button
type="button"
class="btn btn-sm btn-light text-danger"
onclick="deleteReservation(
@js($reservation->id),
@js($reservation->hostname)
)"
>
<i class="bi bi-trash"></i>
</button>
</div>
</td>
</tr>
@empty
<tr>
<td colspan="5" class="text-center py-5 text-muted">
No DHCP reservations found.
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
{{-- Footer --}}
<div class="card-footer bg-white border-0">
<div class="d-flex justify-content-between align-items-center">
<div class="text-muted small">
Showing {{ $reservations->count() }} reservations
</div>
<div>
@if(method_exists($reservations, 'previousPageUrl') && $reservations->previousPageUrl())
<a href="{{ $reservations->previousPageUrl() }}"
class="btn btn-sm btn-outline-secondary">
Previous
</a>
@else
<button class="btn btn-sm btn-outline-secondary" disabled>
Previous
</button>
@endif
@if(method_exists($reservations, 'nextPageUrl') && $reservations->nextPageUrl())
<a href="{{ $reservations->nextPageUrl() }}"
class="btn btn-sm btn-outline-secondary">
Next
</a>
@else
<button class="btn btn-sm btn-outline-secondary" disabled>
Next
</button>
@endif
</div>
</div>
</div>
</div>
{{-- Apply Section --}}
<div class="card border-0 shadow-sm mt-4">
<div class="card-body">
<div class="row align-items-center">
<div class="col">
<div class="fw-semibold">
DHCP Configuration
</div>
<div class="text-muted small mt-1">
Changes are stored in the database
until you apply the configuration.
</div>
</div>
<div class="col-auto">
<button
class="btn btn-outline-secondary me-2"
onclick="testDhcp()"
>
<i class="bi bi-shield-check me-1"></i>
Test Configuration
</button>
<button
class="btn btn-primary"
onclick="applyDhcp()"
>
<i class="bi bi-arrow-repeat me-1"></i>
Apply Changes
</button>
</div>
</div>
</div>
</div>
<div class="card border-0 shadow-sm">
<div class="card-header bg-white border-0
d-flex justify-content-between
align-items-center">
<div>
<div class="fw-semibold">
Recent DHCP Events
</div>
<div class="text-muted small">
Latest activity from DHCP server
</div>
</div>
<button
type="button"
class="btn btn-sm btn-light"
onclick="loadDhcpLogs()"
>
<i class="bi bi-arrow-clockwise"></i>
Refresh
</button>
</div>
<div class="card-body p-0">
<div
id="dhcpLogs"
class="font-monospace small"
style="
max-height: 320px;
overflow-y: auto;
"
>
<div class="text-muted p-4">
Loading DHCP events...
</div>
</div>
</div>
</div>
</div>
{{-- Add / Edit Modal --}}
<div
class="modal fade"
id="reservationModal"
tabindex="-1"
>
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content border-0 shadow">
<div class="modal-header">
<div>
<h5
class="modal-title mb-1"
id="reservationModalTitle"
>
Add DHCP Reservation
</h5>
<div class="text-muted small">
Assign a fixed IP address to a DHCP client
</div>
</div>
<button
type="button"
class="btn-close"
data-bs-dismiss="modal"
></button>
</div>
<form id="reservationForm">
<div class="modal-body">
<input
type="hidden"
id="reservationId"
value=""
>
{{-- Hostname --}}
<div class="mb-3">
<label class="form-label fw-semibold">
Hostname
</label>
<input
type="text"
class="form-control"
id="hostname"
placeholder="e.g. kasir-01"
required
>
<div class="form-text">
Only letters, numbers, dash and underscore.
</div>
</div>
{{-- MAC --}}
<div class="mb-3">
<label class="form-label fw-semibold">
MAC Address
</label>
<input
type="text"
class="form-control font-monospace"
id="macAddress"
placeholder="AA:BB:CC:DD:EE:FF"
maxlength="17"
required
>
<div
class="invalid-feedback"
id="macError"
>
Invalid MAC address.
</div>
</div>
{{-- IP --}}
<div class="mb-3">
<label class="form-label fw-semibold">
IP Address
</label>
<input
type="text"
class="form-control font-monospace"
id="ipAddress"
placeholder="192.168.10.50"
required
>
<div
class="invalid-feedback"
id="ipError"
>
Invalid IP address.
</div>
</div>
{{-- Enabled --}}
<div
class="form-check form-switch"
>
<input
class="form-check-input"
type="checkbox"
id="enabled"
checked
>
<label
class="form-check-label"
for="enabled"
>
Enable reservation
</label>
</div>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-light"
data-bs-dismiss="modal"
>
Cancel
</button>
<button
type="submit"
class="btn btn-primary"
>
<i class="bi bi-check-lg me-1"></i>
Save Reservation
</button>
</div>
</form>
</div>
</div>
</div>
{{-- Apply Confirmation --}}
<div
class="modal fade"
id="applyModal"
tabindex="-1"
>
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content border-0 shadow">
<div class="modal-body text-center p-4">
<div
class="rounded-circle bg-warning bg-opacity-10
d-flex align-items-center justify-content-center
mx-auto mb-3"
style="width:64px;height:64px;"
>
<i class="bi bi-exclamation-triangle text-warning fs-3"></i>
</div>
<h5>
Apply DHCP Configuration?
</h5>
<p class="text-muted mb-4">
The DHCP configuration will be validated
before the DHCP service is restarted.
</p>
<button
class="btn btn-light me-2"
data-bs-dismiss="modal"
>
Cancel
</button>
<button
class="btn btn-primary"
onclick="confirmApply()"
>
Apply Configuration
</button>
</div>
</div>
</div>
</div>
@endsection
@section('javascript')
<script>
window.dhcpConfig = {
reservationStoreUrl: @json(route('dhcp.reservations.store')),
reservationBaseUrl: @json(url('/dhcp/reservations')),
applyUrl: @json(route('dhcp.apply')),
statusUrl: @json(route('dhcp.status')),
logsUrl: @json(route('dhcp.logs')),
};
</script>
<script src="{{ asset('js/setup/dhcp.js') }}"></script>
@endsection