Compare commits
3 Commits
5c5829e438
...
3fc2f3340b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3fc2f3340b | ||
|
|
d404054887 | ||
|
|
d705160b55 |
52
src/app/Http/Controllers/AdminController.php
Normal file
52
src/app/Http/Controllers/AdminController.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Setting;
|
||||
|
||||
class AdminController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
return view('admin.index');
|
||||
}
|
||||
|
||||
public function dashboardSettings($dashboard)
|
||||
{
|
||||
// Define available settings per dashboard here for simplicity
|
||||
$schema = [];
|
||||
if ($dashboard === 'procurement') {
|
||||
$schema = [
|
||||
['key' => 'target_margin', 'name' => 'Target Margin (%)', 'type' => 'integer', 'default' => 20, 'description' => 'Target gross margin percentage for alerts.'],
|
||||
['key' => 'low_stock_threshold', 'name' => 'Low Stock Warning', 'type' => 'integer', 'default' => 50, 'description' => 'Quantity at which a product is considered low stock.'],
|
||||
['key' => 'default_date_range', 'name' => 'Default Date Filter', 'type' => 'string', 'default' => 'YTD', 'description' => 'Default date range on load (e.g. YTD, All).'],
|
||||
];
|
||||
} else if ($dashboard === 'sales') {
|
||||
$schema = [
|
||||
['key' => 'monthly_target', 'name' => 'Monthly Sales Target', 'type' => 'integer', 'default' => 100000, 'description' => 'Overall monthly sales target.'],
|
||||
];
|
||||
} else {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
// Fetch current settings from DB
|
||||
$settings = Setting::where('dashboard', $dashboard)->get()->keyBy('key');
|
||||
|
||||
return view('admin.settings', compact('dashboard', 'schema', 'settings'));
|
||||
}
|
||||
|
||||
public function updateSettings(Request $request, $dashboard)
|
||||
{
|
||||
$settingsData = $request->except('_token');
|
||||
|
||||
foreach ($settingsData as $key => $value) {
|
||||
Setting::updateOrCreate(
|
||||
['dashboard' => $dashboard, 'key' => $key],
|
||||
['value' => $value]
|
||||
);
|
||||
}
|
||||
|
||||
return redirect()->back()->with('success', ucfirst($dashboard) . ' settings saved successfully!');
|
||||
}
|
||||
}
|
||||
39
src/app/Models/Setting.php
Normal file
39
src/app/Models/Setting.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Setting extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'dashboard',
|
||||
'key',
|
||||
'value',
|
||||
'type',
|
||||
'name',
|
||||
'description',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get a setting value, returning the provided default if not found.
|
||||
*/
|
||||
public static function getValue($dashboard, $key, $default = null)
|
||||
{
|
||||
$setting = self::where('dashboard', $dashboard)->where('key', $key)->first();
|
||||
if (!$setting) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
switch ($setting->type) {
|
||||
case 'boolean':
|
||||
return filter_var($setting->value, FILTER_VALIDATE_BOOLEAN);
|
||||
case 'integer':
|
||||
return (int) $setting->value;
|
||||
case 'json':
|
||||
return json_decode($setting->value, true);
|
||||
default:
|
||||
return $setting->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
26
src/apply_indexes_safe.php
Executable file
26
src/apply_indexes_safe.php
Executable file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
require __DIR__.'/vendor/autoload.php';
|
||||
$app = require_once __DIR__.'/bootstrap/app.php';
|
||||
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
|
||||
$kernel->bootstrap();
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
$sql = file_get_contents('/var/www/gauges.stargas.co.za/add_indexes.sql');
|
||||
$queries = array_filter(array_map('trim', explode(';', $sql)));
|
||||
|
||||
foreach ($queries as $query) {
|
||||
if (empty($query) || str_starts_with($query, '--')) continue;
|
||||
echo "Running: " . substr($query, 0, 60) . "...\n";
|
||||
try {
|
||||
DB::unprepared($query);
|
||||
echo "Success.\n";
|
||||
} catch (\Exception $e) {
|
||||
if (str_contains($e->getMessage(), 'Duplicate key name')) {
|
||||
echo "Index already exists, skipping.\n";
|
||||
} else {
|
||||
echo "Error: " . $e->getMessage() . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
echo "Done.\n";
|
||||
0
src/bootstrap/cache/.gitignore
vendored
Normal file → Executable file
0
src/bootstrap/cache/.gitignore
vendored
Normal file → Executable file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('settings', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('dashboard')->index(); // e.g., 'procurement', 'sales', 'global'
|
||||
$table->string('key');
|
||||
$table->text('value')->nullable();
|
||||
$table->string('type')->default('string'); // string, boolean, integer, json
|
||||
$table->string('name')->nullable(); // Human-readable name
|
||||
$table->text('description')->nullable();
|
||||
$table->timestamps();
|
||||
|
||||
$table->unique(['dashboard', 'key']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('settings');
|
||||
}
|
||||
};
|
||||
2421
src/package-lock.json
generated
Normal file
2421
src/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
28
src/resources/views/admin/index.blade.php
Normal file
28
src/resources/views/admin/index.blade.php
Normal file
@@ -0,0 +1,28 @@
|
||||
@extends('admin.layout')
|
||||
|
||||
@section('content')
|
||||
<div class="mb-8">
|
||||
<h2 class="text-2xl font-bold text-white tracking-tight">System Configuration Overview</h2>
|
||||
<p class="text-slate-400 mt-2">Manage dashboard settings and globally defined parameters.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
|
||||
<a href="/admin/settings/procurement" class="glass rounded-xl p-6 group transition-all duration-300 hover:border-red-500/50 hover:bg-white/5 block">
|
||||
<div class="w-12 h-12 rounded-lg bg-red-500/20 text-red-500 flex items-center justify-center mb-4 group-hover:scale-110 transition-transform">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z"/></svg>
|
||||
</div>
|
||||
<h3 class="text-lg font-bold text-white mb-2">Procurement Settings</h3>
|
||||
<p class="text-sm text-slate-400">Configure thresholds, margins, and default variables for the procurement module.</p>
|
||||
</a>
|
||||
|
||||
<a href="/admin/settings/sales" class="glass rounded-xl p-6 group transition-all duration-300 hover:border-orange-500/50 hover:bg-white/5 block">
|
||||
<div class="w-12 h-12 rounded-lg bg-orange-500/20 text-orange-500 flex items-center justify-center mb-4 group-hover:scale-110 transition-transform">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
|
||||
</div>
|
||||
<h3 class="text-lg font-bold text-slate-300 mb-2">Sales Settings (WIP)</h3>
|
||||
<p class="text-sm text-slate-500">Configure revenue targets and metric parameters for the upcoming sales dashboard.</p>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
@endsection
|
||||
112
src/resources/views/admin/layout.blade.php
Normal file
112
src/resources/views/admin/layout.blade.php
Normal file
@@ -0,0 +1,112 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Admin Panel - Stargas Dashboards</title>
|
||||
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
body {
|
||||
background: linear-gradient(135deg, #0a0a0a 0%, #1a0a0a 30%, #0d0d0d 60%, #0a0a0a 100%);
|
||||
min-height: 100vh;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.glass {
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
backdrop-filter: blur(12px);
|
||||
border: 1px solid rgba(227, 25, 55, 0.12);
|
||||
}
|
||||
|
||||
.stargas-accent {
|
||||
background: linear-gradient(90deg, #E31937, #FFD700, #E31937);
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
.fade-in {
|
||||
animation: fadeIn 0.5s ease-out forwards;
|
||||
}
|
||||
@keyframes fadeIn {
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
from { opacity: 0; transform: translateY(10px); }
|
||||
}
|
||||
|
||||
/* Nav links hover glow */
|
||||
.nav-link.active {
|
||||
background: rgba(227, 25, 55, 0.15);
|
||||
border-right: 3px solid #E31937;
|
||||
color: white;
|
||||
}
|
||||
.nav-link:hover:not(.active) {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
color: #fca5a5;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="text-white antialiased flex flex-col min-h-screen">
|
||||
<!-- Stargas Accent Line -->
|
||||
<div class="stargas-accent"></div>
|
||||
|
||||
<!-- Header -->
|
||||
<header class="glass sticky top-0 z-50 border-b border-white/5">
|
||||
<div class="max-w-[1600px] mx-auto px-6 py-3 flex items-center justify-between">
|
||||
<div class="flex items-center gap-4">
|
||||
<img src="/images/stargas-logo.svg" alt="Stargas" class="h-10">
|
||||
<div class="border-l border-white/10 pl-4">
|
||||
<h1 class="text-lg font-bold tracking-tight text-red-400">Admin Panel</h1>
|
||||
<p class="text-xs text-slate-400">System Configuration</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-4">
|
||||
<a href="/" class="px-3 py-2 text-xs font-medium rounded-lg bg-white/5 hover:bg-white/10 transition-colors border border-white/10 flex items-center gap-1.5 text-slate-300">
|
||||
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"/></svg>
|
||||
Hub
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="flex-1 flex max-w-[1600px] w-full mx-auto">
|
||||
<!-- Sidebar Navigation -->
|
||||
<aside class="w-64 glass border-x-0 border-y-0 border-r border-white/5 flex-shrink-0 pt-8">
|
||||
<nav class="space-y-1">
|
||||
<div class="px-6 mb-4">
|
||||
<h3 class="text-xs font-semibold text-slate-500 uppercase tracking-wider">Dashboards</h3>
|
||||
</div>
|
||||
|
||||
<a href="/admin" class="nav-link flex items-center gap-3 px-6 py-3 text-sm font-medium text-slate-400 transition-colors {{ request()->is('admin') ? 'active' : '' }}">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z"/></svg>
|
||||
Overview
|
||||
</a>
|
||||
|
||||
<a href="/admin/settings/procurement" class="nav-link flex items-center gap-3 px-6 py-3 text-sm font-medium text-slate-400 transition-colors {{ request()->is('admin/settings/procurement') ? 'active' : '' }}">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z"/></svg>
|
||||
Procurement
|
||||
</a>
|
||||
|
||||
<a href="/admin/settings/sales" class="nav-link flex items-center gap-3 px-6 py-3 text-sm font-medium text-slate-400 transition-colors {{ request()->is('admin/settings/sales') ? 'active' : '' }}">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
|
||||
Sales (WIP)
|
||||
</a>
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
<!-- Main Content Area -->
|
||||
<main class="flex-1 p-8 fade-in opacity-0">
|
||||
@if(session('success'))
|
||||
<div class="mb-6 p-4 rounded-lg bg-green-500/10 border border-green-500/30 flex items-start gap-3 fade-in">
|
||||
<svg class="w-5 h-5 text-green-400 shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
|
||||
<div>
|
||||
<h4 class="text-sm font-medium text-green-400">Success</h4>
|
||||
<div class="mt-1 text-sm text-green-400/80">{{ session('success') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@yield('content')
|
||||
</main>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
54
src/resources/views/admin/settings.blade.php
Normal file
54
src/resources/views/admin/settings.blade.php
Normal file
@@ -0,0 +1,54 @@
|
||||
@extends('admin.layout')
|
||||
|
||||
@section('content')
|
||||
<div class="mb-8 flex items-center justify-between">
|
||||
<div>
|
||||
<h2 class="text-2xl font-bold text-white tracking-tight">{{ ucfirst($dashboard) }} Settings</h2>
|
||||
<p class="text-slate-400 mt-2">Adjust constants and parameters specific to this dashboard.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form action="/admin/settings/{{ $dashboard }}" method="POST" class="glass rounded-2xl p-8 max-w-3xl border-t-4 border-t-red-700">
|
||||
@csrf
|
||||
|
||||
<div class="space-y-6">
|
||||
@foreach($schema as $field)
|
||||
@php
|
||||
// Retrieve existing value from DB or fallback to default
|
||||
$currentValue = isset($settings[$field['key']]) ? $settings[$field['key']]->value : $field['default'];
|
||||
@endphp
|
||||
|
||||
<div class="border-b border-white/5 pb-6 last:border-0 last:pb-0">
|
||||
<label for="{{ $field['key'] }}" class="block text-sm font-semibold text-slate-200 mb-1">
|
||||
{{ $field['name'] }}
|
||||
</label>
|
||||
<p class="text-xs text-slate-500 mb-3">{{ $field['description'] }}</p>
|
||||
|
||||
@if($field['type'] === 'boolean')
|
||||
<div class="flex items-center gap-3">
|
||||
<label class="relative inline-flex items-center cursor-pointer">
|
||||
<input type="hidden" name="{{ $field['key'] }}" value="0">
|
||||
<input type="checkbox" name="{{ $field['key'] }}" id="{{ $field['key'] }}" value="1" class="sr-only peer" {{ $currentValue ? 'checked' : '' }}>
|
||||
<div class="w-11 h-6 bg-white/10 peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-red-500/50 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-red-600"></div>
|
||||
</label>
|
||||
</div>
|
||||
@else
|
||||
<input type="{{ $field['type'] === 'integer' ? 'number' : 'text' }}"
|
||||
name="{{ $field['key'] }}"
|
||||
id="{{ $field['key'] }}"
|
||||
value="{{ $currentValue }}"
|
||||
class="w-full bg-white/5 border border-white/10 rounded-lg px-4 py-2 text-sm text-white focus:border-red-500 focus:outline-none focus:ring-1 focus:ring-red-500/30 transition-colors"
|
||||
>
|
||||
@endif
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div class="mt-8 pt-6 border-t border-white/10 flex items-center justify-end">
|
||||
<button type="submit" class="px-6 py-2.5 text-sm font-semibold rounded-lg bg-red-700 hover:bg-red-600 border border-red-500/50 transition-colors shadow-lg shadow-red-900/20 text-white flex items-center gap-2">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4"/></svg>
|
||||
Save Changes
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
@endsection
|
||||
@@ -110,6 +110,10 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-4">
|
||||
<a href="/" class="px-3 py-2 text-xs font-medium rounded-lg bg-white/5 hover:bg-white/10 transition-colors border border-white/10 flex items-center gap-1.5 text-slate-300">
|
||||
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/></svg>
|
||||
Hub
|
||||
</a>
|
||||
<span id="last-updated" class="text-xs text-slate-500"></span>
|
||||
<button onclick="loadAllData()" class="px-4 py-2 text-xs font-medium rounded-lg bg-red-700 hover:bg-red-600 transition-colors flex items-center gap-2 border border-red-600/30">
|
||||
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/></svg>
|
||||
|
||||
161
src/resources/views/landing.blade.php
Normal file
161
src/resources/views/landing.blade.php
Normal file
@@ -0,0 +1,161 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Stargas Dashboards</title>
|
||||
<!-- Tailwind via Vite -->
|
||||
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
||||
<!-- Inter Font -->
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
/* Animated gradient background — Stargas dark theme */
|
||||
body {
|
||||
background: linear-gradient(135deg, #0a0a0a 0%, #1a0a0a 30%, #0d0d0d 60%, #0a0a0a 100%);
|
||||
min-height: 100vh;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
/* Glass card effect */
|
||||
.glass {
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
backdrop-filter: blur(12px);
|
||||
border: 1px solid rgba(227, 25, 55, 0.12);
|
||||
}
|
||||
|
||||
/* Dashboard card hover glow */
|
||||
.dashboard-card {
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
.dashboard-card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 12px 40px rgba(227, 25, 55, 0.25);
|
||||
border-color: rgba(227, 25, 55, 0.4);
|
||||
background: rgba(255, 255, 255, 0.06);
|
||||
}
|
||||
|
||||
.disabled-card {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
border-style: dashed;
|
||||
}
|
||||
|
||||
/* Stargas accent line */
|
||||
.stargas-accent {
|
||||
background: linear-gradient(90deg, #E31937, #FFD700, #E31937);
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
/* Fade in animation */
|
||||
.fade-in {
|
||||
animation: fadeIn 0.8s ease-out forwards;
|
||||
opacity: 0;
|
||||
}
|
||||
@keyframes fadeIn {
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
from { opacity: 0; transform: translateY(20px); }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="text-white antialiased">
|
||||
<!-- Stargas Accent Line -->
|
||||
<div class="stargas-accent"></div>
|
||||
|
||||
<!-- Admin Link -->
|
||||
<div class="absolute top-6 right-6 z-50 fade-in">
|
||||
<a href="/admin" class="flex items-center gap-2 px-3 py-2 rounded-lg bg-white/5 hover:bg-white/10 transition-colors border border-white/10 text-xs font-medium text-slate-400 hover:text-white" title="Admin Control Panel">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/></svg>
|
||||
Settings
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<main class="max-w-[1200px] mx-auto px-6 py-16">
|
||||
|
||||
<!-- Hero Section -->
|
||||
<div class="flex flex-col items-center justify-center text-center mb-16 fade-in" style="animation-delay: 100ms">
|
||||
<div class="w-32 h-32 rounded-3xl glass flex items-center justify-center mb-8 p-4 bg-white/5 border-red-500/30 shadow-[0_0_50px_rgba(227,25,55,0.15)]">
|
||||
<img src="/images/stargas-logo.svg" alt="Stargas Energies" class="w-full h-auto drop-shadow-lg">
|
||||
</div>
|
||||
|
||||
<h1 class="text-4xl md:text-5xl font-bold tracking-tight mb-4">
|
||||
Systems <span class="bg-gradient-to-r from-red-500 to-yellow-500 text-transparent bg-clip-text">Hub</span>
|
||||
</h1>
|
||||
<p class="text-slate-400 max-w-xl mx-auto text-lg">
|
||||
Select a module below to access real-time analytics and powerful management tools for your division.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Dashboard Grid -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 max-w-5xl mx-auto">
|
||||
|
||||
<!-- Active: Procurement Dashboard -->
|
||||
<a href="/procurement" class="dashboard-card glass rounded-2xl p-6 flex flex-col group fade-in relative overflow-hidden block" style="animation-delay: 200ms">
|
||||
<div class="absolute top-0 right-0 p-4">
|
||||
<span class="inline-flex items-center rounded-md bg-green-500/10 px-2 py-1 text-xs font-medium text-green-400 ring-1 ring-inset ring-green-500/20">Active</span>
|
||||
</div>
|
||||
|
||||
<div class="w-14 h-14 rounded-xl bg-gradient-to-br from-red-600 to-red-900 flex items-center justify-center mb-6 shadow-lg shadow-red-900/40 group-hover:scale-110 transition-transform duration-300">
|
||||
<svg class="w-7 h-7 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z"/></svg>
|
||||
</div>
|
||||
|
||||
<h2 class="text-xl font-bold text-white mb-2 group-hover:text-red-400 transition-colors">Procurement</h2>
|
||||
<p class="text-sm text-slate-400 mb-6 flex-grow">
|
||||
Track supplier spend, analyze product margins, and monitor purchasing trends across the organization.
|
||||
</p>
|
||||
|
||||
<div class="text-sm font-medium text-red-500 flex items-center gap-1 mt-auto">
|
||||
Access Dashboard
|
||||
<svg class="w-4 h-4 transform group-hover:translate-x-1 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"/></svg>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<!-- Placeholder: Sales Dashboard -->
|
||||
<div class="glass disabled-card rounded-2xl p-6 flex flex-col fade-in relative" style="animation-delay: 300ms">
|
||||
<div class="absolute top-0 right-0 p-4">
|
||||
<span class="inline-flex items-center rounded-md bg-slate-500/10 px-2 py-1 text-xs font-medium text-slate-400 ring-1 ring-inset ring-slate-500/20">Coming Soon</span>
|
||||
</div>
|
||||
|
||||
<div class="w-14 h-14 rounded-xl bg-slate-800 flex items-center justify-center mb-6">
|
||||
<svg class="w-7 h-7 text-slate-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
|
||||
</div>
|
||||
|
||||
<h2 class="text-xl font-bold text-slate-300 mb-2">Sales Analytics</h2>
|
||||
<p class="text-sm text-slate-500 flex-grow">
|
||||
Monitor revenue streams, customer acquisition costs, and identify top performing regions.
|
||||
</p>
|
||||
|
||||
<div class="text-sm font-medium text-slate-600 flex items-center gap-1 mt-auto">
|
||||
In Development
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Placeholder: Inventory Operations -->
|
||||
<div class="glass disabled-card rounded-2xl p-6 flex flex-col fade-in relative" style="animation-delay: 400ms">
|
||||
<div class="absolute top-0 right-0 p-4">
|
||||
<span class="inline-flex items-center rounded-md bg-slate-500/10 px-2 py-1 text-xs font-medium text-slate-400 ring-1 ring-inset ring-slate-500/20">Planned</span>
|
||||
</div>
|
||||
|
||||
<div class="w-14 h-14 rounded-xl bg-slate-800 flex items-center justify-center mb-6">
|
||||
<svg class="w-7 h-7 text-slate-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4"/></svg>
|
||||
</div>
|
||||
|
||||
<h2 class="text-xl font-bold text-slate-300 mb-2">Inventory Control</h2>
|
||||
<p class="text-sm text-slate-500 flex-grow">
|
||||
Real-time stock levels, movement history, category tracking and predictive reordering.
|
||||
</p>
|
||||
|
||||
<div class="text-sm font-medium text-slate-600 flex items-center gap-1 mt-auto">
|
||||
Future Roadmap
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="mt-24 text-center text-xs text-slate-600 fade-in" style="animation-delay: 500ms">
|
||||
© <script>document.write(new Date().getFullYear())</script> Stargas Energies. All Rights Reserved.
|
||||
</div>
|
||||
</main>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,9 +1,21 @@
|
||||
<?php
|
||||
|
||||
use App\Http\Controllers\DashboardController;
|
||||
use App\Http\Controllers\AdminController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::get('/', [DashboardController::class, 'index']);
|
||||
Route::get('/', function() {
|
||||
return view('landing');
|
||||
});
|
||||
|
||||
Route::get('/procurement', [DashboardController::class, 'index']);
|
||||
|
||||
// Admin endpoints
|
||||
Route::prefix('admin')->group(function () {
|
||||
Route::get('/', [AdminController::class, 'index']);
|
||||
Route::get('/settings/{dashboard}', [AdminController::class, 'dashboardSettings']);
|
||||
Route::post('/settings/{dashboard}', [AdminController::class, 'updateSettings']);
|
||||
});
|
||||
|
||||
// Dashboard API endpoints
|
||||
Route::prefix('api/dashboard')->group(function () {
|
||||
|
||||
0
src/storage/app/.gitignore
vendored
Normal file → Executable file
0
src/storage/app/.gitignore
vendored
Normal file → Executable file
0
src/storage/app/private/.gitignore
vendored
Normal file → Executable file
0
src/storage/app/private/.gitignore
vendored
Normal file → Executable file
0
src/storage/app/public/.gitignore
vendored
Normal file → Executable file
0
src/storage/app/public/.gitignore
vendored
Normal file → Executable file
0
src/storage/framework/.gitignore
vendored
Normal file → Executable file
0
src/storage/framework/.gitignore
vendored
Normal file → Executable file
0
src/storage/framework/cache/.gitignore
vendored
Normal file → Executable file
0
src/storage/framework/cache/.gitignore
vendored
Normal file → Executable file
0
src/storage/framework/cache/data/.gitignore
vendored
Normal file → Executable file
0
src/storage/framework/cache/data/.gitignore
vendored
Normal file → Executable file
0
src/storage/framework/sessions/.gitignore
vendored
Normal file → Executable file
0
src/storage/framework/sessions/.gitignore
vendored
Normal file → Executable file
0
src/storage/framework/testing/.gitignore
vendored
Normal file → Executable file
0
src/storage/framework/testing/.gitignore
vendored
Normal file → Executable file
0
src/storage/framework/views/.gitignore
vendored
Normal file → Executable file
0
src/storage/framework/views/.gitignore
vendored
Normal file → Executable file
0
src/storage/logs/.gitignore
vendored
Normal file → Executable file
0
src/storage/logs/.gitignore
vendored
Normal file → Executable file
Reference in New Issue
Block a user