update design

This commit is contained in:
Fran Jurmanović
2025-05-22 21:38:31 +02:00
parent 909c698816
commit 12a9e55f5a
12 changed files with 1278 additions and 1313 deletions

View File

@@ -18,187 +18,172 @@
formLoading = false;
};
}}
class="space-y-6 max-w-3xl"
>
<input type="hidden" name="id" value={id} />
<input type="hidden" name="file" value={configFile.assistRules} />
<div class="sm:mx-auto sm:w-full sm:max-w-7xl">
<div class="border-b border-gray-900/10 pb-12">
<h2 class="text-base/7 font-semibold text-gray-900">Assist Rules</h2>
<div class="mt-10 grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
<!-- Stability Control Level Max -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Stability Control Level Max:
<div class="mt-2">
<div class="input-block">
<input
bind:value={editedConfig.stabilityControlLevelMax}
disabled={formLoading}
name="stabilityControlLevelMax"
type="number"
class="form form-input"
/>
</div>
</div>
</label>
</div>
<!-- Disable Autosteer -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Disable Autosteer:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.disableAutosteer}
disabled={formLoading}
name="disableAutosteer"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</div>
</label>
</div>
<!-- Disable Auto Lights -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Disable Auto Lights:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.disableAutoLights}
disabled={formLoading}
name="disableAutoLights"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</div>
</label>
</div>
<!-- Disable Auto Wiper -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Disable Auto Wiper:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.disableAutoWiper}
disabled={formLoading}
name="disableAutoWiper"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</div>
</label>
</div>
<!-- Disable Auto Engine Start -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Disable Auto Engine Start:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.disableAutoEngineStart}
disabled={formLoading}
name="disableAutoEngineStart"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</div>
</label>
</div>
<!-- Disable Auto Pit Limiter -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Disable Auto Pit Limiter:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.disableAutoPitLimiter}
disabled={formLoading}
name="disableAutoPitLimiter"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</div>
</label>
</div>
<!-- Disable Auto Gear -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Disable Auto Gear:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.disableAutoGear}
disabled={formLoading}
name="disableAutoGear"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</div>
</label>
</div>
<!-- Disable Auto Clutch -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Disable Auto Clutch:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.disableAutoClutch}
disabled={formLoading}
name="disableAutoClutch"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</div>
</label>
</div>
<!-- Disable Ideal Line -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Disable Ideal Line:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.disableIdealLine}
disabled={formLoading}
name="disableIdealLine"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</div>
</label>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Stability Control Level Max -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Stability Control Level Max:
<input
bind:value={editedConfig.stabilityControlLevelMax}
disabled={formLoading}
name="stabilityControlLevelMax"
type="number"
class="form form-input"
/>
</label>
</div>
<div class="mt-6 flex items-center justify-end gap-x-6">
<label
><span class="mx-3">Restart server</span><input
type="checkbox"
id="restart"
name="restart"
bind:checked={restart}
/></label
>
<button disabled={formLoading} type="submit" class="btn btn-blue">Save</button>
<!-- Disable Autosteer -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Disable Autosteer:
<select
bind:value={editedConfig.disableAutosteer}
disabled={formLoading}
name="disableAutosteer"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</label>
</div>
<!-- Disable Auto Lights -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Disable Auto Lights:
<select
bind:value={editedConfig.disableAutoLights}
disabled={formLoading}
name="disableAutoLights"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</label>
</div>
<!-- Disable Auto Wiper -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Disable Auto Wiper:
<select
bind:value={editedConfig.disableAutoWiper}
disabled={formLoading}
name="disableAutoWiper"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</label>
</div>
<!-- Disable Auto Engine Start -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Disable Auto Engine Start:
<select
bind:value={editedConfig.disableAutoEngineStart}
disabled={formLoading}
name="disableAutoEngineStart"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</label>
</div>
<!-- Disable Auto Pit Limiter -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Disable Auto Pit Limiter:
<select
bind:value={editedConfig.disableAutoPitLimiter}
disabled={formLoading}
name="disableAutoPitLimiter"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</label>
</div>
<!-- Disable Auto Gear -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Disable Auto Gear:
<select
bind:value={editedConfig.disableAutoGear}
disabled={formLoading}
name="disableAutoGear"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</label>
</div>
<!-- Disable Auto Clutch -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Disable Auto Clutch:
<select
bind:value={editedConfig.disableAutoClutch}
disabled={formLoading}
name="disableAutoClutch"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</label>
</div>
<!-- Disable Ideal Line -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Disable Ideal Line:
<select
bind:value={editedConfig.disableIdealLine}
disabled={formLoading}
name="disableIdealLine"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</label>
</div>
</div>
<div class="pt-4 border-t border-gray-700">
<label class="flex items-center">
<input
type="checkbox"
bind:checked={restart}
class="h-4 w-4 text-green-600 focus:ring-green-500 border-gray-600 rounded bg-gray-700"
/>
<span class="ml-2 text-sm text-gray-300">Restart server after saving</span>
</label>
</div>
<div class="flex justify-end">
<button
type="submit"
disabled={formLoading}
class="px-4 py-2 bg-green-600 hover:bg-green-700 rounded-md text-sm font-medium"
>
Save Changes
</button>
</div>
</form>

View File

