mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-11 09:41:40 -05:00
Show battery status on family member popup
This commit is contained in:
parent
1bf02bc063
commit
1e63b03b49
6 changed files with 69 additions and 12 deletions
File diff suppressed because one or more lines are too long
|
|
@ -109,7 +109,7 @@ export default class extends Controller {
|
|||
const lastSeen = new Date(location.updated_at).toLocaleString();
|
||||
|
||||
// Create small tooltip that shows automatically
|
||||
const tooltipContent = this.createTooltipContent(lastSeen);
|
||||
const tooltipContent = this.createTooltipContent(lastSeen, location.battery);
|
||||
const tooltip = familyMarker.bindTooltip(tooltipContent, {
|
||||
permanent: true,
|
||||
direction: 'top',
|
||||
|
|
@ -177,7 +177,7 @@ export default class extends Controller {
|
|||
|
||||
// Update tooltip content
|
||||
const lastSeen = new Date(locationData.updated_at).toLocaleString();
|
||||
const tooltipContent = this.createTooltipContent(lastSeen);
|
||||
const tooltipContent = this.createTooltipContent(lastSeen, locationData.battery);
|
||||
existingMarker.setTooltipContent(tooltipContent);
|
||||
|
||||
// Update popup content
|
||||
|
|
@ -216,7 +216,7 @@ export default class extends Controller {
|
|||
|
||||
const lastSeen = new Date(location.updated_at).toLocaleString();
|
||||
|
||||
const tooltipContent = this.createTooltipContent(lastSeen);
|
||||
const tooltipContent = this.createTooltipContent(lastSeen, location.battery);
|
||||
familyMarker.bindTooltip(tooltipContent, {
|
||||
permanent: true,
|
||||
direction: 'top',
|
||||
|
|
@ -238,8 +238,9 @@ export default class extends Controller {
|
|||
this.familyMarkers[location.user_id] = familyMarker;
|
||||
}
|
||||
|
||||
createTooltipContent(lastSeen) {
|
||||
return `Last seen: ${lastSeen}`;
|
||||
createTooltipContent(lastSeen, battery) {
|
||||
const batteryInfo = battery !== null && battery !== undefined ? ` | Battery: ${battery}%` : '';
|
||||
return `Last seen: ${lastSeen}${batteryInfo}`;
|
||||
}
|
||||
|
||||
createPopupContent(location, lastSeen) {
|
||||
|
|
@ -250,6 +251,59 @@ export default class extends Controller {
|
|||
|
||||
const emailInitial = location.email_initial || location.email?.charAt(0)?.toUpperCase() || '?';
|
||||
|
||||
// Battery display with icon
|
||||
const battery = location.battery;
|
||||
const batteryStatus = location.battery_status;
|
||||
let batteryDisplay = '';
|
||||
|
||||
if (battery !== null && battery !== undefined) {
|
||||
// Determine battery color based on level and status
|
||||
let batteryColor = '#10B981'; // green
|
||||
if (batteryStatus === 'charging') {
|
||||
batteryColor = battery <= 50 ? '#F59E0B' : '#10B981'; // orange if low, green if high
|
||||
} else if (battery <= 20) {
|
||||
batteryColor = '#EF4444'; // red
|
||||
} else if (battery <= 50) {
|
||||
batteryColor = '#F59E0B'; // orange
|
||||
}
|
||||
|
||||
// Helper function to get appropriate Lucide battery icon
|
||||
const getBatteryIcon = (battery, batteryStatus, batteryColor) => {
|
||||
const baseAttrs = `width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="${batteryColor}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align: middle; margin-right: 4px;"`;
|
||||
|
||||
// Charging icon
|
||||
if (batteryStatus === 'charging') {
|
||||
return `<svg xmlns="http://www.w3.org/2000/svg" ${baseAttrs}><path d="m11 7-3 5h4l-3 5"/><path d="M14.856 6H16a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.935"/><path d="M22 14v-4"/><path d="M5.14 18H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h2.936"/></svg>`;
|
||||
}
|
||||
|
||||
// Full battery
|
||||
if (battery === 100 || batteryStatus === 'full') {
|
||||
return `<svg xmlns="http://www.w3.org/2000/svg" ${baseAttrs}><path d="M10 10v4"/><path d="M14 10v4"/><path d="M22 14v-4"/><path d="M6 10v4"/><rect x="2" y="6" width="16" height="12" rx="2"/></svg>`;
|
||||
}
|
||||
|
||||
// Low battery (≤20%)
|
||||
if (battery <= 20) {
|
||||
return `<svg xmlns="http://www.w3.org/2000/svg" ${baseAttrs}><path d="M22 14v-4"/><path d="M6 14v-4"/><rect x="2" y="6" width="16" height="12" rx="2"/></svg>`;
|
||||
}
|
||||
|
||||
// Medium battery (21-50%)
|
||||
if (battery <= 50) {
|
||||
return `<svg xmlns="http://www.w3.org/2000/svg" ${baseAttrs}><path d="M10 14v-4"/><path d="M22 14v-4"/><path d="M6 14v-4"/><rect x="2" y="6" width="16" height="12" rx="2"/></svg>`;
|
||||
}
|
||||
|
||||
// High battery (>50%, default to full)
|
||||
return `<svg xmlns="http://www.w3.org/2000/svg" ${baseAttrs}><path d="M10 10v4"/><path d="M14 10v4"/><path d="M22 14v-4"/><path d="M6 10v4"/><rect x="2" y="6" width="16" height="12" rx="2"/></svg>`;
|
||||
};
|
||||
|
||||
const batteryIcon = getBatteryIcon(battery, batteryStatus, batteryColor);
|
||||
|
||||
batteryDisplay = `
|
||||
<p style="margin: 0 0 8px 0; font-size: 13px;">
|
||||
${batteryIcon}<strong>Battery:</strong> ${battery}%${batteryStatus ? ` (${batteryStatus})` : ''}
|
||||
</p>
|
||||
`;
|
||||
}
|
||||
|
||||
return `
|
||||
<div class="family-member-popup" style="background-color: ${bgColor}; color: ${textColor}; padding: 12px; border-radius: 8px; min-width: 220px;">
|
||||
<h3 style="margin: 0 0 12px 0; color: #10B981; font-size: 15px; font-weight: bold; display: flex; align-items: center; gap: 8px;">
|
||||
|
|
@ -263,6 +317,7 @@ export default class extends Controller {
|
|||
<strong>Coordinates:</strong><br/>
|
||||
${location.latitude.toFixed(6)}, ${location.longitude.toFixed(6)}
|
||||
</p>
|
||||
${batteryDisplay}
|
||||
<p style="margin: 0; font-size: 12px; color: ${mutedColor}; padding-top: 8px; border-top: 1px solid ${isDark ? '#374151' : '#e5e7eb'};">
|
||||
<strong>Last seen:</strong> ${lastSeen}
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -803,7 +803,7 @@ export default class extends BaseController {
|
|||
const SettingsControl = L.Control.extend({
|
||||
onAdd: (map) => {
|
||||
const button = L.DomUtil.create('button', 'map-settings-button tooltip tooltip-right');
|
||||
button.innerHTML = '⚙️'; // Gear icon
|
||||
button.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-cog-icon lucide-cog"><path d="M11 10.27 7 3.34"/><path d="m11 13.73-4 6.93"/><path d="M12 22v-2"/><path d="M12 2v2"/><path d="M14 12h8"/><path d="m17 20.66-1-1.73"/><path d="m17 3.34-1 1.73"/><path d="M2 12h2"/><path d="m20.66 17-1.73-1"/><path d="m20.66 7-1.73 1"/><path d="m3.34 17 1.73-1"/><path d="m3.34 7 1.73 1"/><circle cx="12" cy="12" r="2"/><circle cx="12" cy="12" r="8"/></svg>'; // Gear icon
|
||||
button.setAttribute('data-tip', 'Settings');
|
||||
|
||||
// Style the button with theme-aware styling
|
||||
|
|
|
|||
|
|
@ -41,7 +41,9 @@ class Families::Locations
|
|||
latitude: point.lat,
|
||||
longitude: point.lon,
|
||||
timestamp: point.timestamp.to_i,
|
||||
updated_at: Time.zone.at(point.timestamp.to_i)
|
||||
updated_at: Time.zone.at(point.timestamp.to_i),
|
||||
battery: point.battery,
|
||||
battery_status: point.battery_status
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -24,14 +24,14 @@
|
|||
|
||||
<body class='h-screen overflow-hidden relative'>
|
||||
<!-- Fixed Navbar -->
|
||||
<div class='fixed w-full z-50 bg-base-100 shadow-md h-16'>
|
||||
<div class='fixed w-full z-40 bg-base-100 shadow-md h-16'>
|
||||
<div class='container mx-auto h-full w-full flex items-center'>
|
||||
<%= render 'shared/navbar' %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Flash Messages - Fixed below navbar -->
|
||||
<div class='fixed top-16 w-full z-40'>
|
||||
<div class='fixed top-16 w-full z-50'>
|
||||
<div class='container mx-auto px-5'>
|
||||
<%= render 'shared/flash' %>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -525,7 +525,7 @@ test.describe('Map Functionality', () => {
|
|||
|
||||
// Verify it's actually a clickable button with gear icon
|
||||
const buttonText = await settingsButton.textContent();
|
||||
expect(buttonText).toBe('⚙️');
|
||||
expect(buttonText).toBe('<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-cog-icon lucide-cog"><path d="M11 10.27 7 3.34"/><path d="m11 13.73-4 6.93"/><path d="M12 22v-2"/><path d="M12 2v2"/><path d="M14 12h8"/><path d="m17 20.66-1-1.73"/><path d="m17 3.34-1 1.73"/><path d="M2 12h2"/><path d="m20.66 17-1.73-1"/><path d="m20.66 7-1.73 1"/><path d="m3.34 17 1.73-1"/><path d="m3.34 7 1.73 1"/><circle cx="12" cy="12" r="2"/><circle cx="12" cy="12" r="8"/></svg>');
|
||||
|
||||
// Test opening settings panel
|
||||
await settingsButton.click();
|
||||
|
|
|
|||
Loading…
Reference in a new issue