Fix: admin view extends Pterodactyl layout with proper AdminLTE styling

Rewrote view.blade.php to use @extends('layouts.admin'), @section blocks,
AdminLTE box/callout/table classes, and standard Pterodactyl admin chrome.
Replaces custom inline styles with framework components.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude (Chronicler #83 - The Compiler)
2026-04-12 21:33:06 -05:00
parent 5775fc0cd6
commit bd9a5fcde3
2 changed files with 170 additions and 193 deletions

View File

@@ -0,0 +1,50 @@
# Chronicler Dispatch — Phase 11D UI Styling
**Date:** 2026-04-12
**From:** Chronicler #84 — The Meridian
**To:** Code
---
## UI Feedback from Michael
The current admin page renders as plain unstyled HTML — not integrated with Pterodactyl's admin UI. Michael specifically noted there was an earlier version that looked correct (dark theme, proper Pterodactyl admin chrome).
**What's needed:** `view.blade.php` must extend the Pterodactyl admin layout so it renders inside the proper admin chrome.
The standard pattern for Blueprint extensions in Pterodactyl admin pages:
```blade
@extends('layouts.admin')
@include('partials/admin.settings-notices')
@section('title')
ModpackChecker
@endsection
@section('content-header')
<h1>ModpackChecker<small>4-Platform Modpack Version Monitoring</small></h1>
@endsection
@section('content')
<div class="row">
<div class="col-xs-12">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">License</h3>
</div>
<div class="box-body">
{{-- license content here --}}
</div>
</div>
</div>
</div>
@endsection
```
Use AdminLTE's `box`, `box-primary`, `form-group`, `btn btn-primary` classes — that's what the rest of the Pterodactyl admin uses.
Michael has final approval on UI before it goes to the live panel. Please push an updated view.blade.php with proper Pterodactyl admin styling.
*— Chronicler #84, The Meridian*
**Fire + Frost + Foundation** 💙🔥❄️

View File

@@ -1,165 +1,100 @@
<form id="config-form" action="" method="POST">
<script>
document.addEventListener("DOMContentLoaded", function() {
showSaveButton();
});
@extends('layouts.admin')
@include('partials/admin.settings-notices')
function showSaveButton() {
const configForm = document.getElementById("config-form");
const saveOverlay = document.getElementById("save-overlay");
@section('title')
ModpackChecker
@endsection
configForm.addEventListener("change", function() {
saveOverlay.style.display = "inline";
setTimeout(() => {
saveOverlay.style.bottom = "10px";
}, 100);
});
@section('content-header')
<h1>ModpackChecker<small>4-Platform Modpack Version Monitoring</small></h1>
@endsection
configForm.addEventListener("input", function() {
saveOverlay.style.display = "inline";
setTimeout(() => {
saveOverlay.style.bottom = "10px";
}, 100);
});
}
</script>
@section('content')
<!-- Save button overlay -->
<div id="save-overlay">
{{ csrf_field() }}
<button type="submit" name="_method" value="PATCH" class="btn btn-primary btn-sm">
Save Changes
</button>
</div>
<style>
#save-overlay {
display: none;
position: fixed;
transition: bottom 0.3s;
bottom: -200px;
right: 20px;
z-index: 500;
padding: 15px;
background: #1a1a2e;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
}
</style>
<!-- Header -->
<div class="row" style="margin-bottom: 20px;">
<div class="col-xs-12">
<div style="display: flex; align-items: center; gap: 15px;">
<div style="width: 50px; height: 50px; background: linear-gradient(135deg, #FF6B35, #4ECDC4); border-radius: 10px; display: flex; align-items: center; justify-content: center;">
<i class="fa fa-cube" style="font-size: 24px; color: white;"></i>
</div>
<div>
<h2 style="margin: 0; color: #fff;">ModpackChecker</h2>
<p style="margin: 0; color: #888;">4-Platform Modpack Version Monitoring</p>
</div>
</div>
{{-- License Status Banners --}}
@if($license['status'] === 'expired')
<div class="row">
<div class="col-xs-12">
<div class="callout callout-danger">
<h4><i class="fa fa-exclamation-triangle"></i> License Expired</h4>
<p>Your license could not be validated. Pro features are disabled. Please check your order ID or contact support.</p>
</div>
</div>
<!-- License Status Banner -->
@if($license['status'] === 'expired')
<div class="row" style="margin-bottom: 15px;">
<div class="col-xs-12">
<div style="background: #4a1a1a; border-left: 4px solid #e74c3c; border-radius: 4px; padding: 15px;">
<h4 style="margin: 0 0 5px 0; color: #e74c3c;"><i class="fa fa-exclamation-triangle"></i> License Expired</h4>
<p style="margin: 0; color: #ccc;">Your license could not be validated. Pro features are disabled. Please check your order ID or contact support.</p>
</div>
</div>
@elseif($license['status'] === 'grace')
<div class="row">
<div class="col-xs-12">
<div class="callout callout-warning">
<h4><i class="fa fa-clock-o"></i> License Validation Warning</h4>
<p>Could not reach license server. Grace period expires: <strong>{{ $license['grace_expires'] }}</strong></p>
</div>
</div>
@elseif($license['status'] === 'grace')
<div class="row" style="margin-bottom: 15px;">
<div class="col-xs-12">
<div style="background: #4a3a1a; border-left: 4px solid #f39c12; border-radius: 4px; padding: 15px;">
<h4 style="margin: 0 0 5px 0; color: #f39c12;"><i class="fa fa-clock-o"></i> License Validation Warning</h4>
<p style="margin: 0; color: #ccc;">Could not reach license server. Grace period expires: <strong>{{ $license['grace_expires'] }}</strong></p>
</div>
</div>
</div>
@endif
</div>
@endif
<form action="{{ $root }}" method="POST">
{{ csrf_field() }}
<!-- License Activation -->
<div class="row">
{{-- License Activation --}}
<div class="col-xs-12 col-md-6">
<div class="box box-warning">
<div class="box-header with-border">
<h3 class="box-title">
<i class="fa fa-id-card"></i> License
@if($license['status'] === 'active')
<span class="label label-success" style="margin-left: 10px;">Active</span>
@elseif($license['status'] === 'grace')
<span class="label label-warning" style="margin-left: 10px;">Grace Period</span>
@elseif($license['status'] === 'expired')
<span class="label label-danger" style="margin-left: 10px;">Expired</span>
@else
<span class="label label-default" style="margin-left: 10px;">Not Activated</span>
@endif
</h3>
<div class="box-tools pull-right">
@if($license['status'] === 'active')
<span class="label label-success">Active</span>
@elseif($license['status'] === 'grace')
<span class="label label-warning">Grace Period</span>
@elseif($license['status'] === 'expired')
<span class="label label-danger">Expired</span>
@else
<span class="label label-default">Not Activated</span>
@endif
</div>
</div>
<div class="box-body">
<div class="form-group">
<label class="control-label">BuiltByBit Order ID</label>
<input
type="text"
name="order_id"
id="order_id"
value="{{ $license['order_id'] }}"
placeholder="Enter your order ID..."
class="form-control"
/>
<p class="text-muted small" style="margin-top: 8px;">
Enter the order ID from your BuiltByBit purchase to activate.
</p>
<input type="text" name="order_id" value="{{ $license['order_id'] }}"
placeholder="Enter your order ID..." class="form-control" />
<p class="text-muted small">Enter the order ID from your BuiltByBit purchase to activate.</p>
</div>
@if($license['status'] === 'active' || $license['status'] === 'grace')
<div style="margin-top: 8px; padding: 10px; background: #2a2a3e; border-radius: 4px;">
<p style="margin: 0; color: #aaa; font-size: 12px;">
<strong>Tier:</strong> {{ ucfirst($license['tier']) }}
&nbsp;|&nbsp;
<strong>Last Validated:</strong> {{ $license['last_validated'] ?: 'Never' }}
</p>
</div>
@endif
@if(!empty($license['order_id']))
<div style="margin-top: 10px;">
<button type="submit" name="deactivate_license" value="1" class="btn btn-danger btn-xs"
onclick="return confirm('Are you sure you want to deactivate? This frees the activation slot.')">
Deactivate License
</button>
<div class="well well-sm">
<strong>Tier:</strong> {{ ucfirst($license['tier']) }}
&nbsp;|&nbsp;
<strong>Last Validated:</strong> {{ $license['last_validated'] ?: 'Never' }}
</div>
@endif
</div>
@if(!empty($license['order_id']))
<div class="box-footer">
<button type="submit" name="deactivate_license" value="1" class="btn btn-danger btn-xs"
onclick="return confirm('Are you sure? This frees the activation slot.')">
Deactivate License
</button>
</div>
@endif
</div>
</div>
<!-- CurseForge API Key -->
{{-- CurseForge API Key --}}
<div class="col-xs-12 col-md-6">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">
<i class="fa fa-key"></i> CurseForge API Key
</h3>
<h3 class="box-title"><i class="fa fa-key"></i> CurseForge API Key</h3>
</div>
<div class="box-body">
<div class="form-group">
<label class="control-label">API Key (BYOK)</label>
<input
type="password"
name="curseforge_api_key"
id="curseforge_api_key"
value="{{ $curseforge_api_key }}"
placeholder="$2a$10$..."
class="form-control"
autocomplete="off"
/>
<p class="text-muted small" style="margin-top: 8px;">
<input type="password" name="curseforge_api_key" value="{{ $curseforge_api_key }}"
placeholder="$2a$10$..." class="form-control" autocomplete="off" />
<p class="text-muted small">
Get your free API key from
<a href="https://console.curseforge.com/" target="_blank">console.curseforge.com</a>.
Required for CurseForge modpack detection.
</p>
</div>
</div>
@@ -168,29 +103,28 @@
</div>
<div class="row">
<!-- Check Interval (PRO TIER) -->
{{-- Check Interval (PRO) --}}
<div class="col-xs-12 col-md-6">
<div class="box box-info">
<div class="box-header with-border">
<h3 class="box-title">
<i class="fa fa-clock-o"></i> Check Interval
<span class="label label-warning" style="margin-left: 10px;">PRO TIER</span>
<span class="label label-warning">PRO</span>
</h3>
</div>
<div class="box-body">
<div class="form-group">
<label class="control-label">Automatic Check Frequency</label>
<select class="form-control" name="check_interval" id="check_interval"
<select class="form-control" name="check_interval"
{{ $license['tier'] !== 'professional' || $license['status'] === 'expired' ? 'disabled' : '' }}>
<option value="daily" {{ $check_interval === 'daily' ? 'selected' : '' }}>Daily (24 Hours)</option>
<option value="12h" {{ $check_interval === '12h' ? 'selected' : '' }}>Every 12 Hours</option>
<option value="6h" {{ $check_interval === '6h' ? 'selected' : '' }}>Every 6 Hours</option>
</select>
<p class="text-muted small" style="margin-top: 8px;">
<p class="text-muted small">
@if($license['tier'] === 'professional' && $license['status'] !== 'expired')
Professional tier custom check intervals enabled.
@else
Standard tier is locked to daily checks.
Upgrade to Professional for more frequent automated checks.
@endif
</p>
@@ -199,32 +133,27 @@
</div>
</div>
<!-- Discord Webhook (PRO TIER) -->
{{-- Discord Webhook (PRO) --}}
<div class="col-xs-12 col-md-6">
<div class="box box-success">
<div class="box-header with-border">
<h3 class="box-title">
<i class="fa fa-bell"></i> Discord Notifications
<span class="label label-warning" style="margin-left: 10px;">PRO TIER</span>
<span class="label label-warning">PRO</span>
</h3>
</div>
<div class="box-body">
<div class="form-group">
<label class="control-label">Webhook URL</label>
<input
type="url"
name="discord_webhook_url"
id="discord_webhook_url"
value="{{ $discord_webhook_url }}"
placeholder="https://discord.com/api/webhooks/..."
class="form-control"
{{ $license['tier'] !== 'professional' || $license['status'] === 'expired' ? 'disabled' : '' }}
/>
<p class="text-muted small" style="margin-top: 8px;">
<input type="url" name="discord_webhook_url" value="{{ $discord_webhook_url }}"
placeholder="https://discord.com/api/webhooks/..."
class="form-control"
{{ $license['tier'] !== 'professional' || $license['status'] === 'expired' ? 'disabled' : '' }} />
<p class="text-muted small">
@if($license['tier'] === 'professional' && $license['status'] !== 'expired')
Professional tier Discord webhook alerts enabled.
@else
Upgrade to Professional to receive automated update alerts in your Discord server.
Upgrade to Professional for Discord update alerts.
@endif
</p>
</div>
@@ -234,58 +163,50 @@
</div>
<div class="row">
<!-- Supported Platforms -->
{{-- Supported Platforms --}}
<div class="col-xs-12 col-md-6">
<div class="box box-default">
<div class="box-header with-border">
<h3 class="box-title">
<i class="fa fa-check-circle"></i> Supported Platforms
</h3>
<h3 class="box-title"><i class="fa fa-check-circle"></i> Supported Platforms</h3>
</div>
<div class="box-body">
<ul style="list-style: none; padding: 0; margin: 0;">
<li style="padding: 8px 0; border-bottom: 1px solid #333;">
<i class="fa fa-fire" style="color: #f16436; width: 20px;"></i>
<strong>CurseForge</strong>
<span class="text-muted small">(Requires API Key)</span>
</li>
<li style="padding: 8px 0; border-bottom: 1px solid #333;">
<i class="fa fa-leaf" style="color: #1bd96a; width: 20px;"></i>
<strong>Modrinth</strong>
<span class="text-muted small">(No key required)</span>
</li>
<li style="padding: 8px 0; border-bottom: 1px solid #333;">
<i class="fa fa-cogs" style="color: #4a90d9; width: 20px;"></i>
<strong>Technic</strong>
<span class="text-muted small">(No key required)</span>
</li>
<li style="padding: 8px 0;">
<i class="fa fa-cube" style="color: #e04e39; width: 20px;"></i>
<strong>FTB (modpacks.ch)</strong>
<span class="text-muted small">
<div class="box-body no-padding">
<table class="table">
<tr>
<td><i class="fa fa-fire text-red"></i> <strong>CurseForge</strong></td>
<td class="text-muted">Requires API Key</td>
</tr>
<tr>
<td><i class="fa fa-leaf text-green"></i> <strong>Modrinth</strong></td>
<td class="text-muted">No key required</td>
</tr>
<tr>
<td><i class="fa fa-cogs text-blue"></i> <strong>Technic</strong></td>
<td class="text-muted">No key required</td>
</tr>
<tr>
<td><i class="fa fa-cube text-red"></i> <strong>FTB</strong></td>
<td>
@if($license['tier'] === 'professional')
(Enabled Professional)
<span class="text-green">Enabled</span>
@else
(PRO TIER only)
<span class="label label-warning">PRO</span>
@endif
</span>
</li>
</ul>
</td>
</tr>
</table>
</div>
</div>
</div>
<!-- Update Available -->
{{-- Update Available --}}
@if(!empty($license['latest_version']) && $license['latest_version'] !== '1.0.0')
<div class="col-xs-12 col-md-6">
<div class="box box-warning">
<div class="box-header with-border">
<h3 class="box-title">
<i class="fa fa-download"></i> Update Available
</h3>
<h3 class="box-title"><i class="fa fa-download"></i> Update Available</h3>
</div>
<div class="box-body">
<p>A new version (<strong>{{ $license['latest_version'] }}</strong>) is available.</p>
<p>Version <strong>{{ $license['latest_version'] }}</strong> is available.</p>
<a href="https://builtbybit.com/" target="_blank" class="btn btn-warning btn-sm">
Download from BuiltByBit
</a>
@@ -295,32 +216,38 @@
@endif
</div>
<!-- Footer Info -->
{{-- How It Works --}}
<div class="row">
<div class="col-xs-12">
<div style="background: #1a1a2e; border-left: 4px solid #4ECDC4; border-radius: 4px; padding: 15px; margin-bottom: 15px;">
<h4 style="margin: 0 0 10px 0; color: #fff;"><i class="fa fa-info-circle" style="color: #4ECDC4;"></i> How It Works</h4>
<p style="margin-bottom: 0; color: #ccc;">
<div class="callout callout-info">
<h4><i class="fa fa-info-circle"></i> How It Works</h4>
<p>
ModpackChecker automatically detects modpacks via Egg Variables or file fingerprinting.
Set <code style="background: #2a2a3e; padding: 2px 6px; border-radius: 3px;">MODPACK_PLATFORM</code> and
<code style="background: #2a2a3e; padding: 2px 6px; border-radius: 3px;">MODPACK_ID</code> in your server's startup variables
for the most reliable detection, or let the extension scan for
<code style="background: #2a2a3e; padding: 2px 6px; border-radius: 3px;">manifest.json</code> /
<code style="background: #2a2a3e; padding: 2px 6px; border-radius: 3px;">modrinth.index.json</code> files.
Set <code>MODPACK_PLATFORM</code> and <code>MODPACK_ID</code> in your server's startup
variables for the most reliable detection.
</p>
</div>
</div>
</div>
<!-- Support -->
{{-- Save Button --}}
<div class="row">
<div class="col-xs-12">
<div style="background: #1a1a2e; border-left: 4px solid #FF6B35; border-radius: 4px; padding: 15px;">
<h4 style="margin: 0 0 10px 0; color: #fff;"><i class="fa fa-life-ring" style="color: #FF6B35;"></i> Need Help?</h4>
<p style="margin-bottom: 0; color: #ccc;">
Join our Discord for support: <a href="https://firefrostgaming.com/discord" target="_blank" style="color: #4ECDC4;">firefrostgaming.com/discord</a>
</p>
<button type="submit" name="_method" value="PATCH" class="btn btn-primary">
<i class="fa fa-save"></i> Save Changes
</button>
</div>
</div>
{{-- Support --}}
<div class="row" style="margin-top: 20px;">
<div class="col-xs-12">
<div class="callout callout-warning">
<h4><i class="fa fa-life-ring"></i> Need Help?</h4>
<p>Join our Discord for support: <a href="https://firefrostgaming.com/discord" target="_blank">firefrostgaming.com/discord</a></p>
</div>
</div>
</div>
</form>
@endsection