@@ -18,107 +18,96 @@
formLoading = false;
};
}}
class="space-y-6 max-w-3xl"
>
<input type="hidden" name="id" value={id} />
<input type="hidden" name="file" value={configFile.configuration} />
<div class="sm:mx-auto sm:w-full sm:max-w-7xl">
<div class="border-b border-gray-900/10 pb-12">
<h2 class="text-base/7 font-semibold text-gray-900">Configuration</h2>
<div class="mt-10 grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
<div class="sm:col-span-2">
<label class="block text-sm/6 font-medium text-gray-900">
UDP Port:
<div class="mt-2">
<div class="input-block">
<input
disabled={formLoading}
name="udpPort"
type="number"
class="form form-input"
bind:value={editedConfig.udpPort}
/>
</div>
</div></label
>
</div>
<div class="sm:col-span-2">
<label class="block text-sm/6 font-medium text-gray-900">
TCP Port:
<div class="mt-2">
<div class="input-block">
<input
disabled={formLoading}
name="tcpPort"
type="number"
class="form form-input"
bind:value={editedConfig.tcpPort}
/>
</div>
</div></label
>
</div>
<div class="sm:col-span-2">
<label class="block text-sm/6 font-medium text-gray-900">
Max Connections:
<div class="mt-2">
<div class="input-block">
<input
disabled={formLoading}
name="maxConnections"
type="number"
class="form form-input"
bind:value={editedConfig.maxConnections}
/>
</div>
</div></label
>
</div>
<div class="sm:col-span-2">
<label class="block text-sm/6 font-medium text-gray-900">
Lan Discovery:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.lanDiscovery}
disabled={formLoading}
name="lanDiscovery"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</div>
</label>
</div>
<div class="sm:col-span-2">
<label class="block text-sm/6 font-medium text-gray-900">
Register To Lobby:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.registerToLobby}
disabled={formLoading}
name="registerToLobby"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</div>
</label>
</div>
<input type="hidden" name="configVersion" value={1} />
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
UDP Port:
<input
disabled={formLoading}
name="udpPort"
type="number"
class="form form-input"
bind:value={editedConfig.udpPort}
/>
</label>
</div>
<div class="mt-6 flex items-center justify-end gap-x-6">
<label
><span class="mx-3">Restart server</span><input
type="checkbox"
id="restart"
name="restart"
bind:checked={restart}
/></label
>
<button disabled={formLoading} type="submit" class="btn btn-blue">Save</button>
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
TCP Port:
<input
disabled={formLoading}
name="tcpPort"
type="number"
class="form form-input"
bind:value={editedConfig.tcpPort}
/>
</label>
</div>
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Max Connections:
<input
disabled={formLoading}
name="maxConnections"
type="number"
class="form form-input"
bind:value={editedConfig.maxConnections}
/>
</label>
</div>
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Lan Discovery:
<select
bind:value={editedConfig.lanDiscovery}
disabled={formLoading}
name="lanDiscovery"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</label>
</div>
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Register To Lobby:
<select
bind:value={editedConfig.registerToLobby}
disabled={formLoading}
name="registerToLobby"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</label>
</div>
<input type="hidden" name="configVersion" value={1} />
</div>
<div class="pt-4 border-t border-gray-700">
<label class="flex items-center">
<input
type="checkbox"
bind:checked={restart}
class="h-4 w-4 text-green-600 focus:ring-green-500 border-gray-600 rounded bg-gray-700"
/>
<span class="ml-2 text-sm text-gray-300">Restart server after saving</span>
</label>
</div>
<div class="flex justify-end">
<button
type="submit"
disabled={formLoading}
class="px-4 py-2 bg-green-600 hover:bg-green-700 rounded-md text-sm font-medium"
>
Save Changes
</button>
</div>
</form>

View File

