Implemented settings
This commit is contained in:
@@ -1,7 +1,353 @@
|
||||
@page "/settings"
|
||||
@rendermode InteractiveServer
|
||||
@using System
|
||||
@using System.Collections.Generic
|
||||
@using System.Linq
|
||||
@using System.Threading.Tasks
|
||||
|
||||
<h3>Settings</h3>
|
||||
<PageTitle>Enterprise Suite Settings</PageTitle>
|
||||
|
||||
<div class="max-w-[1600px] mx-auto pb-8">
|
||||
<!-- Page Header -->
|
||||
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-end mb-[22px] gap-3">
|
||||
<div>
|
||||
<h2 class="text-[22px] font-bold text-[#1f2a3a] tracking-tight outline-none focus:outline-none select-none" tabindex="-1">Corporate Suite Settings</h2>
|
||||
<p class="text-[13px] text-[#5a6577] mt-1">Configure global travel policies, Lodge Card reconciliation parameters, and GDS sync configurations</p>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<button @onclick="@(() => SaveAllSettings())" class="flex items-center gap-1.5 px-[16px] py-2 bg-[#0066b3] text-white rounded-lg text-[13px] font-semibold hover:bg-[#003b71] transition-all cursor-pointer shadow-xs">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-4 h-4">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
Save All Changes
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Alert / Feedback Notification *@
|
||||
@if (!string.IsNullOrEmpty(_alertFeedback))
|
||||
{
|
||||
<div class="mb-6 p-4 bg-[#effaf3] border-l-4 border-[#22a06b] rounded-r-lg text-sm text-[#1b8054] flex items-center gap-2.5 shadow-xs animate-in fade-in duration-300">
|
||||
<svg class="w-5 h-5 text-[#22a06b] shrink-0" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
<span>@_alertFeedback</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Tab Navigation -->
|
||||
<div class="flex border-b border-[#e4eaf2] mb-6 gap-2">
|
||||
<button @onclick="@(() => _activeTab = "policy")" class="px-4 py-2 text-[13px] font-semibold border-b-2 transition-all cursor-pointer @(_activeTab == "policy" ? "border-[#0066b3] text-[#0066b3]" : "border-transparent text-[#5a6577] hover:text-[#1f2a3a]")">
|
||||
Travel Policies
|
||||
</button>
|
||||
<button @onclick="@(() => _activeTab = "financial")" class="px-4 py-2 text-[13px] font-semibold border-b-2 transition-all cursor-pointer @(_activeTab == "financial" ? "border-[#0066b3] text-[#0066b3]" : "border-transparent text-[#5a6577] hover:text-[#1f2a3a]")">
|
||||
Financial & Lodge Card
|
||||
</button>
|
||||
<button @onclick="@(() => _activeTab = "gds")" class="px-4 py-2 text-[13px] font-semibold border-b-2 transition-all cursor-pointer @(_activeTab == "gds" ? "border-[#0066b3] text-[#0066b3]" : "border-transparent text-[#5a6577] hover:text-[#1f2a3a]")">
|
||||
GDS & API Sync
|
||||
</button>
|
||||
<button @onclick="@(() => _activeTab = "safety")" class="px-4 py-2 text-[13px] font-semibold border-b-2 transition-all cursor-pointer @(_activeTab == "safety" ? "border-[#0066b3] text-[#0066b3]" : "border-transparent text-[#5a6577] hover:text-[#1f2a3a]")">
|
||||
Duty of Care & Security
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 lg:grid-cols-[2fr_1fr] gap-6">
|
||||
|
||||
<!-- Left Column: Settings Pane -->
|
||||
<div class="bg-white rounded-[10px] shadow-[0_1px_2px_rgba(15,23,42,.06)] border border-[#e4eaf2] p-6 text-left">
|
||||
@if (_activeTab == "policy")
|
||||
{
|
||||
<div class="space-y-6">
|
||||
<div>
|
||||
<h3 class="text-base font-bold text-[#1f2a3a]">Corporate Travel Policies</h3>
|
||||
<p class="text-xs text-[#8a96a8] mt-0.5">Control grade limits, pre-approval workflows, and travel guidelines.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label class="block text-[11px] font-bold uppercase text-[#8a96a8] mb-1.5">Max Domestic Hotel Rate (Per Night - ZAR)</label>
|
||||
<input type="number" @bind="_maxHotelRateDom" class="w-full px-3 py-2 border border-[#c8d3e1] rounded-lg text-xs bg-white text-[#1f2a3a] outline-none focus:border-[#0066b3]" />
|
||||
<span class="text-[10px] text-[#8a96a8] mt-1 block">Rates exceeding this trigger manager audit warnings.</span>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-[11px] font-bold uppercase text-[#8a96a8] mb-1.5">Max International Hotel Rate (Per Night - ZAR)</label>
|
||||
<input type="number" @bind="_maxHotelRateInt" class="w-full px-3 py-2 border border-[#c8d3e1] rounded-lg text-xs bg-white text-[#1f2a3a] outline-none focus:border-[#0066b3]" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-[#e4eaf2] pt-4">
|
||||
<label class="block text-[11px] font-bold uppercase text-[#8a96a8] mb-2">Flight Cabin Allowance By Corporate Grade</label>
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-center justify-between p-2.5 bg-[#f4f7fb] rounded-lg text-xs">
|
||||
<span class="font-bold text-[#1f2a3a]">Executive (Grade 1-2)</span>
|
||||
<select @bind="_cabinExec" class="px-2.5 py-1 border border-[#c8d3e1] rounded bg-white text-xs text-[#1f2a3a] outline-none">
|
||||
<option value="First">First Class</option>
|
||||
<option value="Business">Business Class</option>
|
||||
<option value="Premium Economy">Premium Economy</option>
|
||||
<option value="Economy">Economy</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex items-center justify-between p-2.5 bg-[#f4f7fb] rounded-lg text-xs">
|
||||
<span class="font-bold text-[#1f2a3a]">Director & Senior Manager (Grade 3-4)</span>
|
||||
<select @bind="_cabinDirector" class="px-2.5 py-1 border border-[#c8d3e1] rounded bg-white text-xs text-[#1f2a3a] outline-none">
|
||||
<option value="First">First Class</option>
|
||||
<option value="Business">Business Class</option>
|
||||
<option value="Premium Economy">Premium Economy</option>
|
||||
<option value="Economy">Economy</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex items-center justify-between p-2.5 bg-[#f4f7fb] rounded-lg text-xs">
|
||||
<span class="font-bold text-[#1f2a3a]">Standard Operational Staff (Grade 5-8)</span>
|
||||
<select @bind="_cabinStaff" class="px-2.5 py-1 border border-[#c8d3e1] rounded bg-white text-xs text-[#1f2a3a] outline-none">
|
||||
<option value="First">First Class</option>
|
||||
<option value="Business">Business Class</option>
|
||||
<option value="Premium Economy">Premium Economy</option>
|
||||
<option value="Economy">Economy</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-[#e4eaf2] pt-4 space-y-3">
|
||||
<h4 class="text-xs font-bold text-[#1f2a3a] uppercase">Workflow Pre-Approvals</h4>
|
||||
<div class="flex items-center justify-between p-1">
|
||||
<div>
|
||||
<span class="block text-xs font-semibold text-[#1f2a3a]">Auto-approve compliant bookings</span>
|
||||
<span class="block text-[11px] text-[#8a96a8]">Domestic bookings within price limit bypass manual manager check.</span>
|
||||
</div>
|
||||
<input type="checkbox" @bind="_autoApproveCompliant" class="w-4 h-4 text-[#0066b3] rounded accent-[#0066b3]" />
|
||||
</div>
|
||||
<div class="flex items-center justify-between p-1">
|
||||
<div>
|
||||
<span class="block text-xs font-semibold text-[#1f2a3a]">Mandate travel reasons</span>
|
||||
<span class="block text-[11px] text-[#8a96a8]">Force travellers to write business motivations for each reservation.</span>
|
||||
</div>
|
||||
<input type="checkbox" @bind="_forceMotivations" class="w-4 h-4 text-[#0066b3] rounded accent-[#0066b3]" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else if (_activeTab == "financial")
|
||||
{
|
||||
<div class="space-y-6">
|
||||
<div>
|
||||
<h3 class="text-base font-bold text-[#1f2a3a]">Corporate Lodge Card & Financial Rules</h3>
|
||||
<p class="text-xs text-[#8a96a8] mt-0.5">Manage virtual cards, merchant limits, and global Lodge Card billing.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label class="block text-[11px] font-bold uppercase text-[#8a96a8] mb-1.5">Master Lodge Card Account Number</label>
|
||||
<input type="text" @bind="_lodgeCardNumber" class="w-full px-3 py-2 border border-[#c8d3e1] rounded-lg text-xs bg-white text-[#1f2a3a] font-mono outline-none focus:border-[#0066b3]" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-[11px] font-bold uppercase text-[#8a96a8] mb-1.5">Monthly Credit Authorization Limit (ZAR)</label>
|
||||
<input type="number" @bind="_lodgeCardLimit" class="w-full px-3 py-2 border border-[#c8d3e1] rounded-lg text-xs bg-white text-[#1f2a3a] font-mono outline-none focus:border-[#0066b3]" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-[#e4eaf2] pt-4">
|
||||
<label class="block text-[11px] font-bold uppercase text-[#8a96a8] mb-2">Merchant Category Code (MCC) Restrictions</label>
|
||||
<p class="text-[11px] text-[#8a96a8] mb-3">Check categories the Lodge Card and single-use Virtual Cards are authorized to clear.</p>
|
||||
<div class="grid grid-cols-2 gap-2.5">
|
||||
<label class="flex items-center gap-2 text-xs text-[#1f2a3a]">
|
||||
<input type="checkbox" @bind="_mccAirlines" class="w-4 h-4 text-[#0066b3] rounded accent-[#0066b3]" />
|
||||
MCC 4511: Airlines / Flights
|
||||
</label>
|
||||
<label class="flex items-center gap-2 text-xs text-[#1f2a3a]">
|
||||
<input type="checkbox" @bind="_mccHotels" class="w-4 h-4 text-[#0066b3] rounded accent-[#0066b3]" />
|
||||
MCC 7011: Hotels & Motels
|
||||
</label>
|
||||
<label class="flex items-center gap-2 text-xs text-[#1f2a3a]">
|
||||
<input type="checkbox" @bind="_mccCarRental" class="w-4 h-4 text-[#0066b3] rounded accent-[#0066b3]" />
|
||||
MCC 7512: Automobile Rentals
|
||||
</label>
|
||||
<label class="flex items-center gap-2 text-xs text-[#1f2a3a]">
|
||||
<input type="checkbox" @bind="_mccRailroads" class="w-4 h-4 text-[#0066b3] rounded accent-[#0066b3]" />
|
||||
MCC 4112: Passenger Railways
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-[#e4eaf2] pt-4">
|
||||
<label class="block text-[11px] font-bold uppercase text-[#8a96a8] mb-1.5">Automatic Audit Trigger Amount (ZAR)</label>
|
||||
<input type="number" @bind="_auditTriggerAmount" class="w-full px-3 py-2 border border-[#c8d3e1] rounded-lg text-xs bg-white text-[#1f2a3a] outline-none focus:border-[#0066b3]" />
|
||||
<p class="text-[10px] text-[#8a96a8] mt-1">Any single travel service booking exceeding this triggers a strict secondary audit trail.</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else if (_activeTab == "gds")
|
||||
{
|
||||
<div class="space-y-6">
|
||||
<div>
|
||||
<h3 class="text-base font-bold text-[#1f2a3a]">GDS Sync Network & API Configuration</h3>
|
||||
<p class="text-xs text-[#8a96a8] mt-0.5">Control connections to Sabre, Amadeus, Travelport, and internal databases.</p>
|
||||
</div>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label class="block text-[11px] font-bold uppercase text-[#8a96a8] mb-1.5">Primary GDS Partner Feed</label>
|
||||
<select @bind="_primaryGds" class="w-full px-3 py-2 border border-[#c8d3e1] rounded-lg text-xs bg-white text-[#1f2a3a] outline-none focus:border-[#0066b3]">
|
||||
<option value="Sabre">Sabre Global Distribution System</option>
|
||||
<option value="Amadeus">Amadeus Altea Web Services</option>
|
||||
<option value="Travelport">Travelport Galileo API</option>
|
||||
<option value="Custom">Custom Enterprise Middleware</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label class="block text-[11px] font-bold uppercase text-[#8a96a8] mb-1.5">Sabre Client ID / Key</label>
|
||||
<input type="password" @bind="_gdsClientId" class="w-full px-3 py-2 border border-[#c8d3e1] rounded-lg text-xs bg-white text-[#1f2a3a] outline-none focus:border-[#0066b3]" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-[11px] font-bold uppercase text-[#8a96a8] mb-1.5">Sync Interval (Minutes)</label>
|
||||
<input type="number" @bind="_syncInterval" class="w-full px-3 py-2 border border-[#c8d3e1] rounded-lg text-xs bg-white text-[#1f2a3a] outline-none focus:border-[#0066b3]" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-4 bg-[#e2eefb] text-[#0066b3] border border-blue-100 rounded-lg text-xs space-y-1.5">
|
||||
<h4 class="font-bold flex items-center gap-1">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M13 10V3L4 14h7v7l9-11h-7z" /></svg>
|
||||
Enterprise NDC Optimization Active
|
||||
</h4>
|
||||
<p class="leading-relaxed">New Distribution Capability (NDC) routes are prioritized to grab negotiated private corporate fares directly bypassing standard GDS markup.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else if (_activeTab == "safety")
|
||||
{
|
||||
<div class="space-y-6">
|
||||
<div>
|
||||
<h3 class="text-base font-bold text-[#1f2a3a]">Duty of Care & Crisis Response Settings</h3>
|
||||
<p class="text-xs text-[#8a96a8] mt-0.5">Control GPS tracking rules, automatic alert response and emergency contacts.</p>
|
||||
</div>
|
||||
|
||||
<div class="space-y-4 text-xs">
|
||||
<div class="flex items-center justify-between p-1">
|
||||
<div>
|
||||
<span class="block text-xs font-semibold text-[#1f2a3a]">Real-time mobile tracking</span>
|
||||
<span class="block text-[11px] text-[#8a96a8]">Ping location coordinates from traveller devices during international transits.</span>
|
||||
</div>
|
||||
<input type="checkbox" @bind="_enableGpsTracking" class="w-4 h-4 text-[#0066b3] rounded accent-[#0066b3]" />
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between p-1">
|
||||
<div>
|
||||
<span class="block text-xs font-semibold text-[#1f2a3a]">Automatic SOS consultant dispatch</span>
|
||||
<span class="block text-[11px] text-[#8a96a8]">Instantly dial and loop in standby crisis response agencies on SOS beacon trigger.</span>
|
||||
</div>
|
||||
<input type="checkbox" @bind="_enableConsultantSosDispatch" class="w-4 h-4 text-[#0066b3] rounded accent-[#0066b3]" />
|
||||
</div>
|
||||
|
||||
<div class="border-t border-[#e4eaf2] pt-4">
|
||||
<label class="block text-[11px] font-bold uppercase text-[#8a96a8] mb-1.5">Primary Emergency Crisis Center Number</label>
|
||||
<input type="text" @bind="_emergencyPhone" class="w-full px-3 py-2 border border-[#c8d3e1] rounded-lg text-xs bg-white text-[#1f2a3a] font-mono outline-none focus:border-[#0066b3]" />
|
||||
</div>
|
||||
|
||||
<div class="border-t border-[#e4eaf2] pt-4">
|
||||
<label class="block text-[11px] font-bold uppercase text-[#8a96a8] mb-1.5">Global Evacuation Partner Agency</label>
|
||||
<select @bind="_evacuationPartner" class="w-full px-3 py-2 border border-[#c8d3e1] rounded-lg bg-white text-[#1f2a3a] outline-none focus:border-[#0066b3]">
|
||||
<option value="International SOS">International SOS Control Center</option>
|
||||
<option value="Crisis24">Crisis24 Global Security Services</option>
|
||||
<option value="Medex">Medex International Evacuation</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Right Column: Settings Summary Dashboard -->
|
||||
<div class="space-y-6">
|
||||
<div class="bg-white rounded-[10px] shadow-[0_1px_2px_rgba(15,23,42,.06)] border border-[#e4eaf2] p-5 text-left">
|
||||
<h3 class="text-[15px] font-bold text-[#1f2a3a] mb-3">Suite Policy Audit</h3>
|
||||
<p class="text-xs text-[#5a6577] mb-4">A high-level summary of active rules and financial checks running on this deployment.</p>
|
||||
|
||||
<div class="space-y-3.5">
|
||||
<div class="p-3 bg-[#fafcfe] border border-[#e4eaf2] rounded-lg flex justify-between items-center text-xs">
|
||||
<div>
|
||||
<span class="block font-bold text-[#1f2a3a]">Hotel Rate Caps</span>
|
||||
<span class="text-[11px] text-[#8a96a8]">R @_maxHotelRateDom/night dom · R @_maxHotelRateInt/night int</span>
|
||||
</div>
|
||||
<span class="bg-[#e2eefb] text-[#0066b3] px-2 py-0.5 rounded text-[10px] font-bold">Active</span>
|
||||
</div>
|
||||
|
||||
<div class="p-3 bg-[#fafcfe] border border-[#e4eaf2] rounded-lg flex justify-between items-center text-xs">
|
||||
<div>
|
||||
<span class="block font-bold text-[#1f2a3a]">Approved Air Cabins</span>
|
||||
<span class="text-[11px] text-[#8a96a8]">Exec: @_cabinExec · Staff: @_cabinStaff</span>
|
||||
</div>
|
||||
<span class="bg-[#e3f6ed] text-[#22a06b] px-2 py-0.5 rounded text-[10px] font-bold">Active</span>
|
||||
</div>
|
||||
|
||||
<div class="p-3 bg-[#fafcfe] border border-[#e4eaf2] rounded-lg flex justify-between items-center text-xs">
|
||||
<div>
|
||||
<span class="block font-bold text-[#1f2a3a]">Lodge Card Limit</span>
|
||||
<span class="text-[11px] text-[#8a96a8]">R @_lodgeCardLimit.ToString("N0") monthly</span>
|
||||
</div>
|
||||
<span class="bg-[#e3f6ed] text-[#22a06b] px-2 py-0.5 rounded text-[10px] font-bold">Active</span>
|
||||
</div>
|
||||
|
||||
<div class="p-3 bg-[#fafcfe] border border-[#e4eaf2] rounded-lg flex justify-between items-center text-xs">
|
||||
<div>
|
||||
<span class="block font-bold text-[#1f2a3a]">Pre-Approvals</span>
|
||||
<span class="text-[11px] text-[#8a96a8]">@(_autoApproveCompliant ? "Bypass manual checks" : "All bookings manual")</span>
|
||||
</div>
|
||||
<span class="bg-[#fff4dd] text-[#b06b00] px-2 py-0.5 rounded text-[10px] font-bold">Configured</span>
|
||||
</div>
|
||||
|
||||
<div class="p-3 bg-[#fafcfe] border border-[#e4eaf2] rounded-lg flex justify-between items-center text-xs">
|
||||
<div>
|
||||
<span class="block font-bold text-[#1f2a3a]">Duty of Care Partner</span>
|
||||
<span class="text-[11px] text-[#8a96a8]">@_evacuationPartner</span>
|
||||
</div>
|
||||
<span class="bg-indigo-50 text-indigo-700 px-2 py-0.5 rounded text-[10px] font-bold">Linked</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private string _activeTab = "policy";
|
||||
private string _alertFeedback = string.Empty;
|
||||
|
||||
// Travel Policy bindings
|
||||
private int _maxHotelRateDom = 2500;
|
||||
private int _maxHotelRateInt = 5500;
|
||||
private string _cabinExec = "Business";
|
||||
private string _cabinDirector = "Premium Economy";
|
||||
private string _cabinStaff = "Economy";
|
||||
private bool _autoApproveCompliant = true;
|
||||
private bool _forceMotivations = false;
|
||||
|
||||
// Financial bindings
|
||||
private string _lodgeCardNumber = "4002 8332 9110 5410";
|
||||
private double _lodgeCardLimit = 1500000;
|
||||
private bool _mccAirlines = true;
|
||||
private bool _mccHotels = true;
|
||||
private bool _mccCarRental = true;
|
||||
private bool _mccRailroads = false;
|
||||
private int _auditTriggerAmount = 25000;
|
||||
|
||||
// GDS bindings
|
||||
private string _primaryGds = "Sabre";
|
||||
private string _gdsClientId = "SABRE-ENT-99238-PROD";
|
||||
private int _syncInterval = 15;
|
||||
|
||||
// Safety bindings
|
||||
private bool _enableGpsTracking = true;
|
||||
private bool _enableConsultantSosDispatch = true;
|
||||
private string _emergencyPhone = "+27 11 911 2000";
|
||||
private string _evacuationPartner = "International SOS";
|
||||
|
||||
private void SaveAllSettings()
|
||||
{
|
||||
_alertFeedback = "Corporate travel configurations successfully updated! Global GDS policies re-audited and synced across all enterprise endpoints.";
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user