Skip to content

Commit d384572

Browse files
committed
Show user session in frontend
1 parent b370d53 commit d384572

1 file changed

Lines changed: 79 additions & 2 deletions

File tree

app/web/templates/users/me.html

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ <h2 class="font-semibold">{{ _('me.rentals_title') }}</h2>
4949
<tr class="border-t hover:bg-gray-50">
5050
<td class="px-4 py-2 font-medium" x-text="r.item_name"></td>
5151
<td class="px-4 py-2 text-xs text-gray-400 text-right"
52-
x-text="r.rented_at ? r.rented_at.substring(0,16).replace('T',' ') : ''"></td>
52+
x-text="fmtDateTime(r.rented_at)"></td>
5353
</tr>
5454
</template>
5555
</tbody>
@@ -90,6 +90,53 @@ <h2 class="font-semibold">{{ _('me.machines_title') }}</h2>
9090

9191
</div>
9292

93+
<!-- Machine Session History -->
94+
<div class="bg-white rounded-lg shadow mb-6">
95+
<div class="px-5 py-4 border-b">
96+
<h2 class="font-semibold">{{ _('me.sessions_title') }}</h2>
97+
</div>
98+
<div class="overflow-x-auto">
99+
<table class="w-full text-sm">
100+
<thead class="bg-gray-50 text-gray-500 text-xs uppercase">
101+
<tr>
102+
<th class="px-4 py-2 text-left">{{ _('me.sessions_machine') }}</th>
103+
<th class="px-4 py-2 text-left">{{ _('machines.col_start') }}</th>
104+
<th class="px-4 py-2 text-left">{{ _('machines.col_duration') }}</th>
105+
<th class="px-4 py-2 text-right">{{ _('machines.col_cost') }}</th>
106+
</tr>
107+
</thead>
108+
<tbody>
109+
<template x-if="loadingSessions">
110+
<tr><td colspan="4" class="px-4 py-6 text-center text-gray-400">Loading…</td></tr>
111+
</template>
112+
<template x-if="!loadingSessions && sessions.length === 0">
113+
<tr><td colspan="4" class="px-4 py-6 text-center text-gray-400">{{ _('me.sessions_empty') }}</td></tr>
114+
</template>
115+
<template x-for="s in sessions" :key="s.id">
116+
<tr class="border-t hover:bg-gray-50">
117+
<td class="px-4 py-2 font-medium" x-text="s.machine_name"></td>
118+
<td class="px-4 py-2 text-xs text-gray-500 whitespace-nowrap" x-text="fmtDateTime(s.start_time)"></td>
119+
<td class="px-4 py-2 text-xs text-gray-500">
120+
<template x-if="s.end_time === null">
121+
<span class="bg-green-100 text-green-700 rounded px-1.5 py-0.5">{{ _('machines.history_active') }}</span>
122+
</template>
123+
<template x-if="s.end_time !== null">
124+
<span x-text="fmtDuration(s.duration_seconds)"></span>
125+
</template>
126+
</td>
127+
<td class="px-4 py-2 text-right tabular-nums text-xs"
128+
x-text="parseFloat(s.total_cost).toFixed(2) + ' €'"></td>
129+
</tr>
130+
</template>
131+
</tbody>
132+
</table>
133+
</div>
134+
<div class="mt-3 px-5 pb-3 text-center" x-show="sessionHasMore && !loadingSessions">
135+
<button @click="loadSessions()"
136+
class="text-sm text-blue-600 hover:underline">{{ _('machines.history_load_more') }}</button>
137+
</div>
138+
</div>
139+
93140
<!-- Transaction history -->
94141
<div class="bg-white rounded-lg shadow">
95142
<div class="px-5 py-4 border-b">
@@ -160,14 +207,19 @@ <h2 class="font-semibold">{{ _('me.transactions_title') }}</h2>
160207
rentals: [],
161208
machines: [],
162209
transactions: [],
210+
sessions: [],
163211
loading: true,
164212
loadingRentals: true,
165213
loadingMachines: true,
166214
loadingTx: true,
167215
loadingMoreTx: false,
216+
loadingSessions: true,
168217
txOffset: 0,
169218
txLimit: 50,
170219
hasMore: false,
220+
sessionOffset: 0,
221+
sessionPageSize: 10,
222+
sessionHasMore: false,
171223

172224
async init() {
173225
try {
@@ -180,7 +232,7 @@ <h2 class="font-semibold">{{ _('me.transactions_title') }}</h2>
180232
return;
181233
}
182234
this.loading = false;
183-
await Promise.all([this.loadRentals(), this.loadMachines(), this.loadTx()]);
235+
await Promise.all([this.loadRentals(), this.loadMachines(), this.loadTx(), this.loadSessions()]);
184236
},
185237

186238
async loadRentals() {
@@ -223,6 +275,31 @@ <h2 class="font-semibold">{{ _('me.transactions_title') }}</h2>
223275
this.loadingMoreTx = false;
224276
},
225277

278+
async loadSessions() {
279+
this.loadingSessions = true;
280+
try {
281+
const r = await apiFetch(`/api/v1/users/me/sessions?limit=${this.sessionPageSize}&offset=${this.sessionOffset}`);
282+
if (r.ok) {
283+
const data = await r.json();
284+
this.sessions.push(...data);
285+
this.sessionOffset += data.length;
286+
this.sessionHasMore = data.length === this.sessionPageSize;
287+
}
288+
} finally {
289+
this.loadingSessions = false;
290+
}
291+
},
292+
293+
fmtDuration(seconds) {
294+
if (seconds === null || seconds === undefined) return '';
295+
const h = Math.floor(seconds / 3600);
296+
const m = Math.floor((seconds % 3600) / 60);
297+
const s = seconds % 60;
298+
if (h > 0) return `${h}h ${m}m`;
299+
if (m > 0) return `${m}m ${s}s`;
300+
return `${s}s`;
301+
},
302+
226303
txLabel(type) {
227304
return _TX_LABELS[type] || type;
228305
},

0 commit comments

Comments
 (0)