@@ -20,331 +20,285 @@
formLoading = false;
};
}}
class="space-y-6 max-w-3xl"
>
<input type="hidden" name="id" value={id} />
<input type="hidden" name="file" value={configFile.event} />
<div class="sm:mx-auto sm:w-full sm:max-w-7xl">
<div class="border-b border-gray-900/10 pb-12">
<h2 class="text-base/7 font-semibold text-gray-900">Event</h2>
<div class="mt-10 grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Track:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.track}
disabled={formLoading}
name="track"
class="form form-select"
>
{#each tracks as track}
<option value={track.track}>{track.track}</option>
{/each}
</select>
</div>
</label>
</div>
<div class="sm:col-span-2">
<label class="block text-sm/6 font-medium text-gray-900">
Pre-Race waiting time seconds:
<div class="mt-2">
<div class="input-block">
<input
disabled={formLoading}
name="preRaceWaitingTimeSeconds"
type="number"
class="form form-input"
bind:value={editedConfig.preRaceWaitingTimeSeconds}
/>
</div>
</div></label
>
</div>
<div class="sm:col-span-2">
<label class="block text-sm/6 font-medium text-gray-900">
Session over time seconds:
<div class="mt-2">
<div class="input-block">
<input
disabled={formLoading}
name="sessionOverTimeSeconds"
type="number"
class="form form-input"
bind:value={editedConfig.sessionOverTimeSeconds}
/>
</div>
</div></label
>
</div>
<div class="sm:col-span-2">
<label class="block text-sm/6 font-medium text-gray-900">
Ambient temp:
<div class="mt-2">
<div class="input-block">
<input
disabled={formLoading}
name="ambientTemp"
type="number"
class="form form-input"
bind:value={editedConfig.ambientTemp}
/>
</div>
</div></label
>
</div>
<div class="sm:col-span-2">
<label class="block text-sm/6 font-medium text-gray-900">
Cloud level:
<div class="mt-2">
<div class="input-block">
<input
disabled={formLoading}
name="cloudLevel"
type="number"
class="form form-input"
bind:value={editedConfig.cloudLevel}
step=".01"
/>
</div>
</div></label
>
</div>
<div class="sm:col-span-2">
<label class="block text-sm/6 font-medium text-gray-900">
Rain:
<div class="mt-2">
<div class="input-block">
<input
disabled={formLoading}
name="rain"
type="number"
class="form form-input"
bind:value={editedConfig.rain}
step=".01"
/>
</div>
</div></label
>
</div>
<div class="sm:col-span-2">
<label class="block text-sm/6 font-medium text-gray-900">
Weather randomness:
<div class="mt-2">
<div class="input-block">
<input
disabled={formLoading}
name="weatherRandomness"
type="number"
class="form form-input"
bind:value={editedConfig.weatherRandomness}
/>
</div>
</div></label
>
</div>
<div class="sm:col-span-2">
<label class="block text-sm/6 font-medium text-gray-900">
Post-Qualy seconds:
<div class="mt-2">
<div class="input-block">
<input
disabled={formLoading}
name="postQualySeconds"
type="number"
class="form form-input"
bind:value={editedConfig.postQualySeconds}
/>
</div>
</div></label
>
</div>
<div class="sm:col-span-2">
<label class="block text-sm/6 font-medium text-gray-900">
Post-Race seconds:
<div class="mt-2">
<div class="input-block">
<input
disabled={formLoading}
name="postRaceSeconds"
type="number"
class="form form-input"
bind:value={editedConfig.postRaceSeconds}
/>
</div>
</div></label
>
</div>
<div class="sm:col-span-2">
<label class="block text-sm/6 font-medium text-gray-900">
Simracer weather conditions:
<div class="mt-2">
<div class="input-block">
<input
disabled={formLoading}
name="simracerWeatherConditions"
type="number"
class="form form-input"
bind:value={editedConfig.simracerWeatherConditions}
/>
</div>
</div></label
>
</div>
<div class="sm:col-span-2">
<label class="block text-sm/6 font-medium text-gray-900">
Is fixed condition qualification:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.isFixedConditionQualification}
disabled={formLoading}
name="isFixedConditionQualification"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</div>
</label>
</div>
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Sessions:
<div class="mt-2">
{#each editedConfig.sessions as session, index}
<div class="mb-4 rounded-lg border p-4">
<div class="grid grid-cols-2 gap-4">
<!-- Hour of Day -->
<div>
<label class="block text-sm font-medium text-gray-700"
>Hour of Day:
<div class="mt-2">
<div class="input-block">
<input
bind:value={session.hourOfDay}
name={`sessions[${index}].hourOfDay`}
disabled={formLoading}
type="number"
class="form form-input"
/>
</div>
</div></label
>
</div>
<!-- Day of Weekend -->
<div>
<label class="block text-sm font-medium text-gray-700"
>Day of Weekend:
<div class="mt-2">
<div class="input-block">
<input
bind:value={session.dayOfWeekend}
name={`sessions[${index}].dayOfWeekend`}
disabled={formLoading}
type="number"
class="form form-input"
/>
</div>
</div>
</label>
</div>
<!-- Time Multiplier -->
<div>
<label class="block text-sm font-medium text-gray-700"
>Time Multiplier:
<div class="mt-2">
<div class="input-block">
<input
bind:value={session.timeMultiplier}
name={`sessions[${index}].timeMultiplier`}
disabled={formLoading}
type="number"
class="form form-input"
/>
</div>
</div></label
>
</div>
<!-- Session Type -->
<div>
<label class="block text-sm font-medium text-gray-700"
>Session Type:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={session.sessionType}
name={`sessions[${index}].sessionType`}
disabled={formLoading}
class="form form-select"
>
<option value="P">Practice</option>
<option value="Q">Qualifying</option>
<option value="R">Race</option>
</select>
</div></label
>
</div>
<!-- Session Duration Minutes -->
<div>
<label class="block text-sm font-medium text-gray-700"
>Session Duration (Minutes):
<div class="mt-2">
<div class="input-block">
<input
bind:value={session.sessionDurationMinutes}
name={`sessions[${index}].sessionDurationMinutes`}
disabled={formLoading}
type="number"
class="form form-input"
/>
</div>
</div>
</label>
</div>
</div>
<button
type="button"
onclick={() => {
editedConfig.sessions = editedConfig.sessions.filter((_, i) => i !== index);
}}
class="mt-2 text-sm text-red-600 hover:text-red-800"
>
Remove Session
</button>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Track:
<select
bind:value={editedConfig.track}
disabled={formLoading}
name="track"
class="form form-select"
>
{#each tracks as track}
<option value={track.track}>{track.track}</option>
{/each}
</select>
</label>
</div>
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Pre-Race waiting time seconds:
<input
disabled={formLoading}
name="preRaceWaitingTimeSeconds"
type="number"
class="form form-input"
bind:value={editedConfig.preRaceWaitingTimeSeconds}
/>
</label>
</div>
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Session over time seconds:
<input
disabled={formLoading}
name="sessionOverTimeSeconds"
type="number"
class="form form-input"
bind:value={editedConfig.sessionOverTimeSeconds}
/>
</label>
</div>
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Ambient temp:
<input
disabled={formLoading}
name="ambientTemp"
type="number"
class="form form-input"
bind:value={editedConfig.ambientTemp}
/>
</label>
</div>
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Cloud level:
<input
disabled={formLoading}
name="cloudLevel"
type="number"
class="form form-input"
bind:value={editedConfig.cloudLevel}
step=".01"
/>
</label>
</div>
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Rain:
<input
disabled={formLoading}
name="rain"
type="number"
class="form form-input"
bind:value={editedConfig.rain}
step=".01"
/>
</label>
</div>
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Weather randomness:
<input
disabled={formLoading}
name="weatherRandomness"
type="number"
class="form form-input"
bind:value={editedConfig.weatherRandomness}
/>
</label>
</div>
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Post-Qualy seconds:
<input
disabled={formLoading}
name="postQualySeconds"
type="number"
class="form form-input"
bind:value={editedConfig.postQualySeconds}
/>
</label>
</div>
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Post-Race seconds:
<input
disabled={formLoading}
name="postRaceSeconds"
type="number"
class="form form-input"
bind:value={editedConfig.postRaceSeconds}
/>
</label>
</div>
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Simracer weather conditions:
<input
disabled={formLoading}
name="simracerWeatherConditions"
type="number"
class="form form-input"
bind:value={editedConfig.simracerWeatherConditions}
/>
</label>
</div>
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Is fixed condition qualification:
<select
bind:value={editedConfig.isFixedConditionQualification}
disabled={formLoading}
name="isFixedConditionQualification"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</label>
</div>
<div />
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Sessions:
<div class="mt-2 space-y-4">
{#each editedConfig.sessions as session, index}
<div class="mb-4 rounded-lg border border-gray-700 bg-gray-800 p-4">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<!-- Hour of Day -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1"
>Hour of Day:
<input
bind:value={session.hourOfDay}
name={`sessions[${index}].hourOfDay`}
disabled={formLoading}
type="number"
class="form form-input"
/>
</label>
</div>
{/each}
<!-- Day of Weekend -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Day of Weekend:
<input
bind:value={session.dayOfWeekend}
name={`sessions[${index}].dayOfWeekend`}
disabled={formLoading}
type="number"
class="form form-input"
/>
</label>
</div>
<!-- Time Multiplier -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Time Multiplier:
<input
bind:value={session.timeMultiplier}
name={`sessions[${index}].timeMultiplier`}
disabled={formLoading}
type="number"
class="form form-input"
/>
</label>
</div>
<!-- Session Type -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Session Type:
<select
bind:value={session.sessionType}
name={`sessions[${index}].sessionType`}
disabled={formLoading}
class="form form-select"
>
<option value="P">Practice</option>
<option value="Q">Qualifying</option>
<option value="R">Race</option>
</select>
</label>
</div>
<!-- Session Duration Minutes -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Session Duration (Minutes):
<input
bind:value={session.sessionDurationMinutes}
name={`sessions[${index}].sessionDurationMinutes`}
disabled={formLoading}
type="number"
class="form form-input"
/>
</label>
</div>
</div>
<button
type="button"
onclick={() => {
editedConfig.sessions = [
...editedConfig.sessions,
{
hourOfDay: 14,
dayOfWeekend: 1,
timeMultiplier: 1,
sessionType: 'Practice',
sessionDurationMinutes: 60
}
];
editedConfig.sessions = editedConfig.sessions.filter((_, i) => i !== index);
}}
class="btn btn-blue mt-2"
class="mt-4 px-3 py-1 bg-red-600 hover:bg-red-700 rounded-md text-xs font-medium text-white flex items-center"
>
Add Session
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
</svg>
Remove Session
</button>
</div>
</label>
{/each}
<button
type="button"
onclick={() => {
editedConfig.sessions = [
...editedConfig.sessions,
{
hourOfDay: 14,
dayOfWeekend: 1,
timeMultiplier: 1,
sessionType: 'Practice',
sessionDurationMinutes: 60
}
];
}}
class="px-4 py-2 bg-green-600 hover:bg-green-700 rounded-md text-sm font-medium text-white flex items-center"
>
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
</svg>
Add Session
</button>
</div>
</div>
</label>
</div>
<div class="mt-6 flex items-center justify-end gap-x-6">
<label
><span class="mx-3">Restart server</span><input
type="checkbox"
id="restart"
name="restart"
bind:checked={restart}
/></label
>
<button disabled={formLoading} type="submit" class="btn btn-blue">Save</button>
</div>
<div class="pt-4 border-t border-gray-700">
<label class="flex items-center">
<input
type="checkbox"
bind:checked={restart}
class="h-4 w-4 text-green-600 focus:ring-green-500 border-gray-600 rounded bg-gray-700"
/>
<span class="ml-2 text-sm text-gray-300">Restart server after saving</span>
</label>
</div>
<div class="flex justify-end">
<button
type="submit"
disabled={formLoading}
class="px-4 py-2 bg-green-600 hover:bg-green-700 rounded-md text-sm font-medium"
>
Save Changes
</button>
</div>
</form>

View File

@@ -18,223 +18,194 @@
formLoading = false;
};
}}
class="space-y-6 max-w-3xl"
>
<input type="hidden" name="id" value={id} />
<input type="hidden" name="file" value={configFile.eventRules} />
<div class="sm:mx-auto sm:w-full sm:max-w-7xl">
<div class="border-b border-gray-900/10 pb-12">
<h2 class="text-base/7 font-semibold text-gray-900">Event Rules</h2>
<div class="mt-10 grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
<!-- Qualify Standing Type -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Qualify Standing Type:
<div class="mt-2">
<div class="input-block">
<input
bind:value={editedConfig.qualifyStandingType}
disabled={formLoading}
name="qualifyStandingType"
type="number"
class="form form-input"
/>
</div>
</div>
</label>
</div>
<!-- Pit Window Length Sec -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Pit Window Length (Sec):
<div class="mt-2">
<div class="input-block">
<input
bind:value={editedConfig.pitWindowLengthSec}
disabled={formLoading}
name="pitWindowLengthSec"
type="number"
class="form form-input"
/>
</div>
</div>
</label>
</div>
<!-- Driver Stint Time Sec -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Driver Stint Time (Sec):
<div class="mt-2">
<div class="input-block">
<input
bind:value={editedConfig.driverStintTimeSec}
disabled={formLoading}
name="driverStintTimeSec"
type="number"
class="form form-input"
/>
</div>
</div>
</label>
</div>
<!-- Mandatory Pitstop Count -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Mandatory Pitstop Count:
<div class="mt-2">
<div class="input-block">
<input
bind:value={editedConfig.mandatoryPitstopCount}
disabled={formLoading}
name="mandatoryPitstopCount"
type="number"
class="form form-input"
/>
</div>
</div>
</label>
</div>
<!-- Max Total Driving Time -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Max Total Driving Time:
<div class="mt-2">
<div class="input-block">
<input
bind:value={editedConfig.maxTotalDrivingTime}
disabled={formLoading}
name="maxTotalDrivingTime"
type="number"
class="form form-input"
/>
</div>
</div>
</label>
</div>
<!-- Is Refuelling Allowed In Race -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Is Refuelling Allowed In Race:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.isRefuellingAllowedInRace}
disabled={formLoading}
name="isRefuellingAllowedInRace"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</div>
</label>
</div>
<!-- Is Refuelling Time Fixed -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Is Refuelling Time Fixed:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.isRefuellingTimeFixed}
disabled={formLoading}
name="isRefuellingTimeFixed"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</div>
</label>
</div>
<!-- Is Mandatory Pitstop Refuelling Required -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Is Mandatory Pitstop Refuelling Required:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.isMandatoryPitstopRefuellingRequired}
disabled={formLoading}
name="isMandatoryPitstopRefuellingRequired"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</div>
</label>
</div>
<!-- Is Mandatory Pitstop Tyre Change Required -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Is Mandatory Pitstop Tyre Change Required:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.isMandatoryPitstopTyreChangeRequired}
disabled={formLoading}
name="isMandatoryPitstopTyreChangeRequired"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</div>
</label>
</div>
<!-- Is Mandatory Pitstop Swap Driver Required -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Is Mandatory Pitstop Swap Driver Required:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.isMandatoryPitstopSwapDriverRequired}
disabled={formLoading}
name="isMandatoryPitstopSwapDriverRequired"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</div>
</label>
</div>
<!-- Tyre Set Count -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Tyre Set Count:
<div class="mt-2">
<div class="input-block">
<input
bind:value={editedConfig.tyreSetCount}
disabled={formLoading}
name="tyreSetCount"
type="number"
class="form form-input"
/>
</div>
</div>
</label>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Qualify Standing Type -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Qualify Standing Type:
<input
bind:value={editedConfig.qualifyStandingType}
disabled={formLoading}
name="qualifyStandingType"
type="number"
class="form form-input"
/>
</label>
</div>
<div class="mt-6 flex items-center justify-end gap-x-6">
<label
><span class="mx-3">Restart server</span><input
type="checkbox"
id="restart"
name="restart"
bind:checked={restart}
/></label
>
<button disabled={formLoading} type="submit" class="btn btn-blue">Save</button>
<!-- Pit Window Length Sec -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Pit Window Length (Sec):
<input
bind:value={editedConfig.pitWindowLengthSec}
disabled={formLoading}
name="pitWindowLengthSec"
type="number"
class="form form-input"
/>
</label>
</div>
<!-- Driver Stint Time Sec -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Driver Stint Time (Sec):
<input
bind:value={editedConfig.driverStintTimeSec}
disabled={formLoading}
name="driverStintTimeSec"
type="number"
class="form form-input"
/>
</label>
</div>
<!-- Mandatory Pitstop Count -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Mandatory Pitstop Count:
<input
bind:value={editedConfig.mandatoryPitstopCount}
disabled={formLoading}
name="mandatoryPitstopCount"
type="number"
class="form form-input"
/>
</label>
</div>
<!-- Max Total Driving Time -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Max Total Driving Time:
<input
bind:value={editedConfig.maxTotalDrivingTime}
disabled={formLoading}
name="maxTotalDrivingTime"
type="number"
class="form form-input"
/>
</label>
</div>
<!-- Is Refuelling Allowed In Race -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Is Refuelling Allowed In Race:
<select
bind:value={editedConfig.isRefuellingAllowedInRace}
disabled={formLoading}
name="isRefuellingAllowedInRace"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</label>
</div>
<!-- Is Refuelling Time Fixed -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Is Refuelling Time Fixed:
<select
bind:value={editedConfig.isRefuellingTimeFixed}
disabled={formLoading}
name="isRefuellingTimeFixed"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</label>
</div>
<!-- Is Mandatory Pitstop Refuelling Required -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Is Mandatory Pitstop Refuelling Required:
<select
bind:value={editedConfig.isMandatoryPitstopRefuellingRequired}
disabled={formLoading}
name="isMandatoryPitstopRefuellingRequired"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</label>
</div>
<!-- Is Mandatory Pitstop Tyre Change Required -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Is Mandatory Pitstop Tyre Change Required:
<select
bind:value={editedConfig.isMandatoryPitstopTyreChangeRequired}
disabled={formLoading}
name="isMandatoryPitstopTyreChangeRequired"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</label>
</div>
<!-- Is Mandatory Pitstop Swap Driver Required -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Is Mandatory Pitstop Swap Driver Required:
<select
bind:value={editedConfig.isMandatoryPitstopSwapDriverRequired}
disabled={formLoading}
name="isMandatoryPitstopSwapDriverRequired"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</label>
</div>
<!-- Tyre Set Count -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Tyre Set Count:
<input
bind:value={editedConfig.tyreSetCount}
disabled={formLoading}
name="tyreSetCount"
type="number"
class="form form-input"
/>
</label>
</div>
</div>
<div class="pt-4 border-t border-gray-700">
<label class="flex items-center">
<input
type="checkbox"
bind:checked={restart}
class="h-4 w-4 text-green-600 focus:ring-green-500 border-gray-600 rounded bg-gray-700"
/>
<span class="ml-2 text-sm text-gray-300">Restart server after saving</span>
</label>
</div>
<div class="flex justify-end">
<button
type="submit"
disabled={formLoading}
class="px-4 py-2 bg-green-600 hover:bg-green-700 rounded-md text-sm font-medium"
>
Save Changes
</button>
</div>
</form>

