first commit
This commit is contained in:
@@ -0,0 +1,360 @@
|
||||
package pages
|
||||
|
||||
import (
|
||||
"tankstopp/internal/currency"
|
||||
"tankstopp/internal/models"
|
||||
"tankstopp/internal/views/components"
|
||||
)
|
||||
|
||||
templ SettingsPage(user *models.User, username string, currencies []currency.Currency, successMessage, errorMessage string) {
|
||||
@components.BaseLayout("Settings", user, username) {
|
||||
@components.PageHeader("Manage your account", "Settings")
|
||||
<div class="page-body">
|
||||
<div class="container-xl">
|
||||
if successMessage != "" {
|
||||
<div class="row mb-3">
|
||||
<div class="col-12">
|
||||
@components.Alert("success", successMessage)
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
if errorMessage != "" {
|
||||
<div class="row mb-3">
|
||||
<div class="col-12">
|
||||
@components.Alert("danger", errorMessage)
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col-12 col-lg-8">
|
||||
<!-- Profile Settings -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
@components.Card("Profile Settings", "user") {
|
||||
@components.Form("post", "/settings/profile") {
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
@components.FormGroup("Username", "Your unique username") {
|
||||
@components.Input("username", "text", "Enter username", username, true)
|
||||
}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
@components.FormGroup("Email", "Your email address") {
|
||||
@components.Input("email", "email", "Enter email", user.Email, true)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
@components.FormGroup("Base Currency", "Default currency for fuel prices") {
|
||||
@components.CurrencySelect("base_currency", user.BaseCurrency, currencies)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
@components.ButtonGroup() {
|
||||
@components.PrimaryButton("Save Profile", "save")
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<!-- Application Preferences -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
@components.Card("Application Preferences", "settings") {
|
||||
@components.Form("post", "/settings/preferences") {
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
@components.FormGroup("Distance Unit", "Unit for distance measurements") {
|
||||
@components.Select("distance_unit", false) {
|
||||
@components.Option("km", "Kilometers (km)", true)
|
||||
@components.Option("mi", "Miles (mi)", false)
|
||||
}
|
||||
}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
@components.FormGroup("Volume Unit", "Unit for fuel volume measurements") {
|
||||
@components.Select("volume_unit", false) {
|
||||
@components.Option("L", "Liters (L)", true)
|
||||
@components.Option("gal", "Gallons (gal)", false)
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
@components.FormGroup("Date Format", "How dates are displayed") {
|
||||
@components.Select("date_format", false) {
|
||||
@components.Option("DD/MM/YYYY", "DD/MM/YYYY", false)
|
||||
@components.Option("MM/DD/YYYY", "MM/DD/YYYY", false)
|
||||
@components.Option("YYYY-MM-DD", "YYYY-MM-DD", true)
|
||||
}
|
||||
}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
@components.FormGroup("Language", "Application language") {
|
||||
@components.Select("language", false) {
|
||||
@components.Option("en", "English", true)
|
||||
@components.Option("de", "Deutsch", false)
|
||||
@components.Option("fr", "Français", false)
|
||||
@components.Option("es", "Español", false)
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
@components.FormGroup("Notifications", "Email notification preferences") {
|
||||
@components.Switch("email_notifications", "Send email notifications", false)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
@components.ButtonGroup() {
|
||||
@components.PrimaryButton("Save Preferences", "save")
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<!-- Security Settings -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
@components.Card("Security Settings", "lock") {
|
||||
@components.Form("post", "/settings/password") {
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
@components.FormGroup("Current Password", "Enter your current password") {
|
||||
@components.PasswordInput("current_password", "Current password", true)
|
||||
}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
@components.FormGroup("New Password", "Choose a new password") {
|
||||
@components.PasswordInput("new_password", "New password", true)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
@components.FormGroup("Confirm New Password", "Confirm your new password") {
|
||||
@components.PasswordInput("confirm_password", "Confirm new password", true)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
@components.ButtonGroup() {
|
||||
@components.PrimaryButton("Change Password", "lock")
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<!-- Data Management -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
@components.Card("Data Management", "database") {
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h5>Export Data</h5>
|
||||
<p class="text-muted">Download your fuel stop data in various formats</p>
|
||||
@components.ButtonGroup() {
|
||||
<a href="/export/csv" class="btn btn-outline-primary">
|
||||
@components.Icon("download", 24)
|
||||
Export CSV
|
||||
</a>
|
||||
<a href="/export/json" class="btn btn-outline-primary">
|
||||
@components.Icon("download", 24)
|
||||
Export JSON
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h5>Import Data</h5>
|
||||
<p class="text-muted">Import fuel stop data from a CSV file</p>
|
||||
@components.Form("post", "/import/csv") {
|
||||
<div class="mb-3">
|
||||
<input type="file" class="form-control" name="csv_file" accept=".csv" required/>
|
||||
</div>
|
||||
@components.PrimaryButton("Import CSV", "upload")
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<hr class="my-4"/>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h5 class="text-danger">Danger Zone</h5>
|
||||
<p class="text-muted">These actions cannot be undone</p>
|
||||
@components.ButtonGroup() {
|
||||
<button type="button" class="btn btn-outline-danger" onclick="confirmClearData()">
|
||||
@components.Icon("trash", 24)
|
||||
Clear All Data
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<!-- Account Management -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
@components.Card("Account Management", "user") {
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h5 class="text-danger">Delete Account</h5>
|
||||
<p class="text-muted">
|
||||
Permanently delete your account and all associated data. This action cannot be undone.
|
||||
</p>
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<div class="d-flex">
|
||||
<div>
|
||||
@components.Icon("alert-triangle", 24)
|
||||
</div>
|
||||
<div>
|
||||
<strong>Warning:</strong> This will permanently delete your account, all vehicles, and all fuel stop records.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-danger" onclick="confirmDeleteAccount()">
|
||||
@components.Icon("trash", 24)
|
||||
Delete Account
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Sidebar with Quick Stats -->
|
||||
<div class="col-12 col-lg-4">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
@components.Card("Account Summary", "info-circle") {
|
||||
<div class="list-group list-group-flush">
|
||||
<div class="list-group-item">
|
||||
<div class="d-flex justify-content-between">
|
||||
<span>Member since</span>
|
||||
<span class="text-muted">{ user.CreatedAt.Format("Jan 2006") }</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-group-item">
|
||||
<div class="d-flex justify-content-between">
|
||||
<span>Email</span>
|
||||
<span class="text-muted">{ user.Email }</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-group-item">
|
||||
<div class="d-flex justify-content-between">
|
||||
<span>Base currency</span>
|
||||
<span class="text-muted">{ user.BaseCurrency }</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-group-item">
|
||||
<div class="d-flex justify-content-between">
|
||||
<span>Account status</span>
|
||||
<span class="text-muted">
|
||||
<span class="badge bg-success">Active</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-4">
|
||||
<div class="col-12">
|
||||
@components.Card("Quick Actions", "zap") {
|
||||
<div class="list-group list-group-flush">
|
||||
<a href="/add" class="list-group-item list-group-item-action d-flex align-items-center">
|
||||
<span class="me-2">
|
||||
@components.Icon("plus", 24)
|
||||
</span>
|
||||
Add Fuel Stop
|
||||
</a>
|
||||
<a href="/vehicles" class="list-group-item list-group-item-action d-flex align-items-center">
|
||||
<span class="me-2">
|
||||
@components.Icon("car", 24)
|
||||
</span>
|
||||
Manage Vehicles
|
||||
</a>
|
||||
<a href="/dashboard" class="list-group-item list-group-item-action d-flex align-items-center">
|
||||
<span class="me-2">
|
||||
@components.Icon("home", 24)
|
||||
</span>
|
||||
Go to Dashboard
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@SettingsScript()
|
||||
}
|
||||
}
|
||||
|
||||
script SettingsScript() {
|
||||
function confirmClearData() {
|
||||
if (confirm('Are you sure you want to clear all your data? This will delete all fuel stops and vehicles permanently.')) {
|
||||
if (confirm('This action cannot be undone. Are you absolutely sure?')) {
|
||||
// Create a form to submit the clear data request
|
||||
const form = document.createElement('form');
|
||||
form.method = 'POST';
|
||||
form.action = '/settings/clear-data';
|
||||
document.body.appendChild(form);
|
||||
form.submit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function confirmDeleteAccount() {
|
||||
if (confirm('Are you sure you want to delete your account? This will permanently delete all your data.')) {
|
||||
if (confirm('This action cannot be undone. Type "DELETE" to confirm:')) {
|
||||
const confirmation = prompt('Please type "DELETE" to confirm account deletion:');
|
||||
if (confirmation === 'DELETE') {
|
||||
// Create a form to submit the delete account request
|
||||
const form = document.createElement('form');
|
||||
form.method = 'POST';
|
||||
form.action = '/settings/delete-account';
|
||||
document.body.appendChild(form);
|
||||
form.submit();
|
||||
} else {
|
||||
alert('Account deletion cancelled. The confirmation text did not match.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize settings page
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Initialize tooltips
|
||||
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
|
||||
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
|
||||
return new bootstrap.Tooltip(tooltipTriggerEl);
|
||||
});
|
||||
|
||||
// Handle file input styling
|
||||
const fileInputs = document.querySelectorAll('input[type="file"]');
|
||||
fileInputs.forEach(function(input) {
|
||||
input.addEventListener('change', function(e) {
|
||||
const fileName = e.target.files[0] ? e.target.files[0].name : 'No file chosen';
|
||||
const label = e.target.parentNode.querySelector('.file-label');
|
||||
if (label) {
|
||||
label.textContent = fileName;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user