Added Notifications

This commit is contained in:
2026-05-18 14:51:46 +10:00
parent 10b5b6a5c9
commit e1bed676e4
5 changed files with 67 additions and 5 deletions
+38
View File
@@ -0,0 +1,38 @@
<?php
namespace App\Console\Commands;
use App\Models\UserAction;
use App\Models\UserFlight;
use Illuminate\Console\Attributes\Description;
use Illuminate\Console\Attributes\Signature;
use Illuminate\Console\Command;
#[Signature('app:flight-feed-update')]
#[Description('Command description')]
class FlightFeedUpdate extends Command
{
public function handle()
{
$time = now('UTC');
$this->logFlightActions('flight_departing', UserFlight::where('departure_date', $time)->get()->toArray());
$this->logFlightActions('flight_arriving', UserFlight::where('arrival_date', $time)->get()->toArray());
}
/**
* @param string $type
* @param UserFlight[] $flights
* @return void
*/
private function logFlightActions(string $type, array $flights): void
{
foreach ($flights as $flight) {
UserAction::create([
'user_id' => $flight->user_id,
'type' => $type,
'data' => $flight->snapshot($flight->id),
]);
}
}
}
@@ -12,6 +12,7 @@ import {Link} from "@inertiajs/vue3";
import FlightUpdatedFeedItem from "@/Components/FlightsGoneBy/Feed/FlightUpdatedFeedItem.vue"; import FlightUpdatedFeedItem from "@/Components/FlightsGoneBy/Feed/FlightUpdatedFeedItem.vue";
import FlightCancelledFeedItem from "@/Components/FlightsGoneBy/Feed/FlightCancelledFeedItem.vue"; import FlightCancelledFeedItem from "@/Components/FlightsGoneBy/Feed/FlightCancelledFeedItem.vue";
import FlightImportedFeedItem from "@/Components/FlightsGoneBy/Feed/FlightImportedFeedItem.vue"; import FlightImportedFeedItem from "@/Components/FlightsGoneBy/Feed/FlightImportedFeedItem.vue";
import FlightMovedFeedItem from "@/Components/FlightsGoneBy/Feed/FlightMovedFeedItem.vue";
const props = defineProps<{ const props = defineProps<{
action: UserAction action: UserAction
@@ -31,6 +32,8 @@ const badgeVariant = computed(() => {
switch (props.action.type) { switch (props.action.type) {
case 'flight_booked': return 'generic' case 'flight_booked': return 'generic'
case 'flight_logged': return 'generic' case 'flight_logged': return 'generic'
case 'flight_departing': return 'generic'
case 'flight_arriving': return 'generic'
case 'flight_imported': return 'economy' case 'flight_imported': return 'economy'
case 'flight_updated': return 'economy' case 'flight_updated': return 'economy'
case 'flight_cancelled': return 'crew' case 'flight_cancelled': return 'crew'
@@ -74,6 +77,7 @@ function timeAgo(dateStr: string): string {
<FlightImportedFeedItem v-if="action.type == 'flight_imported'" :flight="(action.data as UserActionFlightBookedData).flight" ></FlightImportedFeedItem> <FlightImportedFeedItem v-if="action.type == 'flight_imported'" :flight="(action.data as UserActionFlightBookedData).flight" ></FlightImportedFeedItem>
<FlightUpdatedFeedItem v-if="action.type == 'flight_updated'" :data="(action.data as UserActionFlightUpdatedData)" ></FlightUpdatedFeedItem> <FlightUpdatedFeedItem v-if="action.type == 'flight_updated'" :data="(action.data as UserActionFlightUpdatedData)" ></FlightUpdatedFeedItem>
<FlightCancelledFeedItem v-if="action.type == 'flight_cancelled'" :data="(action.data as UserActionFlightCancelledData)" flight=""></FlightCancelledFeedItem> <FlightCancelledFeedItem v-if="action.type == 'flight_cancelled'" :data="(action.data as UserActionFlightCancelledData)" flight=""></FlightCancelledFeedItem>
<FlightMovedFeedItem v-if="action.type == 'flight_departing' || action.type== 'flight_arriving'" :flight="(action.data as UserActionFlightBookedData).flight" ></FlightMovedFeedItem>/
</div> </div>
<div class="card-actions"> <div class="card-actions">
<Link v-if="flight" :href="`/u/${action.user?.name}/departure-board/${flight?.id}`" class="view-flight-link"> <Link v-if="flight" :href="`/u/${action.user?.name}/departure-board/${flight?.id}`" class="view-flight-link">
@@ -0,0 +1,23 @@
<script setup lang="ts">
import {Flight} from "@/Types/types";
import BoardingPass from "@/Components/FlightsGoneBy/BoardingPass.vue";
import FlightBadge from "@/Components/FlightsGoneBy/FlightBadge.vue";
import {computed} from "vue";
const props = defineProps<{
flight: Flight
action: 'flight_departing' | 'flight_arriving'
}>()
const actionText = computed(() => props.action === 'flight_departing' ? 'departed' : 'landed')
</script>
<template>
<div class="flight-booked">
Flight <FlightBadge :flight="flight" /> from {{flight.departure_airport.municipality}} to {{flight.arrival_airport.municipality}} has {{actionText}}.
</div>
</template>
<style scoped>
</style>
+1 -1
View File
@@ -19,7 +19,7 @@ export interface User {
email_verified_at: string | null email_verified_at: string | null
} }
export type UserActionType = "flight_cancelled" | "flight_booked" | "flight_updated" | "flight_logged" | "flight_deleted" | "flight_imported" export type UserActionType = "flight_cancelled" | "flight_booked" | "flight_updated" | "flight_logged" | "flight_deleted" | "flight_imported" | "flight_departing" | "flight_arriving"
export type UserActionDataKey = "field" | "from" | "to" export type UserActionDataKey = "field" | "from" | "to"
export type UserActionFlightBookedData = { export type UserActionFlightBookedData = {
+1 -4
View File
@@ -3,8 +3,5 @@
use Illuminate\Foundation\Inspiring; use Illuminate\Foundation\Inspiring;
use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Artisan;
Artisan::command('inspire', function () {
$this->comment(Inspiring::quote());
})->purpose('Display an inspiring quote');
Schedule::command('app:update-departed-flights')->hourly()->runInBackground(); Schedule::command('app:update-departed-flights')->hourly()->runInBackground();
Schedule::command('app:flight-feed-update')->everyMinute()->runInBackground();