View File

@@ -19,335 +19,288 @@
formLoading = false;
};
}}
class="space-y-6 max-w-3xl"
>
<input type="hidden" name="id" value={id} />
<input type="hidden" name="file" value={configFile.settings} />
<div class="sm:mx-auto sm:w-full sm:max-w-7xl">
<div class="border-b border-gray-900/10 pb-12">
<h2 class="text-base/7 font-semibold text-gray-900">Settings</h2>
<div class="mt-10 grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
<!-- Server Name -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Server Name:
<div class="mt-2">
<div class="input-block">
<input
bind:value={editedConfig.serverName}
disabled={formLoading}
name="serverName"
type="text"
class="form form-input"
/>
</div>
</div>
</label>
</div>
<!-- Admin Password -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Admin Password:
<div class="mt-2">
<div class="input-block">
<input
bind:value={editedConfig.adminPassword}
disabled={formLoading}
name="adminPassword"
type="password"
class="form form-input"
/>
</div>
</div>
</label>
</div>
<!-- Car Group -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Car Group:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.carGroup}
disabled={formLoading}
name="carGroup"
class="form form-select"
>
{#each carGroups as group}
<option value={group}>{group}</option>
{/each}
</select>
</div>
</label>
</div>
<!-- Track Medals Requirement -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Track Medals Requirement:
<div class="mt-2">
<div class="input-block">
<input
bind:value={editedConfig.trackMedalsRequirement}
disabled={formLoading}
name="trackMedalsRequirement"
type="number"
class="form form-input"
/>
</div>
</div>
</label>
</div>
<!-- Safety Rating Requirement -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Safety Rating Requirement:
<div class="mt-2">
<div class="input-block">
<input
bind:value={editedConfig.safetyRatingRequirement}
disabled={formLoading}
name="safetyRatingRequirement"
type="number"
class="form form-input"
/>
</div>
</div>
</label>
</div>
<!-- Racecraft Rating Requirement -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Racecraft Rating Requirement:
<div class="mt-2">
<div class="input-block">
<input
bind:value={editedConfig.racecraftRatingRequirement}
disabled={formLoading}
name="racecraftRatingRequirement"
type="number"
class="form form-input"
/>
</div>
</div>
</label>
</div>
<!-- Password -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Password:
<div class="mt-2">
<div class="input-block">
<input
bind:value={editedConfig.password}
disabled={formLoading}
name="password"
type="password"
class="form form-input"
/>
</div>
</div>
</label>
</div>
<!-- Spectator Password -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Spectator Password:
<div class="mt-2">
<div class="input-block">
<input
bind:value={editedConfig.spectatorPassword}
disabled={formLoading}
name="spectatorPassword"
type="password"
class="form form-input"
/>
</div>
</div>
</label>
</div>
<!-- Max Car Slots -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Max Car Slots:
<div class="mt-2">
<div class="input-block">
<input
bind:value={editedConfig.maxCarSlots}
disabled={formLoading}
name="maxCarSlots"
type="number"
class="form form-input"
/>
</div>
</div>
</label>
</div>
<!-- Dump Leaderboards -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Dump Leaderboards:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.dumpLeaderboards}
disabled={formLoading}
name="dumpLeaderboards"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</div>
</label>
</div>
<!-- Is Race Locked -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Is Race Locked:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.isRaceLocked}
disabled={formLoading}
name="isRaceLocked"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</div>
</label>
</div>
<!-- Randomize Track When Empty -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Randomize Track When Empty:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.randomizeTrackWhenEmpty}
disabled={formLoading}
name="randomizeTrackWhenEmpty"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</div>
</label>
</div>
<!-- Central Entry List Path -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Central Entry List Path:
<div class="mt-2">
<div class="input-block">
<input
bind:value={editedConfig.centralEntryListPath}
disabled={formLoading}
name="centralEntryListPath"
type="text"
class="form form-input"
/>
</div>
</div>
</label>
</div>
<!-- Allow Auto DQ -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Allow Auto DQ:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.allowAutoDQ}
disabled={formLoading}
name="allowAutoDQ"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</div>
</label>
</div>
<!-- Short Formation Lap -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Short Formation Lap:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.shortFormationLap}
disabled={formLoading}
name="shortFormationLap"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</div>
</label>
</div>
<!-- Formation Lap Type -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Formation Lap Type:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.formationLapType}
disabled={formLoading}
name="formationLapType"
class="form form-select"
>
<option value={0}>Old Limiter Lap</option>
<option value={1}
>Free (replaces /manual start), only usable for private servers</option
>
<option value={3}>Default formation lap with position control and UI</option>
</select>
</div>
</label>
</div>
<!-- Ignore Premature Disconnects -->
<div class="sm:col-span-6">
<label class="block text-sm/6 font-medium text-gray-900">
Ignore Premature Disconnects:
<div class="mt-2 grid grid-cols-1">
<select
bind:value={editedConfig.ignorePrematureDisconnects}
disabled={formLoading}
name="ignorePrematureDisconnects"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</div>
</label>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Server Name -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Server Name:
<input
bind:value={editedConfig.serverName}
disabled={formLoading}
name="serverName"
type="text"
class="form form-input"
/>
</label>
</div>
<div class="mt-6 flex items-center justify-end gap-x-6">
<label
><span class="mx-3">Restart server</span><input
type="checkbox"
id="restart"
name="restart"
bind:checked={restart}
/></label
>
<button disabled={formLoading} type="submit" class="btn btn-blue">Save</button>
<!-- Admin Password -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Admin Password:
<input
bind:value={editedConfig.adminPassword}
disabled={formLoading}
name="adminPassword"
type="password"
class="form form-input"
/>
</label>
</div>
<!-- Car Group -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Car Group:
<select
bind:value={editedConfig.carGroup}
disabled={formLoading}
name="carGroup"
class="form form-select"
>
{#each carGroups as group}
<option value={group}>{group}</option>
{/each}
</select>
</label>
</div>
<!-- Track Medals Requirement -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Track Medals Requirement:
<input
bind:value={editedConfig.trackMedalsRequirement}
disabled={formLoading}
name="trackMedalsRequirement"
type="number"
class="form form-input"
/>
</label>
</div>
<!-- Safety Rating Requirement -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Safety Rating Requirement:
<input
bind:value={editedConfig.safetyRatingRequirement}
disabled={formLoading}
name="safetyRatingRequirement"
type="number"
class="form form-input"
/>
</label>
</div>
<!-- Racecraft Rating Requirement -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Racecraft Rating Requirement:
<input
bind:value={editedConfig.racecraftRatingRequirement}
disabled={formLoading}
name="racecraftRatingRequirement"
type="number"
class="form form-input"
/>
</label>
</div>
<!-- Password -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Password:
<input
bind:value={editedConfig.password}
disabled={formLoading}
name="password"
type="password"
class="form form-input"
/>
</label>
</div>
<!-- Spectator Password -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Spectator Password:
<input
bind:value={editedConfig.spectatorPassword}
disabled={formLoading}
name="spectatorPassword"
type="password"
class="form form-input"
/>
</label>
</div>
<!-- Max Car Slots -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Max Car Slots:
<input
bind:value={editedConfig.maxCarSlots}
disabled={formLoading}
name="maxCarSlots"
type="number"
class="form form-input"
/>
</label>
</div>
<!-- Dump Leaderboards -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Dump Leaderboards:
<select
bind:value={editedConfig.dumpLeaderboards}
disabled={formLoading}
name="dumpLeaderboards"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</label>
</div>
<!-- Is Race Locked -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Is Race Locked:
<select
bind:value={editedConfig.isRaceLocked}
disabled={formLoading}
name="isRaceLocked"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</label>
</div>
<!-- Randomize Track When Empty -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Randomize Track When Empty:
<select
bind:value={editedConfig.randomizeTrackWhenEmpty}
disabled={formLoading}
name="randomizeTrackWhenEmpty"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</label>
</div>
<!-- Central Entry List Path -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Central Entry List Path:
<input
bind:value={editedConfig.centralEntryListPath}
disabled={formLoading}
name="centralEntryListPath"
type="text"
class="form form-input"
/>
</label>
</div>
<!-- Allow Auto DQ -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Allow Auto DQ:
<select
bind:value={editedConfig.allowAutoDQ}
disabled={formLoading}
name="allowAutoDQ"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</label>
</div>
<!-- Short Formation Lap -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Short Formation Lap:
<select
bind:value={editedConfig.shortFormationLap}
disabled={formLoading}
name="shortFormationLap"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</label>
</div>
<!-- Formation Lap Type -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Formation Lap Type:
<select
bind:value={editedConfig.formationLapType}
disabled={formLoading}
name="formationLapType"
class="form form-select"
>
<option value={0}>Old Limiter Lap</option>
<option value={1}
>Free (replaces /manual start), only usable for private servers</option
>
<option value={3}>Default formation lap with position control and UI</option>
</select>
</label>
</div>
<!-- Ignore Premature Disconnects -->
<div>
<label class="block text-sm font-medium text-gray-300 mb-1">
Ignore Premature Disconnects:
<select
bind:value={editedConfig.ignorePrematureDisconnects}
disabled={formLoading}
name="ignorePrematureDisconnects"
class="form form-select"
>
<option value={0}>No</option>
<option value={1}>Yes</option>
</select>
</label>
</div>
</div>
<div class="pt-4 border-t border-gray-700">
<label class="flex items-center">
<input
type="checkbox"
bind:checked={restart}
class="h-4 w-4 text-green-600 focus:ring-green-500 border-gray-600 rounded bg-gray-700"
/>
<span class="ml-2 text-sm text-gray-300">Restart server after saving</span>
</label>
</div>
<div class="flex justify-end">
<button
type="submit"
disabled={formLoading}
class="px-4 py-2 bg-green-600 hover:bg-green-700 rounded-md text-sm font-medium"
>
Save Changes
</button>
</div>
</form>

View File

@@ -2,40 +2,86 @@
import type { Server } from '$models/server';
let { server }: { server: Server } = $props();
function getStatusColor(status: string) {
switch (status) {
case 'SERVICE_RUNNING\r\n': return 'bg-green-500';
case 'SERVICE_STOPPED\r\n': return 'bg-red-500';
case 'SERVICE_RESTARTING\r\n': return 'bg-yellow-500';
default: return 'bg-gray-500';
}
}
</script>
<a
href={`dashboard/server/${server.id}`}
class="w-full max-w-sm rounded-lg border border-gray-200 bg-white shadow-sm dark:border-gray-700 dark:bg-gray-800"
>
<div class="flex flex-col items-center pb-4">
<h2 class="mb-1 text-xl font-medium text-gray-900 dark:text-white">{server.name}</h2>
<p class="text-sm text-gray-500 dark:text-gray-400">Status: {server.status}</p>
<div class="mt-12 flex">
<form method="POST" action="?/start">
<input type="hidden" name="id" value={server.id} />
<button
class="btn btn-blue"
disabled={server.status.startsWith('SERVICE_RUNNING')}
onclick={(e) => e.stopPropagation()}
type="submit">Start</button
>
<button
class="btn btn-blue"
disabled={server.status.startsWith('SERVICE_STOPPED')}
onclick={(e) => e.stopPropagation()}
formaction="?/stop">Stop</button
>
<button
class="btn btn-blue"
disabled={server.status.startsWith('SERVICE_STOPPED')}
onclick={(e) => e.stopPropagation()}
formaction="?/restart">Restart</button
>
</form>
<div class="bg-gray-800 rounded-lg shadow-lg overflow-hidden border border-gray-700">
<a
href={`dashboard/server/${server.id}`}
>
<div class="p-4">
<div class="flex justify-between items-start">
<div>
<h3 class="text-lg font-medium">{server.name}</h3>
<div class="flex items-center mt-1">
<span class={`inline-block w-2 h-2 rounded-full ${getStatusColor(server.status)} mr-2`}></span>
<span class="text-sm capitalize">{server.status}</span>
</div>
</div>
<button
class="text-gray-400 hover:text-white"
>
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM11.379 5.793L3 14.172V17h2.828l8.38-8.379-2.83-2.828z" />
</svg>
</button>
</div>
<div class="mt-4 grid grid-cols-2 gap-2 text-sm text-gray-300">
<div>
<span class="text-gray-500">Track:</span> {server.track}
</div>
<div>
<span class="text-gray-500">Class:</span> {server.carClass}
</div>
<div>
<span class="text-gray-500">Players:</span> {server.players}
</div>
<div>
<span class="text-gray-500">Uptime:</span> {server.uptime}
</div>
</div>
</div>
</div>
</a>
</a>
<form method="POST" action="?/start">
<div class="bg-gray-900 px-4 py-3 flex justify-between">
<input type="hidden" name="id" value={server.id} />
<button
type="submit"
disabled={server.status.startsWith('SERVICE_RUNNING')}
onclick={(e) => e.stopPropagation()}
class="px-3 py-1 bg-green-600 hover:bg-green-700 rounded-md text-xs font-medium disabled:opacity-50 disabled:cursor-not-allowed"
>
Start
</button>
<button
disabled={server.status.startsWith('SERVICE_STOPPED')}
onclick={(e) => e.stopPropagation()}
class="px-3 py-1 bg-yellow-600 hover:bg-yellow-700 rounded-md text-xs font-medium disabled:opacity-50 disabled:cursor-not-allowed"
formaction="?/restart"
>
Restart
</button>
<button
disabled={server.status.startsWith('SERVICE_STOPPED')}
onclick={(e) => e.stopPropagation()}
class="px-3 py-1 bg-red-600 hover:bg-red-700 rounded-md text-xs font-medium disabled:opacity-50 disabled:cursor-not-allowed"
formaction="?/stop"
>
Stop
</button>
</div>
</form>
</div>
<style>
</style>

View File

@@ -1,28 +0,0 @@
<script lang="ts">
</script>
<aside class="fixed top-0 left-0 z-40 h-screen w-64">
<div class="h-full overflow-y-auto bg-gray-50 px-3 py-4 dark:bg-gray-800">
<ul class="space-y-2 font-medium">
<li>
<a
href="/dashboard"
class="group flex items-center rounded-lg p-2 text-gray-900 hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700"
>
<span class="ms-3">Dashboard</span>
</a>
</li>
<li>
<a
href="/logout"
class="group flex items-center rounded-lg p-2 text-gray-900 hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700"
>
<span class="ms-3">Logout</span>
</a>
</li>
</ul>
</div>
</aside>
<style>
</style>

View File

@@ -1,14 +0,0 @@
<script>
import Sidebar from '$components/Sidebar.svelte';
import '../../app.css';
let { children } = $props();
</script>
<div class="layout">
<Sidebar />
<div class="p-4 sm:ml-64">
{@render children()}
</div>
</div>
<style></style>

View File

@@ -6,10 +6,41 @@
let servers: Server[] = data.servers;
</script>
<div class="server-grid">
<div class="min-h-screen bg-gray-900 text-white">
<header class="bg-gray-800 shadow-md">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4 flex justify-between items-center">
<h1 class="text-2xl font-bold">ACC Server Manager</h1>
<div class="flex items-center space-x-4">
<a href="/logout">
<button
class="text-gray-300 hover:text-white flex items-center"
>
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" />
</svg>
<span class="ml-1 hidden sm:inline">Logout</span>
</button>
</a>
</div>
</div>
</header>
<main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div class="flex justify-between items-center mb-6">
<h2 class="text-xl font-semibold">Your Servers</h2>
<div class="flex space-x-2">
<a href="/dashboard" class="px-3 py-1 bg-gray-700 hover:bg-gray-600 rounded-md text-sm">
Refresh
</a>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{#each servers as server}
<ServerCard {server} />
{/each}
</div>
</main>
</div>
<svelte:head>

View File

@@ -12,72 +12,144 @@
const id = data.id;
const server = data.server;
let tab = $state(configFile.event);
function getStatusColor(status: string) {
console.log({status})
switch (status) {
case 'SERVICE_RUNNING\r\n': return 'bg-green-500';
case 'SERVICE_STOPPED\r\n': return 'bg-red-500';
case 'SERVICE_RESTARTING\r\n': return 'bg-yellow-500';
default: return 'bg-gray-500';
}
}
</script>
<svelte:head>
<title>{server.name}</title>
</svelte:head>
<aside class="fixed top-0 left-64 z-40 h-screen w-48">
<div class="h-full overflow-y-auto bg-gray-50 px-1 py-4 dark:bg-gray-700">
<div class="flex items-center justify-center">
<h2 class="bold mb-5 text-gray-300">{server.name}</h2>
<div class="min-h-screen bg-gray-900 text-white flex">
<!-- Sidebar -->
<aside class="w-64 bg-gray-800 border-r border-gray-700 flex-shrink-0">
<!-- Update the sidebar header to make the server name clickable -->
<div class="p-4 border-b border-gray-700">
<a href="/dashboard" class="hover:text-green-400 transition-colors">
<h2 class="text-lg font-semibold truncate">{server.name}</h2>
</a>
<div class="flex items-center mt-1">
<span class={`inline-block w-2 h-2 rounded-full ${getStatusColor(server.status)} mr-2`}></span>
<span class="text-sm capitalize">{server.status}</span>
</div>
</div>
<nav class="p-2">
<ul class="space-y-1">
<li>
<button
class={`w-full text-left px-3 py-2 rounded-md ${tab === configFile.event ? 'bg-green-600 text-white' : 'text-gray-300 hover:bg-gray-700'}`}
disabled={tab === configFile.event || !configs.event}
onclick={() => (tab = configFile.event)}
>
Event
</button>
</li>
<li>
<button
class={`w-full text-left px-3 py-2 rounded-md ${tab === configFile.configuration ? 'bg-green-600 text-white' : 'text-gray-300 hover:bg-gray-700'}`}
disabled={tab === configFile.configuration || !configs.configuration}
onclick={() => (tab = configFile.configuration)}
>
Configuration
</button>
</li>
<li>
<button
class={`w-full text-left px-3 py-2 rounded-md ${tab === configFile.settings ? 'bg-green-600 text-white' : 'text-gray-300 hover:bg-gray-700'}`}
disabled={tab === configFile.settings || !configs.settings}
onclick={() => (tab = configFile.settings)}
>
Settings
</button>
</li>
{#if configs.assistRules}
<li>
<button
class={`w-full text-left px-3 py-2 rounded-md ${tab === configFile.assistRules ? 'bg-green-600 text-white' : 'text-gray-300 hover:bg-gray-700'}`}
disabled={tab === configFile.assistRules || !configs.assistRules}
onclick={() => (tab = configFile.assistRules)}
>
Assist Rules
</button>
</li>
{/if}
{#if configs.eventRules}
<li>
<button
class={`w-full text-left px-3 py-2 rounded-md ${tab === configFile.eventRules ? 'bg-green-600 text-white' : 'text-gray-300 hover:bg-gray-700'}`}
disabled={tab === configFile.eventRules || !configs.eventRules}
onclick={() => (tab = configFile.eventRules)}
>
Event Rules
</button>
</li>
{/if}
</ul>
</nav>
</aside>
<main class="flex-1 overflow-auto">
<header class="bg-gray-800 shadow-md p-4 flex justify-between items-center">
<h1 class="text-xl font-semibold">
{#if tab === configFile.event}
Event
{:else if tab === configFile.configuration}
Configuration
{:else if tab === configFile.settings}
Settings
{:else if tab === configFile.assistRules}
Assist Rules
{:else if tab === configFile.eventRules}
Event Rules
{/if}
</h1>
<div class="flex space-x-3">
<a
href="/dashboard"
class="px-3 py-1.5 bg-gray-700 hover:bg-gray-600 rounded-md text-sm flex items-center"
>
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18" />
</svg>
Back to Dashboard
</a>
<a
href="/logout"
class="px-3 py-1.5 bg-red-700 hover:bg-red-800 rounded-md text-sm flex items-center"
>
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" />
</svg>
Logout
</a>
</div>
</header>
<div class="p-6">
{#if tab === configFile.event}
<EditorEvent config={configs.event} {tracks} {id} />
{:else if tab === configFile.configuration}
<EditorConfiguration config={configs.configuration} {id} />
{:else if tab === configFile.settings}
<EditorSettings config={configs.settings} {id} />
{:else if tab === configFile.assistRules}
<EditorAssistRules config={configs.assistRules} {id} />
{:else if tab === configFile.eventRules}
<EditorEventRules config={configs.eventRules} {id} />
{:else}
<div class="bg-gray-800 rounded-lg p-6 text-center">
<p class="text-gray-400">Select a section from the sidebar to edit settings</p>
</div>
<ul class="space-y-2 font-medium">
<li>
<button
class="btn btn-sidebar"
disabled={tab === configFile.event || !configs.event}
onclick={() => (tab = configFile.event)}
>
<span class="ms-3">Event</span>
</button>
<button
class="btn btn-sidebar"
disabled={tab === configFile.configuration || !configs.configuration}
onclick={() => (tab = configFile.configuration)}
>
<span class="ms-3">Configuration</span>
</button>
<button
class="btn btn-sidebar"
disabled={tab === configFile.settings || !configs.settings}
onclick={() => (tab = configFile.settings)}
>
<span class="ms-3">Settings</span>
</button>
{#if configs.assistRules}
<button
class="btn btn-sidebar"
disabled={tab === configFile.assistRules}
onclick={() => (tab = configFile.assistRules)}
>
<span class="ms-3">Assist Rules</span>
</button>
{/if}
{#if configs.eventRules}
<button
class="btn btn-sidebar"
disabled={tab === configFile.eventRules}
onclick={() => (tab = configFile.eventRules)}
>
<span class="ms-3">Event Rules</span>
</button>
{/if}
</li>
</ul>
{/if}
</div>
</aside>
<div class="sm:ml-48">
{#if tab === configFile.event}
<EditorEvent config={configs.event} {tracks} {id} />
{:else if tab === configFile.configuration}
<EditorConfiguration config={configs.configuration} {id} />
{:else if tab === configFile.settings}
<EditorSettings config={configs.settings} {id} />
{:else if tab === configFile.assistRules}
<EditorAssistRules config={configs.assistRules} {id} />
{:else if tab === configFile.eventRules}
<EditorEventRules config={configs.eventRules} {id} />
{/if}
</main>
</div>

View File

@@ -13,67 +13,73 @@
<title>ACC Server Manager - Login</title>
</svelte:head>
<div class="flex min-h-full flex-col justify-center px-6 py-12 lg:px-8">
<div class="sm:mx-auto sm:w-full sm:max-w-sm">
<h2 class="mt-10 text-center text-2xl/9 font-bold tracking-tight text-gray-900">
Sign in to your account
</h2>
</div>
{#if error}
<div class="sm:mx-auto sm:w-full sm:max-w-sm">
<p class="error">{error}</p>
<div class="min-h-screen flex items-center justify-center bg-gray-900">
<div class="w-full max-w-md p-8 space-y-8 bg-gray-800 rounded-lg shadow-lg">
<div class="text-center">
<h1 class="text-3xl font-bold text-white">ACC Server Manager</h1>
<p class="mt-2 text-gray-400">Sign in to manage your servers</p>
</div>
{/if}
<form
method="POST"
action="?/login"
use:enhance={() => {
formLoading = true;
}}
>
<div class="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
<div class="space-y-6">
<div>
<label for="text" class="block text-sm/6 font-medium text-gray-900">Username</label>
<div class="mt-2">
<input
type="text"
name="username"
id="username"
autocomplete="username"
required
class="form form-login"
bind:value={username}
disabled={formLoading}
/>
</div>
</div>
<div>
<div class="flex items-center justify-between">
<label for="password" class="block text-sm/6 font-medium text-gray-900">Password</label>
</div>
<div class="mt-2">
<input
type="password"
name="password"
id="password"
autocomplete="current-password"
required
class="form form-login"
bind:value={password}
disabled={formLoading}
/>
</div>
</div>
<div>
<button type="submit" class="btn btn-login" disabled={formLoading}>Sign in</button>
</div>
{#if error}
<div class="p-3 bg-red-900/50 border border-red-700 rounded-md text-red-200 text-sm">
{error}
</div>
{/if}
<form
method="POST"
action="?/login"
use:enhance={() => {
formLoading = true;
}}
>
<div class="space-y-4">
<div>
<label for="username" class="block text-sm font-medium text-gray-300">Username</label>
<input
type="text"
name="username"
id="username"
autocomplete="username"
required
bind:value={username}
disabled={formLoading}
class="mt-1 block w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded-md text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent"
/>
</div>
<div>
<label for="password" class="block text-sm font-medium text-gray-300">Password</label>
<input
type="password"
name="password"
id="password"
autocomplete="current-password"
required
bind:value={password}
disabled={formLoading}
class="mt-1 block w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded-md text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent"
/>
</div>
</div>
</form>
<div>
<button
type="submit"
disabled={formLoading}
class="w-full flex justify-center mt-4 py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-green-600 hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 disabled:opacity-50 disabled:cursor-not-allowed"
>
{#if formLoading}
<svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
Signing in...
{:else}
Sign in
{/if}
</button>
</div>
</form>
</div>
</div>
<style>

View File

@@ -7,11 +7,11 @@
}
.form-input {
@apply min-w-0 grow py-1.5 pr-3 pl-1 text-base text-gray-900 placeholder:text-gray-400 focus:outline-none sm:text-sm/6;
@apply w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded-md text-white focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent;
}
.form-select {
@apply col-start-1 row-start-1 w-full appearance-none rounded-md bg-white py-1.5 pr-8 pl-3 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6;
@apply w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded-md text-white focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent;
}
.form:disabled {