feat(dashboard): refine moment media experience
This commit is contained in:
+88
-12
@@ -94,6 +94,10 @@ final class App
|
||||
$this->serveDayImage();
|
||||
return;
|
||||
|
||||
case '/event-image':
|
||||
$this->serveEventImage();
|
||||
return;
|
||||
|
||||
case '/track':
|
||||
$method === 'POST' ? $this->handleTrack() : $this->showTrack();
|
||||
return;
|
||||
@@ -327,8 +331,8 @@ final class App
|
||||
|
||||
$upload = uploaded_files('background_image')[0] ?? null;
|
||||
if (is_array($upload) && (int) ($upload['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_NO_FILE) {
|
||||
$this->deleteDashboardBackgroundImage($user['username'], $date, (string) ($current['background_image'] ?? ''));
|
||||
$current['background_image'] = $this->storeDashboardBackgroundImage($user['username'], $date, $upload);
|
||||
$this->deleteDashboardImage($user['username'], (string) ($current['background_image'] ?? ''));
|
||||
$current['background_image'] = $this->storeDashboardImage($user['username'], $date, $upload);
|
||||
}
|
||||
|
||||
$entryMap[$date] = $current;
|
||||
@@ -339,12 +343,16 @@ final class App
|
||||
|
||||
if ($form === 'add_event') {
|
||||
$event = $this->dashboardEventFromPost($_POST);
|
||||
$upload = uploaded_files('event_image')[0] ?? null;
|
||||
if (is_array($upload) && (int) ($upload['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_NO_FILE) {
|
||||
$event['image'] = $this->storeDashboardImage($user['username'], $date, $upload);
|
||||
}
|
||||
$events = is_array($current['events'] ?? null) ? $current['events'] : [];
|
||||
$events[] = $event;
|
||||
$current['events'] = $events;
|
||||
$entryMap[$date] = $current;
|
||||
$this->persistUserEntries($user['username'], $settings, array_values($entryMap));
|
||||
flash('success', 'Die Aktivität wurde hinzugefügt.');
|
||||
flash('success', 'Der Moment wurde hinzugefügt.');
|
||||
redirect('/?view=day&date=' . rawurlencode($date));
|
||||
}
|
||||
|
||||
@@ -352,6 +360,7 @@ final class App
|
||||
$eventID = trim((string) ($_POST['event_id'] ?? ''));
|
||||
$updatedEvent = $this->dashboardEventFromPost($_POST);
|
||||
$updatedEvent['id'] = $eventID !== '' ? $eventID : $updatedEvent['id'];
|
||||
$upload = uploaded_files('event_image')[0] ?? null;
|
||||
$events = [];
|
||||
|
||||
foreach (is_array($current['events'] ?? null) ? $current['events'] : [] as $event) {
|
||||
@@ -360,6 +369,11 @@ final class App
|
||||
}
|
||||
|
||||
if ((string) ($event['id'] ?? '') === $eventID) {
|
||||
$updatedEvent['image'] = (string) ($event['image'] ?? '');
|
||||
if (is_array($upload) && (int) ($upload['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_NO_FILE) {
|
||||
$this->deleteDashboardImage($user['username'], (string) ($event['image'] ?? ''));
|
||||
$updatedEvent['image'] = $this->storeDashboardImage($user['username'], $date, $upload);
|
||||
}
|
||||
$events[] = $updatedEvent;
|
||||
continue;
|
||||
}
|
||||
@@ -376,18 +390,23 @@ final class App
|
||||
|
||||
if ($form === 'delete_event') {
|
||||
$eventID = trim((string) ($_POST['event_id'] ?? ''));
|
||||
foreach (is_array($current['events'] ?? null) ? $current['events'] : [] as $event) {
|
||||
if (is_array($event) && (string) ($event['id'] ?? '') === $eventID) {
|
||||
$this->deleteDashboardImage($user['username'], (string) ($event['image'] ?? ''));
|
||||
}
|
||||
}
|
||||
$current['events'] = array_values(array_filter(
|
||||
is_array($current['events'] ?? null) ? $current['events'] : [],
|
||||
static fn (array $event): bool => (string) ($event['id'] ?? '') !== $eventID
|
||||
));
|
||||
$entryMap[$date] = $current;
|
||||
$this->persistUserEntries($user['username'], $settings, array_values($entryMap));
|
||||
flash('success', 'Die Aktivität wurde entfernt.');
|
||||
flash('success', 'Der Moment wurde entfernt.');
|
||||
redirect('/?view=day&date=' . rawurlencode($date));
|
||||
}
|
||||
|
||||
if ($form === 'remove_background') {
|
||||
$this->deleteDashboardBackgroundImage($user['username'], $date, (string) ($current['background_image'] ?? ''));
|
||||
$this->deleteDashboardImage($user['username'], (string) ($current['background_image'] ?? ''));
|
||||
$current['background_image'] = '';
|
||||
$entryMap[$date] = $current;
|
||||
$this->persistUserEntries($user['username'], $settings, array_values($entryMap));
|
||||
@@ -449,6 +468,8 @@ final class App
|
||||
'unit' => (string) ($event['unit'] ?? ''),
|
||||
'sport_type_id' => (string) ($event['sport_type_id'] ?? ''),
|
||||
'consumed' => !empty($event['consumed']),
|
||||
'image' => (string) ($event['image'] ?? ''),
|
||||
'image_url' => is_string($event['image_url'] ?? null) ? (string) $event['image_url'] : null,
|
||||
'mood' => normalize_signal_value($event['mood'] ?? 0),
|
||||
'energy' => normalize_signal_value($event['energy'] ?? 0),
|
||||
'stress' => normalize_signal_value($event['stress'] ?? 0),
|
||||
@@ -684,7 +705,7 @@ final class App
|
||||
|
||||
$value = max(0, min(50000, (float) ($input['event_value'] ?? 0)));
|
||||
if (in_array($type, ['walk', 'sport', 'sleep'], true) && $value <= 0) {
|
||||
throw new RuntimeException('Für diese Aktivität braucht es einen Wert oder eine Dauer.');
|
||||
throw new RuntimeException('Für diesen Moment braucht es einen Wert oder eine Dauer.');
|
||||
}
|
||||
|
||||
$sportTypeID = trim((string) ($input['event_sport_type_id'] ?? ''));
|
||||
@@ -724,6 +745,21 @@ final class App
|
||||
$date = (string) ($entry['date'] ?? '');
|
||||
|
||||
$entry['background_image_url'] = null;
|
||||
$events = [];
|
||||
foreach (is_array($entry['events'] ?? null) ? $entry['events'] : [] as $event) {
|
||||
if (!is_array($event)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$event['image_url'] = null;
|
||||
$eventImage = trim((string) ($event['image'] ?? ''));
|
||||
if ($eventImage !== '' && is_file($this->dashboardMediaDirectory($username) . '/' . basename($eventImage))) {
|
||||
$event['image_url'] = '/event-image?date=' . rawurlencode($date) . '&id=' . rawurlencode((string) ($event['id'] ?? ''));
|
||||
}
|
||||
$events[] = $event;
|
||||
}
|
||||
$entry['events'] = $events;
|
||||
|
||||
if ($fileName === '' || !$this->isValidDate($date)) {
|
||||
return $entry;
|
||||
}
|
||||
@@ -736,11 +772,11 @@ final class App
|
||||
return $entry;
|
||||
}
|
||||
|
||||
private function storeDashboardBackgroundImage(string $username, string $date, array $upload): string
|
||||
private function storeDashboardImage(string $username, string $date, array $upload): string
|
||||
{
|
||||
$error = (int) ($upload['error'] ?? UPLOAD_ERR_NO_FILE);
|
||||
if ($error !== UPLOAD_ERR_OK) {
|
||||
throw new RuntimeException('Das Tagesbild konnte nicht hochgeladen werden.');
|
||||
throw new RuntimeException('Das Bild konnte nicht hochgeladen werden.');
|
||||
}
|
||||
|
||||
$tmpName = (string) ($upload['tmp_name'] ?? '');
|
||||
@@ -757,7 +793,7 @@ final class App
|
||||
};
|
||||
|
||||
if ($extension === '') {
|
||||
throw new RuntimeException('Bitte nutze JPG, PNG oder WebP als Tagesbild.');
|
||||
throw new RuntimeException('Bitte nutze JPG, PNG oder WebP als Bild.');
|
||||
}
|
||||
|
||||
$directory = $this->dashboardMediaDirectory($username);
|
||||
@@ -769,13 +805,13 @@ final class App
|
||||
$target = $directory . '/' . $fileName;
|
||||
|
||||
if (!move_uploaded_file($tmpName, $target)) {
|
||||
throw new RuntimeException('Das Tagesbild konnte nicht gespeichert werden.');
|
||||
throw new RuntimeException('Das Bild konnte nicht gespeichert werden.');
|
||||
}
|
||||
|
||||
return $fileName;
|
||||
}
|
||||
|
||||
private function deleteDashboardBackgroundImage(string $username, string $date, string $fileName): void
|
||||
private function deleteDashboardImage(string $username, string $fileName): void
|
||||
{
|
||||
$path = $this->dashboardMediaDirectory($username) . '/' . basename($fileName);
|
||||
if (is_file($path)) {
|
||||
@@ -814,6 +850,41 @@ final class App
|
||||
exit;
|
||||
}
|
||||
|
||||
private function serveEventImage(): void
|
||||
{
|
||||
$user = $this->requireUser();
|
||||
$date = (string) ($_GET['date'] ?? '');
|
||||
$eventID = trim((string) ($_GET['id'] ?? ''));
|
||||
|
||||
if (!$this->isValidDate($date) || $eventID === '') {
|
||||
http_response_code(404);
|
||||
exit('Nicht gefunden');
|
||||
}
|
||||
|
||||
$entry = $this->entries->find($user['username'], $date);
|
||||
foreach (is_array($entry['events'] ?? null) ? $entry['events'] : [] as $event) {
|
||||
if (!is_array($event) || (string) ($event['id'] ?? '') !== $eventID) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$fileName = trim((string) ($event['image'] ?? ''));
|
||||
$path = $this->dashboardMediaDirectory($user['username']) . '/' . basename($fileName);
|
||||
if ($fileName === '' || !is_file($path)) {
|
||||
break;
|
||||
}
|
||||
|
||||
$mime = mime_content_type($path) ?: 'application/octet-stream';
|
||||
header('Content-Type: ' . $mime);
|
||||
header('Content-Length: ' . (string) filesize($path));
|
||||
header('Cache-Control: private, max-age=3600');
|
||||
readfile($path);
|
||||
exit;
|
||||
}
|
||||
|
||||
http_response_code(404);
|
||||
exit('Nicht gefunden');
|
||||
}
|
||||
|
||||
private function showTrack(): void
|
||||
{
|
||||
$user = $this->requireUser();
|
||||
@@ -1098,11 +1169,16 @@ final class App
|
||||
}
|
||||
}
|
||||
|
||||
$optionsOpenPanel = trim((string) ($_GET['panel'] ?? ''));
|
||||
if ($optionsOpenPanel === 'score') {
|
||||
$optionsOpenPanel = '';
|
||||
}
|
||||
|
||||
View::render('options', [
|
||||
'pageTitle' => 'Optionen',
|
||||
'page' => 'options',
|
||||
'authUser' => $user,
|
||||
'optionsOpenPanel' => trim((string) ($_GET['panel'] ?? '')),
|
||||
'optionsOpenPanel' => $optionsOpenPanel,
|
||||
'settings' => $settings,
|
||||
'sportTypePresets' => $sportTypePresets,
|
||||
'sportLocationOptions' => sport_location_options(),
|
||||
|
||||
Reference in New Issue
Block a user