dawarich/app/views/maps_v2/_settings_panel.html.erb

930 lines
34 KiB
Text
Raw Normal View History

2025-11-25 17:37:50 -05:00
<div class="map-control-panel" data-maps-v2-target="settingsPanel" data-controller="map-panel">
<!-- Vertical Icon Tabs (Left Side) -->
<div class="panel-tabs">
<button class="tab-btn active"
data-action="click->map-panel#switchTab"
data-tab="search"
data-map-panel-target="tabButton"
title="Search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tab-icon">
<circle cx="11" cy="11" r="8"></circle>
<path d="m21 21-4.35-4.35"></path>
</svg>
</button>
<button class="tab-btn"
data-action="click->map-panel#switchTab"
data-tab="layers"
data-map-panel-target="tabButton"
title="Map Layers">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tab-icon">
<polygon points="12 2 2 7 12 12 22 7 12 2"></polygon>
<polyline points="2 17 12 22 22 17"></polyline>
<polyline points="2 12 12 17 22 12"></polyline>
</svg>
</button>
<button class="tab-btn"
data-action="click->map-panel#switchTab"
data-tab="settings"
data-map-panel-target="tabButton"
title="Settings">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tab-icon">
<path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"></path>
<circle cx="12" cy="12" r="3"></circle>
</svg>
2025-11-20 16:36:58 -05:00
</button>
<button class="tab-btn"
data-action="click->map-panel#switchTab"
data-tab="tools"
data-map-panel-target="tabButton"
title="Tools">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tab-icon">
<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"></path>
</svg>
</button>
<% if !DawarichSettings.self_hosted? %>
<button class="tab-btn"
data-action="click->map-panel#switchTab"
data-tab="links"
data-map-panel-target="tabButton"
title="Links">
<%= icon 'info' %>
</button>
<% end %>
2025-11-20 16:36:58 -05:00
</div>
2025-11-25 17:37:50 -05:00
<!-- Panel Content -->
<div class="panel-content">
<!-- Panel Header -->
<div class="panel-header">
<h3 class="panel-title" data-map-panel-target="title">Search</h3>
<button class="btn btn-ghost btn-sm btn-circle"
data-action="click->maps-v2#toggleSettings"
title="Close panel">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-5 h-5">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
2025-11-20 16:36:58 -05:00
</div>
2025-11-25 17:37:50 -05:00
<!-- Panel Body -->
<div class="panel-body">
<!-- Search Tab -->
<div class="tab-content active" data-tab-content="search" data-map-panel-target="tabContent">
<div class="form-control w-full">
<label class="label">
<span class="label-text">Search for a place</span>
</label>
2025-11-26 15:07:12 -05:00
<div class="relative">
<input type="text"
placeholder="Enter name of a place"
class="input input-bordered w-full"
data-maps-v2-target="searchInput"
autocomplete="off" />
<!-- Search Results -->
<div class="absolute z-50 w-full mt-1 bg-base-100 rounded-lg shadow-lg border border-base-300 hidden max-h-96 overflow-y-auto"
data-maps-v2-target="searchResults">
<!-- Results will be populated by SearchManager -->
</div>
</div>
<p class="text-xs text-base-content/60 mt-2">
Search for a location to navigate on the map
</p>
2025-11-25 17:37:50 -05:00
</div>
</div>
2025-11-20 16:36:58 -05:00
2025-11-25 17:37:50 -05:00
<!-- Layers Tab -->
<div class="tab-content" data-tab-content="layers" data-map-panel-target="tabContent">
<div class="space-y-4">
<!-- Points Layer -->
<div class="form-control">
<label class="label cursor-pointer justify-start gap-3">
<input type="checkbox"
class="toggle toggle-primary"
2025-11-26 13:40:12 -05:00
data-maps-v2-target="pointsToggle"
data-action="change->maps-v2#togglePoints" />
2025-11-25 17:37:50 -05:00
<span class="label-text font-medium">Points</span>
</label>
<p class="text-sm text-base-content/60 ml-14">Show individual location points</p>
</div>
2025-11-20 16:36:58 -05:00
2025-11-25 17:37:50 -05:00
<div class="divider my-2"></div>
2025-11-20 16:36:58 -05:00
2025-11-25 17:37:50 -05:00
<!-- Routes Layer -->
<div class="form-control">
<label class="label cursor-pointer justify-start gap-3">
<input type="checkbox"
class="toggle toggle-primary"
2025-11-26 13:40:12 -05:00
data-maps-v2-target="routesToggle"
data-action="change->maps-v2#toggleRoutes" />
2025-11-25 17:37:50 -05:00
<span class="label-text font-medium">Routes</span>
</label>
<p class="text-sm text-base-content/60 ml-14">Show connected route lines</p>
</div>
2025-11-20 16:36:58 -05:00
2025-11-26 15:43:59 -05:00
<!-- Speed-Colored Routes Options (conditionally shown) -->
<div class="ml-14 space-y-3" data-maps-v2-target="routesOptions" style="display: none;">
<div class="form-control">
<label class="label cursor-pointer py-2">
<span class="label-text text-sm">Color by speed</span>
<input type="checkbox"
class="toggle toggle-sm toggle-primary"
data-maps-v2-target="speedColoredToggle"
data-action="change->maps-v2#toggleSpeedColoredRoutes" />
</label>
</div>
<!-- Speed Color Scale Editor (shown when speed colors enabled) -->
<div class="hidden" data-maps-v2-target="speedColorScaleContainer">
<button type="button"
class="btn btn-sm btn-outline w-full"
data-action="click->maps-v2#openSpeedColorEditor">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01" />
</svg>
Edit Color Gradient
</button>
<input type="hidden" data-maps-v2-target="speedColorScaleInput" value="" />
</div>
</div>
2025-11-25 17:37:50 -05:00
<div class="divider my-2"></div>
2025-11-20 17:46:06 -05:00
2025-11-25 17:37:50 -05:00
<!-- Heatmap Layer -->
<div class="form-control">
<label class="label cursor-pointer justify-start gap-3">
<input type="checkbox"
class="toggle toggle-primary"
2025-11-26 13:40:12 -05:00
data-maps-v2-target="heatmapToggle"
2025-11-25 17:37:50 -05:00
data-action="change->maps-v2#toggleHeatmap" />
<span class="label-text font-medium">Heatmap</span>
</label>
<p class="text-sm text-base-content/60 ml-14">Show density heatmap</p>
</div>
2025-11-20 17:46:06 -05:00
2025-11-25 17:37:50 -05:00
<div class="divider my-2"></div>
2025-11-20 18:10:08 -05:00
2025-11-25 17:37:50 -05:00
<!-- Visits Layer -->
<div class="form-control">
<label class="label cursor-pointer justify-start gap-3">
<input type="checkbox"
class="toggle toggle-primary"
2025-11-26 13:40:12 -05:00
data-maps-v2-target="visitsToggle"
2025-11-25 17:37:50 -05:00
data-action="change->maps-v2#toggleVisits" />
<span class="label-text font-medium">Visits</span>
</label>
<p class="text-sm text-base-content/60 ml-14">Show detected area visits</p>
</div>
2025-11-20 18:10:08 -05:00
2025-11-25 17:37:50 -05:00
<!-- Visits Search (conditionally shown) -->
<div class="ml-14 space-y-2" data-maps-v2-target="visitsSearch" style="display: none;">
<input type="text"
id="visits-search"
placeholder="Filter by name..."
class="input input-sm input-bordered w-full"
data-action="input->maps-v2#searchVisits" />
2025-11-21 13:46:51 -05:00
2025-11-26 13:40:12 -05:00
<select class="select select-bordered w-full"
2025-11-25 17:37:50 -05:00
data-action="change->maps-v2#filterVisits">
<option value="all">All Visits</option>
<option value="confirmed">Confirmed Only</option>
<option value="suggested">Suggested Only</option>
</select>
</div>
2025-11-20 16:36:58 -05:00
2025-11-25 17:37:50 -05:00
<div class="divider my-2"></div>
<!-- Places Layer -->
<div class="form-control">
<label class="label cursor-pointer justify-start gap-3">
<input type="checkbox"
class="toggle toggle-primary"
data-maps-v2-target="placesToggle"
data-action="change->maps-v2#togglePlaces" />
<span class="label-text font-medium">Places</span>
</label>
<p class="text-sm text-base-content/60 ml-14">Show your saved places</p>
</div>
<!-- Places Tags (conditionally shown) -->
<div class="ml-14 space-y-2" data-maps-v2-target="placesFilters" style="display: none;">
<div class="form-control">
<label class="label cursor-pointer justify-start gap-2">
<input type="checkbox"
class="toggle toggle-sm"
data-maps-v2-target="enableAllPlaceTagsToggle"
data-action="change->maps-v2#toggleAllPlaceTags">
<span class="label-text text-sm">Enable All Tags</span>
</label>
</div>
<div class="form-control">
<label class="label">
<span class="label-text text-sm">Filter by Tags</span>
</label>
<div class="flex flex-wrap gap-2">
<!-- Untagged option -->
<label class="cursor-pointer">
<input type="checkbox"
name="place_tag_ids[]"
value="untagged"
class="checkbox checkbox-xs hidden peer"
data-action="change->maps-v2#filterPlacesByTags">
<span class="badge badge-sm badge-outline transition-all peer-checked:scale-105"
style="border-color: #94a3b8; color: #94a3b8;"
data-checked-style="background-color: #94a3b8; color: white;">
🏷️ Untagged
</span>
</label>
<% current_user.tags.ordered.each do |tag| %>
<label class="cursor-pointer">
<input type="checkbox"
name="place_tag_ids[]"
value="<%= tag.id %>"
class="checkbox checkbox-xs hidden peer"
data-action="change->maps-v2#filterPlacesByTags">
<span class="badge badge-sm badge-outline transition-all peer-checked:scale-105"
style="border-color: <%= tag.color %>; color: <%= tag.color %>;"
data-checked-style="background-color: <%= tag.color %>; color: white;">
<%= tag.icon %> #<%= tag.name %>
</span>
</label>
<% end %>
</div>
<label class="label">
<span class="label-text-alt">Click tags to filter places</span>
</label>
</div>
</div>
<div class="divider my-2"></div>
2025-11-25 17:37:50 -05:00
<!-- Photos Layer -->
<div class="form-control">
<label class="label cursor-pointer justify-start gap-3">
<input type="checkbox"
class="toggle toggle-primary"
2025-11-26 13:40:12 -05:00
data-maps-v2-target="photosToggle"
2025-11-25 17:37:50 -05:00
data-action="change->maps-v2#togglePhotos" />
<span class="label-text font-medium">Photos</span>
</label>
<p class="text-sm text-base-content/60 ml-14">Show geotagged photos</p>
</div>
<div class="divider my-2"></div>
<!-- Areas Layer -->
<div class="form-control">
<label class="label cursor-pointer justify-start gap-3">
<input type="checkbox"
class="toggle toggle-primary"
2025-11-26 13:40:12 -05:00
data-maps-v2-target="areasToggle"
2025-11-25 17:37:50 -05:00
data-action="change->maps-v2#toggleAreas" />
<span class="label-text font-medium">Areas</span>
</label>
<p class="text-sm text-base-content/60 ml-14">Show defined areas</p>
</div>
<div class="divider my-2"></div>
<!-- Tracks Layer -->
2025-11-26 13:40:12 -05:00
<%# <div class="form-control">
2025-11-25 17:37:50 -05:00
<label class="label cursor-pointer justify-start gap-3">
<input type="checkbox"
class="toggle toggle-primary"
2025-11-26 13:40:12 -05:00
data-maps-v2-target="tracksToggle"
2025-11-25 17:37:50 -05:00
data-action="change->maps-v2#toggleTracks" />
<span class="label-text font-medium">Tracks</span>
</label>
<p class="text-sm text-base-content/60 ml-14">Show saved tracks</p>
2025-11-26 13:40:12 -05:00
</div> %>
2025-11-25 17:37:50 -05:00
2025-11-26 13:40:12 -05:00
<%# <div class="divider my-2"></div> %>
2025-11-25 17:37:50 -05:00
<!-- Fog of War Layer -->
<div class="form-control">
<label class="label cursor-pointer justify-start gap-3">
<input type="checkbox"
class="toggle toggle-primary"
2025-11-26 13:40:12 -05:00
data-maps-v2-target="fogToggle"
2025-11-25 17:37:50 -05:00
data-action="change->maps-v2#toggleFog" />
<span class="label-text font-medium">Fog of War</span>
</label>
<p class="text-sm text-base-content/60 ml-14">Show explored areas</p>
</div>
<div class="divider my-2"></div>
<!-- Scratch Map Layer -->
<div class="form-control">
<label class="label cursor-pointer justify-start gap-3">
<input type="checkbox"
class="toggle toggle-primary"
2025-11-26 13:40:12 -05:00
data-maps-v2-target="scratchToggle"
2025-11-25 17:37:50 -05:00
data-action="change->maps-v2#toggleScratch" />
<span class="label-text font-medium">Scratch Map</span>
</label>
<p class="text-sm text-base-content/60 ml-14">Show scratched countries</p>
</div>
2025-11-26 13:40:12 -05:00
2025-11-25 17:37:50 -05:00
</div>
</div>
<!-- Settings Tab -->
<div class="tab-content" data-tab-content="settings" data-map-panel-target="tabContent">
2025-11-26 13:40:12 -05:00
<form data-action="submit->maps-v2#updateAdvancedSettings" class="space-y-4">
2025-11-25 17:37:50 -05:00
<!-- Map Style -->
<div class="form-control w-full">
<label class="label">
<span class="label-text font-medium">Map Style</span>
</label>
<select class="select select-bordered w-full"
2025-11-26 13:40:12 -05:00
name="mapStyle"
2025-11-25 17:37:50 -05:00
data-action="change->maps-v2#updateMapStyle">
<option value="light" selected>Light</option>
<option value="dark">Dark</option>
<option value="white">White</option>
<option value="black">Black</option>
<option value="grayscale">Grayscale</option>
</select>
</div>
2025-11-26 13:40:12 -05:00
<div class="divider my-2"></div>
<!-- Route Opacity -->
<div class="form-control w-full">
<label class="label">
<span class="label-text font-medium">Route Opacity</span>
<span class="label-text-alt">%</span>
</label>
<input type="range"
name="routeOpacity"
min="10"
max="100"
step="10"
value="100"
class="range range-primary range-sm"
data-maps-v2-target="routeOpacityRange"
data-action="input->maps-v2#updateRouteOpacity" />
<div class="w-full flex justify-between text-xs px-2 mt-1">
<span>10%</span>
<span>50%</span>
<span>100%</span>
</div>
</div>
<div class="divider my-2"></div>
<!-- Fog of War Settings -->
<div class="form-control w-full">
<label class="label">
<span class="label-text font-medium">Fog of War Radius</span>
<span class="label-text-alt" data-maps-v2-target="fogRadiusValue">1000m</span>
</label>
<input type="range"
name="fogOfWarRadius"
min="5"
max="2000"
step="5"
value="1000"
class="range range-primary range-sm"
data-action="input->maps-v2#updateFogRadiusDisplay" />
<div class="w-full flex justify-between text-xs px-2 mt-1">
<span>5m</span>
<span>1000m</span>
<span>2000m</span>
</div>
<p class="text-xs text-base-content/60 mt-1">Clear radius around visited points</p>
</div>
<div class="form-control w-full">
<label class="label">
<span class="label-text font-medium">Fog of War Threshold</span>
<span class="label-text-alt" data-maps-v2-target="fogThresholdValue">1</span>
</label>
<input type="range"
name="fogOfWarThreshold"
min="1"
max="10"
step="1"
value="1"
class="range range-primary range-sm"
data-action="input->maps-v2#updateFogThresholdDisplay" />
<div class="w-full flex justify-between text-xs px-2 mt-1">
<span>1</span>
<span>5</span>
<span>10</span>
</div>
<p class="text-xs text-base-content/60 mt-1">Minimum points to clear fog</p>
</div>
<div class="divider my-2"></div>
<!-- Route Generation Settings -->
<div class="form-control w-full">
<label class="label">
<span class="label-text font-medium">Meters Between Routes</span>
<span class="label-text-alt" data-maps-v2-target="metersBetweenValue">500m</span>
</label>
<input type="range"
name="metersBetweenRoutes"
min="100"
max="5000"
step="100"
value="500"
class="range range-primary range-sm"
data-action="input->maps-v2#updateMetersBetweenDisplay" />
<div class="w-full flex justify-between text-xs px-2 mt-1">
<span>100m</span>
<span>2500m</span>
<span>5000m</span>
</div>
<p class="text-xs text-base-content/60 mt-1">Distance threshold for route splitting</p>
</div>
<div class="form-control w-full">
<label class="label">
<span class="label-text font-medium">Minutes Between Routes</span>
<span class="label-text-alt" data-maps-v2-target="minutesBetweenValue">60min</span>
</label>
<input type="range"
name="minutesBetweenRoutes"
min="1"
max="180"
step="1"
value="60"
class="range range-primary range-sm"
data-action="input->maps-v2#updateMinutesBetweenDisplay" />
<div class="w-full flex justify-between text-xs px-2 mt-1">
<span>1min</span>
<span>90min</span>
<span>180min</span>
</div>
<p class="text-xs text-base-content/60 mt-1">Time threshold for route splitting</p>
</div>
<div class="divider my-2"></div>
<!-- Points Rendering Mode -->
<div class="form-control w-full">
<label class="label">
<span class="label-text font-medium">Points Rendering Mode</span>
</label>
<div class="flex flex-col gap-2">
<label class="label cursor-pointer justify-start gap-3 py-1">
<input type="radio"
name="pointsRenderingMode"
value="raw"
class="radio radio-primary radio-sm"
checked />
<span class="label-text">Raw (all points)</span>
</label>
<label class="label cursor-pointer justify-start gap-3 py-1">
<input type="radio"
name="pointsRenderingMode"
value="simplified"
class="radio radio-primary radio-sm" />
<span class="label-text">Simplified (reduced points)</span>
</label>
</div>
</div>
<div class="divider my-2"></div>
2025-11-25 17:37:50 -05:00
2025-11-26 13:40:12 -05:00
<!-- Speed-Colored Routes -->
2025-11-25 17:37:50 -05:00
<div class="form-control">
<label class="label cursor-pointer justify-start gap-3">
<input type="checkbox"
2025-11-26 13:40:12 -05:00
name="speedColoredRoutes"
class="toggle toggle-primary" />
<span class="label-text font-medium">Speed-Colored Routes</span>
2025-11-25 17:37:50 -05:00
</label>
2025-11-26 13:40:12 -05:00
<p class="text-sm text-base-content/60 mt-1">Color routes by speed</p>
2025-11-25 17:37:50 -05:00
</div>
2025-11-26 13:40:12 -05:00
<div class="divider my-2"></div>
2025-11-25 17:37:50 -05:00
<!-- Live Mode -->
<div class="form-control">
<label class="label cursor-pointer justify-start gap-3">
<input type="checkbox"
class="toggle toggle-primary"
data-action="change->maps-v2-realtime#toggleLiveMode"
data-maps-v2-realtime-target="liveModeToggle" />
<span class="label-text font-medium">Live Mode</span>
</label>
<p class="text-sm text-base-content/60 mt-1">Show new points in real-time</p>
</div>
2025-11-26 13:40:12 -05:00
<div class="divider my-2"></div>
<!-- Update Button -->
<button type="submit" class="btn btn-primary btn-block">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-5 h-5">
<path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
<polyline points="12 2 12 12 14.5 14.5"></polyline>
</svg>
Apply Settings
</button>
2025-11-25 17:37:50 -05:00
<!-- Reset Settings -->
2025-11-26 13:40:12 -05:00
<button type="button"
class="btn btn-outline btn-block"
2025-11-25 17:37:50 -05:00
data-action="click->maps-v2#resetSettings">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-5 h-5">
<path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"></path>
<path d="M21 3v5h-5"></path>
<path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"></path>
<path d="M3 21v-5h5"></path>
</svg>
Reset to Defaults
</button>
2025-11-26 13:40:12 -05:00
</form>
2025-11-25 17:37:50 -05:00
</div>
<!-- Tools Tab -->
<div class="tab-content" data-tab-content="tools" data-map-panel-target="tabContent">
<div class="space-y-4">
<!-- Create a Visit Button -->
<button type="button"
class="btn btn-primary btn-block"
data-action="click->maps-v2#startCreateVisit">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-5 h-5">
<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path>
<circle cx="12" cy="10" r="3"></circle>
</svg>
Create a Visit
</button>
<div class="divider my-2"></div>
<!-- Create a Place Button -->
<button type="button"
class="btn btn-outline btn-block"
data-action="click->maps-v2#startCreatePlace">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-5 h-5">
<path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z"></path>
<circle cx="12" cy="10" r="3"></circle>
</svg>
Create a Place
</button>
<div class="divider my-2"></div>
<!-- Select Area Button -->
<button type="button"
class="btn btn-outline btn-block"
disabled>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-5 h-5">
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
<path d="M9 3v18"></path>
<path d="M15 3v18"></path>
<path d="M3 9h18"></path>
<path d="M3 15h18"></path>
</svg>
Select Area
</button>
<p class="text-xs text-base-content/60 text-center">Coming soon</p>
</div>
</div>
<% if !DawarichSettings.self_hosted? %>
<!-- Links Tab -->
<div class="tab-content" data-tab-content="links" data-map-panel-target="tabContent">
<div class="space-y-6">
<!-- Community Section -->
<div>
<h4 class="font-semibold text-base mb-3">Community</h4>
<div class="flex flex-col gap-2">
<a href="https://discord.gg/pHsBjpt5J8" target="_blank" class="link-hover text-sm">Discord</a>
<a href="https://x.com/freymakesstuff" target="_blank" class="link-hover text-sm">X</a>
<a href="https://github.com/Freika/dawarich" target="_blank" class="link-hover text-sm">Github</a>
<a href="https://mastodon.social/@dawarich" target="_blank" class="link-hover text-sm">Mastodon</a>
</div>
</div>
<div class="divider my-2"></div>
<!-- Docs Section -->
<div>
<h4 class="font-semibold text-base mb-3">Docs</h4>
<div class="flex flex-col gap-2">
<a href="https://dawarich.app/docs/intro" target="_blank" class="link-hover text-sm">Tutorial</a>
<a href="https://dawarich.app/docs/tutorials/import-existing-data" target="_blank" class="link-hover text-sm">Import existing data</a>
<a href="https://dawarich.app/docs/tutorials/export-your-data" target="_blank" class="link-hover text-sm">Exporting data</a>
<a href="https://dawarich.app/docs/FAQ" target="_blank" class="link-hover text-sm">FAQ</a>
<a href="https://dawarich.app/contact" target="_blank" class="link-hover text-sm">Contact</a>
</div>
</div>
<div class="divider my-2"></div>
<!-- More Section -->
<div>
<h4 class="font-semibold text-base mb-3">More</h4>
<div class="flex flex-col gap-2">
<a href="https://dawarich.app/privacy-policy" target="_blank" class="link-hover text-sm">Privacy policy</a>
<a href="https://dawarich.app/terms-and-conditions" target="_blank" class="link-hover text-sm">Terms and Conditions</a>
<a href="https://dawarich.app/refund-policy" target="_blank" class="link-hover text-sm">Refund policy</a>
<a href="https://dawarich.app/impressum" target="_blank" class="link-hover text-sm">Impressum</a>
<a href="https://dawarich.app/blog" target="_blank" class="link-hover text-sm">Blog</a>
</div>
</div>
</div>
</div>
<% end %>
2025-11-25 17:37:50 -05:00
</div>
2025-11-20 16:36:58 -05:00
</div>
</div>
<style>
2025-11-25 17:37:50 -05:00
.map-control-panel {
position: absolute;
2025-11-20 16:36:58 -05:00
top: 0;
2025-11-26 13:40:12 -05:00
right: -480px; /* Hidden by default */
width: 480px;
2025-11-25 17:37:50 -05:00
height: 100%;
background: oklch(var(--b1));
box-shadow: -4px 0 24px rgba(0, 0, 0, 0.15);
2025-11-20 16:36:58 -05:00
z-index: 9999;
2025-11-25 17:37:50 -05:00
transition: right 0.3s cubic-bezier(0.4, 0, 0.2, 1);
display: flex;
overflow: hidden;
2025-11-20 16:36:58 -05:00
}
2025-11-25 17:37:50 -05:00
.map-control-panel.open {
2025-11-20 16:36:58 -05:00
right: 0;
}
2025-11-25 17:37:50 -05:00
/* Vertical Tab Bar */
.panel-tabs {
width: 64px;
background: oklch(var(--b2));
border-right: 1px solid oklch(var(--bc) / 0.1);
2025-11-20 16:36:58 -05:00
display: flex;
2025-11-25 17:37:50 -05:00
flex-direction: column;
2025-11-20 16:36:58 -05:00
align-items: center;
2025-11-25 17:37:50 -05:00
padding: 16px 0;
gap: 8px;
2025-11-26 13:40:12 -05:00
flex-shrink: 0;
2025-11-20 16:36:58 -05:00
}
2025-11-25 17:37:50 -05:00
.tab-btn {
width: 48px;
height: 48px;
2025-11-20 16:36:58 -05:00
display: flex;
align-items: center;
justify-content: center;
2025-11-25 17:37:50 -05:00
border-radius: 8px;
border: none;
background: transparent;
cursor: pointer;
transition: all 0.2s;
position: relative;
color: oklch(var(--bc) / 0.6);
2025-11-20 16:36:58 -05:00
}
2025-11-25 17:37:50 -05:00
.tab-btn:hover {
background: oklch(var(--b3));
color: oklch(var(--bc));
2025-11-20 16:36:58 -05:00
}
2025-11-25 17:37:50 -05:00
.tab-btn.active {
background: oklch(var(--p));
color: oklch(var(--pc));
2025-11-20 16:36:58 -05:00
}
2025-11-25 17:37:50 -05:00
.tab-btn.active::after {
content: '';
position: absolute;
right: -1px;
top: 50%;
transform: translateY(-50%);
width: 3px;
height: 24px;
background: oklch(var(--p));
border-radius: 2px 0 0 2px;
2025-11-20 16:36:58 -05:00
}
2025-11-25 17:37:50 -05:00
.tab-icon {
width: 24px;
height: 24px;
2025-11-20 16:36:58 -05:00
}
2025-11-25 17:37:50 -05:00
/* Panel Content */
.panel-content {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
2025-11-26 13:40:12 -05:00
min-width: 0;
2025-11-20 16:36:58 -05:00
}
2025-11-25 17:37:50 -05:00
.panel-header {
2025-11-20 16:36:58 -05:00
display: flex;
2025-11-25 17:37:50 -05:00
justify-content: space-between;
2025-11-20 16:36:58 -05:00
align-items: center;
2025-11-25 17:37:50 -05:00
padding: 20px 24px;
border-bottom: 1px solid oklch(var(--bc) / 0.1);
background: oklch(var(--b1));
2025-11-26 13:40:12 -05:00
flex-shrink: 0;
2025-11-20 16:36:58 -05:00
}
2025-11-25 17:37:50 -05:00
.panel-title {
font-size: 1.25rem;
font-weight: 600;
margin: 0;
color: oklch(var(--bc));
2025-11-20 16:36:58 -05:00
}
2025-11-25 17:37:50 -05:00
.panel-body {
flex: 1;
overflow-y: auto;
padding: 24px;
}
/* Tab Content */
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
/* Custom Scrollbar */
.panel-body::-webkit-scrollbar {
width: 8px;
}
.panel-body::-webkit-scrollbar-track {
background: transparent;
}
.panel-body::-webkit-scrollbar-thumb {
background: oklch(var(--bc) / 0.2);
border-radius: 4px;
}
.panel-body::-webkit-scrollbar-thumb:hover {
background: oklch(var(--bc) / 0.3);
2025-11-20 16:36:58 -05:00
}
2025-11-26 13:40:12 -05:00
/* Toggle Focus State - Remove all focus indicators */
.toggle:focus,
.toggle:focus-visible,
.toggle:focus-within {
outline: none !important;
box-shadow: none !important;
border-color: inherit !important;
}
/* Override DaisyUI toggle focus styles */
.toggle:focus-visible:checked,
.toggle:checked:focus,
.toggle:checked:focus-visible {
outline: none !important;
box-shadow: none !important;
}
/* Ensure no outline on the toggle container */
.form-control .toggle:focus {
outline: none !important;
}
/* Prevent indeterminate visual state on toggles */
.toggle:indeterminate {
opacity: 1;
}
/* Ensure smooth toggle transitions without intermediate states */
.toggle {
transition: background-color 0.2s ease, border-color 0.2s ease;
}
.toggle:checked {
transition: background-color 0.2s ease, border-color 0.2s ease;
}
/* Remove any active/pressed state that might cause intermediate appearance */
.toggle:active,
.toggle:active:focus {
outline: none !important;
box-shadow: none !important;
}
/* Responsive Breakpoints */
/* Large tablets and smaller desktops (1024px - 1280px) */
@media (max-width: 1280px) {
.map-control-panel {
width: 420px;
right: -420px;
}
}
/* Tablets (768px - 1024px) */
@media (max-width: 1024px) {
.map-control-panel {
width: 380px;
right: -380px;
}
.panel-body {
padding: 20px;
}
}
/* Small tablets and large phones (640px - 768px) */
@media (max-width: 768px) {
.map-control-panel {
width: 90%;
right: -90%;
max-width: 400px;
}
.panel-header {
padding: 16px 20px;
}
.panel-title {
font-size: 1.125rem;
}
.panel-body {
padding: 16px 20px;
}
}
/* Mobile phones (< 640px) */
2025-11-25 17:37:50 -05:00
@media (max-width: 640px) {
.map-control-panel {
width: 100%;
right: -100%;
2025-11-26 13:40:12 -05:00
max-width: none;
}
.panel-tabs {
width: 56px;
padding: 12px 0;
gap: 6px;
}
.tab-btn {
width: 44px;
height: 44px;
}
.tab-icon {
width: 20px;
height: 20px;
}
.panel-header {
padding: 14px 16px;
}
.panel-title {
font-size: 1rem;
}
.panel-body {
padding: 16px;
}
/* Reduce spacing on mobile */
.space-y-4 > * + * {
margin-top: 0.75rem;
}
.space-y-6 > * + * {
margin-top: 1rem;
}
}
/* Very small phones (< 375px) */
@media (max-width: 375px) {
.panel-tabs {
width: 52px;
padding: 10px 0;
}
.tab-btn {
width: 40px;
height: 40px;
}
.panel-header {
padding: 12px;
}
.panel-body {
padding: 12px;
2025-11-25 17:37:50 -05:00
}
2025-11-20 16:36:58 -05:00
}
</style>