diff --git a/app/Domain/Trip/Jobs/PostTripJob.php b/app/Domain/Trip/Jobs/PostTripJob.php index 89eea467..d8048f9d 100644 --- a/app/Domain/Trip/Jobs/PostTripJob.php +++ b/app/Domain/Trip/Jobs/PostTripJob.php @@ -18,13 +18,20 @@ class PostTripJob implements ShouldQueue use SerializesModels; - public function handle(Trip $trip) + public Trip $trip; + public function __construct(Trip $trip) { - $this->processTrip($trip); + $this->trip = $trip; + } + - $this->processProfiles($trip); + public function handle() + { + $this->processTrip($this->trip); - $this->processEvents($trip); + $this->processProfiles($this->trip); + + $this->processEvents($this->trip); } private function processTrip(Trip $trip): void @@ -33,7 +40,6 @@ private function processTrip(Trip $trip): void $avrageSpeed = $this->getAverageSpeed($trip); $distance = $duration * $avrageSpeed / 3600; - $trip->update([ 'distance' => $distance ]); diff --git a/app/UserInterface/Domain/Homepage/Controllers/Main.php b/app/UserInterface/Domain/Homepage/Controllers/Main.php index ac5d1701..02611297 100644 --- a/app/UserInterface/Domain/Homepage/Controllers/Main.php +++ b/app/UserInterface/Domain/Homepage/Controllers/Main.php @@ -2,13 +2,18 @@ namespace App\UserInterface\Domain\Homepage\Controllers; +use App\Domain\Device\Model\Device; use App\Domain\Shared\Interface\BreadCrumbInterface; use App\Domain\Shared\ValueObject\BreadCrumbValueObject; use App\Domain\Shared\ValueObject\RouteValueObject; +use App\Domain\Trip\Jobs\PostTripJob; +use App\Domain\Trip\Model\Trip; +use App\Domain\Trip\Model\TripEvent; use App\Helpers\View\Abstract\AbstractViewController; use App\Helpers\View\ValueObject\ButtonValueObject; use App\Helpers\View\ValueObject\PageHeaderValueOject; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Auth; class Main extends AbstractViewController implements BreadCrumbInterface { @@ -34,10 +39,7 @@ protected function pageHeader(): PageHeaderValueOject /** * @inheritdoc */ - protected function appendViewData(Request $request): array - { - return []; - } + public function getBreadCrumb(Request $request): BreadCrumbValueObject { @@ -46,4 +48,40 @@ public function getBreadCrumb(Request $request): BreadCrumbValueObject route: new RouteValueObject('homepage') ); } + + public function get_stats() + { + + $data['weekly'] = $this->get_weekly_review(); + + return response()->json(['stats' => $data]); + } + + public function get_weekly_review() + { + $allSpeeds = []; + $trip = Trip::whereUserId(Auth::id())->get(); + foreach ($trip as $t) { + $allSpeeds[] = $t->data()->get()->avg('speed'); + } + $sumspeed = array_sum($allSpeeds); + if (count($allSpeeds) == 0) { + $data['avg_speed'] = "N/A"; + return $data; + } + $avgspeed = $sumspeed / count($allSpeeds); + $rounded = round($avgspeed); + $data['avg_speed'] = $rounded; + return $data; + } + + public function get_recent_trips() + { + } + + protected function appendViewData(Request $request): array + { + $data['device'] = Device::whereUserId(Auth::id())->orderBy('created_at', 'desc')->first(); + return $data; + } } diff --git a/app/UserInterface/Domain/Homepage/Resources/sass/_homepage 2.scss b/app/UserInterface/Domain/Homepage/Resources/sass/_homepage 2.scss deleted file mode 100644 index 1d8a2418..00000000 --- a/app/UserInterface/Domain/Homepage/Resources/sass/_homepage 2.scss +++ /dev/null @@ -1,3 +0,0 @@ -body { - display: none; -} diff --git a/app/UserInterface/Domain/Homepage/Resources/sass/_homepage 3.scss b/app/UserInterface/Domain/Homepage/Resources/sass/_homepage 3.scss deleted file mode 100644 index 1d8a2418..00000000 --- a/app/UserInterface/Domain/Homepage/Resources/sass/_homepage 3.scss +++ /dev/null @@ -1,3 +0,0 @@ -body { - display: none; -} diff --git a/app/UserInterface/Domain/Homepage/Resources/sass/_homepage.scss b/app/UserInterface/Domain/Homepage/Resources/sass/_homepage.scss index 8112993c..d0bae564 100644 --- a/app/UserInterface/Domain/Homepage/Resources/sass/_homepage.scss +++ b/app/UserInterface/Domain/Homepage/Resources/sass/_homepage.scss @@ -1,5 +1,5 @@ .homepage-under-construction { - margin-top: 7.5rem; + margin-top: 0.25rem; display: flex; justify-content: center; flex-direction: column; @@ -18,6 +18,31 @@ } img { - width: 400px; + width: 25rem; } -} + + + .recent { + height: 5rem; + border-radius: 0.625rem; + background-color: #ffffff; + padding: 0.9375rem; + color: #000000; + display: flex; + cursor: pointer; + margin-bottom: 1rem; + box-shadow: rgba(149, 157, 165, 0.2) 0px 2px 2.5px; + } + + .review { + height: 11rem; + border-radius: 0.625rem; + background-color: #ffffff; + padding: 0.9375rem; + color: #000000; + display: flex; + cursor: pointer; + margin-bottom: 1rem; + box-shadow: rgba(149, 157, 165, 0.2) 0px 2px 2.5px; + } +} \ No newline at end of file diff --git a/app/UserInterface/Domain/Homepage/Resources/sass/_recent_device.scss b/app/UserInterface/Domain/Homepage/Resources/sass/_recent_device.scss new file mode 100644 index 00000000..7cb7fc74 --- /dev/null +++ b/app/UserInterface/Domain/Homepage/Resources/sass/_recent_device.scss @@ -0,0 +1,88 @@ +#recent-device-wrapper { + padding: 1rem 2rem; + min-width: 100%; + justify-content: center; + align-items: center; + border-radius: 0.625rem; + background-color: #ffffff; + color: #000000; + cursor: pointer; + margin-bottom: 1rem; + box-shadow: rgba(149, 157, 165, 0.2) 0px 2px 2.5px; + + + + #recent-device-header { + width: 100%; + + .card { + padding: 2rem 2rem 2rem 2rem; + } + + .icon { + display: flex; + justify-content: center; + align-items: center; + background-color: var(--color-gray-100); + border-radius: 10%; + padding: 1rem; + + i { + font-size: 3rem; + padding: 0.5rem 0.5rem; + color: var(--color-tertiary-color); + } + } + + .details { + padding: 0 0.9rem; + + .name { + margin-top: 1rem; + margin-left: 0.5rem; + + h3 { + font-size: 2rem; + font-weight: 600; + margin: 0; + } + + p { + font-size: 1rem; + margin: 0; + color: var(--color-gray-500); + } + } + + .badges { + margin-top: 0.5rem; + + .badge { + border: 1px dashed var(--color-gray-300); + padding: 0.5rem 1rem; + border-radius: .475rem !important; + min-width: 125px; + margin: 0.5rem 0; + color: black; + text-align: left; + font-size: 1rem; + + .badge-value { + i { + margin-right: 0.5rem; + } + + font-size: 1.25rem; + } + + .badge-label { + font-weight: 200; + margin: 0; + margin-top: 0.3rem; + color: var(--color-gray-500); + } + } + } + } + } +} \ No newline at end of file diff --git a/app/UserInterface/Domain/Homepage/Resources/sass/_recent_trip.scss b/app/UserInterface/Domain/Homepage/Resources/sass/_recent_trip.scss new file mode 100644 index 00000000..5d5e1e40 --- /dev/null +++ b/app/UserInterface/Domain/Homepage/Resources/sass/_recent_trip.scss @@ -0,0 +1,98 @@ +#recent_trip_wrapper { + .page-item { + &:not(#datatable_previous, #datatable_next) { + a { + background-color: var(--color-secondary-color); + border-color: var(--color-secondary-color); + + &:hover { + background-color: var(--color-secondary-color-hover); + border-color: var(--color-secondary-color-hover); + } + } + } + + } +} + +.dt-recent-trip-wrapper { + display: inline-block; + background-color: var(--color-tertiary-color); + color: white; + border-radius: 50%; + padding: 0.5em; + font-size: 1.25em; + font-weight: bold; + width: 2.8em; + height: 2.8em; + + .number { + display: flex; + justify-content: center; + align-items: center; + height: 100%; + font-size: 0.75em; + } +} + +.r-type-inline-d { + font-size: 1.5rem; +} + +.r-type-inline-l { + color: grey; + text-overflow: ellipsis; +} + +.trip-review-container { + max-height: 125px; + height: 125px; + display: flex; + justify-content: space-evenly; + padding-left: 1rem; + flex-direction: column; + + .trip-review { + display: flex; + align-items: center; + margin-top: 0.25rem; + + &-title-wrapper { + display: flex; + justify-content: center; + width: 100%; + flex-direction: column; + + + .trip-review-title { + font-size: 1.25rem; + font-weight: 500; + } + + .trip-review-unit { + font-size: 0.75rem; + font-weight: 400; + color: var(--color-gray-500); + } + } + + &-value-wrapper { + width: 70px; + height: 35px; + margin-right: 1rem; + display: flex; + justify-content: center; + align-items: center; + background-color: var(--color-tertiary-color); + border-radius: 0.25rem; + + + .trip-review-value { + margin-top: 3px; + font-size: 1.25rem; + font-weight: 700; + color: white; + } + } + } +} \ No newline at end of file diff --git a/app/UserInterface/Domain/Homepage/Resources/views/homepage.blade.php b/app/UserInterface/Domain/Homepage/Resources/views/homepage.blade.php index 03aac360..1213a7aa 100644 --- a/app/UserInterface/Domain/Homepage/Resources/views/homepage.blade.php +++ b/app/UserInterface/Domain/Homepage/Resources/views/homepage.blade.php @@ -2,18 +2,373 @@ @section('head') @vite('app/UserInterface/Domain/Homepage/Resources/sass/_homepage.scss') + @vite('app/UserInterface/Domain/Homepage/Resources/sass/_recent_device.scss') + @vite('app/UserInterface/Domain/Homepage/Resources/sass/_recent_trip.scss') @endsection @section('content')
-
- Under Construction -
+
+
+
+

Recent Device

+
+
+
+
+ +
+
+
+
+

{{$device->name}}

+

{{$device->getLastActiveFormatted()}}

+
+
+
+
+ + {{$device->type->getLabel()}} +
+
+ Device type +
+
+
+
+ + {{ $device->trips()->count() }} +
+
+ Total trips +
+
+
+
+ + {{$device->getTotalKilometers()}} +
+
+ Total KM's +
+
+
+
+
+
+ + +
+
+ +
+
+
+
+

Weekly Review

+
+
+
+
+
Speed
+
+
+ + + + +
+
+ Average + km/h +
+
+
+
+
+
+
+
+
Gear
+
+
+ 01 +
+
+ Excpected Changes +
+
+
+
+ 00 +
+
+ Changes +
+
+
+
+
+
+ +
+
+
+
+
Brake
+
+
+ 12 +
+
+ Stop short +
+
+
+
+ 07 +
+
+ Inefficient +
+
+
+
+ 04 +
+
+ Perfect +
+
+
+
+
+
+
+
+
Steering
+
+
+ 01 +
+
+ Wrong Steering +
+
+
+
+ 00 +
+
+ Inefficient +
+
+
+
+ 00 +
+
+ Efficient +
+
+
+
+
+
+
-
-

- This page is under construction. Please check back later. -

+
+

Recent Trips

+
+
+
+ +
+
+ #0001 +
+
+ Trip #0001 + Device: Test +
+
+ 12-01-2024 + Date +
+ + +
+ 08:39 - 12:00 + Time +
+ + +
+ 100 km + Distance +
+ + +
+ 6.0 + Score +
+ + + + + +
+ + +
+
+ +
+
+ #0002 +
+
+ Trip #0002 + Device: Test +
+
+ 12-01-2024 + Date +
+ + +
+ 08:39 - 12:00 + Time +
+ + +
+ 100 km + Distance +
+ + +
+ 6.0 + Score +
+ + + + + +
+ + +
+
+ +
+
+ #0003 +
+
+ Trip #0003 + Device: Test +
+
+ 12-01-2024 + Date +
+ + +
+ 08:39 - 12:00 + Time +
+ + +
+ 100 km + Distance +
+ + +
+ 6.0 + Score +
+ + + + + +
+ + + +
+
+ +
+
+ #0004 +
+
+ Trip #0004 + Device: Test +
+
+ 12-01-2024 + Date +
+ + +
+ 08:39 - 12:00 + Time +
+ + +
+ 100 km + Distance +
+ + +
+ 6.0 + Score +
+ + + + + +
+ + +
+
+
+
+
+ +
+ + + + @endsection diff --git a/app/UserInterface/Domain/Homepage/Routes/web.php b/app/UserInterface/Domain/Homepage/Routes/web.php index 59e4f219..3c5ade80 100644 --- a/app/UserInterface/Domain/Homepage/Routes/web.php +++ b/app/UserInterface/Domain/Homepage/Routes/web.php @@ -17,5 +17,6 @@ Route::middleware(['auth', 'verified'])->group(function () { Route::get('/', [Main::class, 'run'])->name('homepage'); + Route::get("/stats", [Main::class, 'get_stats'])->name("stats"); }); diff --git a/app/UserInterface/Domain/Trip/Controllers/ApiTripController.php b/app/UserInterface/Domain/Trip/Controllers/ApiTripController.php index a41db398..ff916ede 100644 --- a/app/UserInterface/Domain/Trip/Controllers/ApiTripController.php +++ b/app/UserInterface/Domain/Trip/Controllers/ApiTripController.php @@ -13,6 +13,7 @@ use App\UserInterface\Domain\Shared\Responses\ApiEloquentSucessResponse; use Carbon\Carbon; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Validator; class ApiTripController extends Controller @@ -50,11 +51,12 @@ public function update(Request $request, string $id): ApiEloquentSucessResponse if (isset($data['state']) && $data['state'] === TripStateEnum::FINISHED->value) { $data['end_time'] = Carbon::now(); + $trip->update($data); PostTripJob::dispatch($trip); } - $trip->update($data); + return new ApiEloquentSucessResponse($trip); } @@ -83,20 +85,25 @@ public function createEvents(Request $request, string $id): ApiEloquentSucessRes $eventData = json_decode($eventData, true) ?? []; } + if (!is_array($eventData)) { $eventData = []; } $requiredEventdata = TripEventEnum::from($eventType)->requiredDataField(); - $validator = Validator::make($eventData, array_combine($requiredEventdata, array_fill(0, count($requiredEventdata), 'required'))); + $newEventData = json_decode($eventData[0], true); + + + $validator = Validator::make($newEventData, array_combine($requiredEventdata, array_fill(0, count($requiredEventdata), 'required'))); if ($validator->fails()) { + throw new ApiValidationException($validator); } $trip->events()->create([ 'type' => $eventType, 'timestamp' => $timestamp, - 'data' => $eventData, + 'data' => $newEventData, ]); } diff --git a/app/UserInterface/Domain/Trip/Controllers/TripShowController.php b/app/UserInterface/Domain/Trip/Controllers/TripShowController.php index 9f95d4b5..f96b899c 100644 --- a/app/UserInterface/Domain/Trip/Controllers/TripShowController.php +++ b/app/UserInterface/Domain/Trip/Controllers/TripShowController.php @@ -48,7 +48,7 @@ protected function pageHeader(): PageHeaderValueOject protected function appendViewData(Request $request): array { - $psot = new PostTripJob(); + $psot = new PostTripJob($this->trip); $psot->handle($this->trip); return [ 'trip' => $this->trip, diff --git a/composer.bat b/composer.bat new file mode 100644 index 00000000..9748644e --- /dev/null +++ b/composer.bat @@ -0,0 +1 @@ +@php "%~dp0composer.phar" %* diff --git a/composer.phar b/composer.phar new file mode 100644 index 00000000..4723b1b3 Binary files /dev/null and b/composer.phar differ diff --git a/public/build/assets/_homepage 2-c5f9c697.css b/public/build/assets/_homepage 2-c5f9c697.css deleted file mode 100644 index 3e08d141..00000000 --- a/public/build/assets/_homepage 2-c5f9c697.css +++ /dev/null @@ -1 +0,0 @@ -body{display:none} diff --git a/public/build/assets/_homepage-09252892.css b/public/build/assets/_homepage-09252892.css new file mode 100644 index 00000000..d85db293 --- /dev/null +++ b/public/build/assets/_homepage-09252892.css @@ -0,0 +1 @@ +.homepage-under-construction{margin-top:.25rem;display:flex;justify-content:center;flex-direction:column;align-items:center}.homepage-under-construction_title{font-size:4rem;font-weight:700;margin-bottom:1rem}.homepage-under-construction_text{font-size:1.5rem;font-weight:400;margin-bottom:1rem}.homepage-under-construction img{width:25rem}.homepage-under-construction .recent{height:5rem;border-radius:.625rem;background-color:#fff;padding:.9375rem;color:#000;display:flex;cursor:pointer;margin-bottom:1rem;box-shadow:#959da533 0 2px 2.5px}.homepage-under-construction .review{height:11rem;border-radius:.625rem;background-color:#fff;padding:.9375rem;color:#000;display:flex;cursor:pointer;margin-bottom:1rem;box-shadow:#959da533 0 2px 2.5px} diff --git a/public/build/assets/_homepage-ed0cff5d.css b/public/build/assets/_homepage-ed0cff5d.css deleted file mode 100644 index 1556f144..00000000 --- a/public/build/assets/_homepage-ed0cff5d.css +++ /dev/null @@ -1 +0,0 @@ -.homepage-under-construction{margin-top:7.5rem;display:flex;justify-content:center;flex-direction:column;align-items:center}.homepage-under-construction_title{font-size:4rem;font-weight:700;margin-bottom:1rem}.homepage-under-construction_text{font-size:1.5rem;font-weight:400;margin-bottom:1rem}.homepage-under-construction img{width:400px} diff --git a/public/build/assets/_recent_device-b591bfdb.css b/public/build/assets/_recent_device-b591bfdb.css new file mode 100644 index 00000000..e01ef4e1 --- /dev/null +++ b/public/build/assets/_recent_device-b591bfdb.css @@ -0,0 +1 @@ +#recent-device-wrapper{padding:1rem 2rem;min-width:100%;justify-content:center;align-items:center;border-radius:.625rem;background-color:#fff;color:#000;cursor:pointer;margin-bottom:1rem;box-shadow:#959da533 0 2px 2.5px}#recent-device-wrapper #recent-device-header{width:100%}#recent-device-wrapper #recent-device-header .card{padding:2rem}#recent-device-wrapper #recent-device-header .icon{display:flex;justify-content:center;align-items:center;background-color:var(--color-gray-100);border-radius:10%;padding:1rem}#recent-device-wrapper #recent-device-header .icon i{font-size:3rem;padding:.5rem;color:var(--color-tertiary-color)}#recent-device-wrapper #recent-device-header .details{padding:0 .9rem}#recent-device-wrapper #recent-device-header .details .name{margin-top:1rem;margin-left:.5rem}#recent-device-wrapper #recent-device-header .details .name h3{font-size:2rem;font-weight:600;margin:0}#recent-device-wrapper #recent-device-header .details .name p{font-size:1rem;margin:0;color:var(--color-gray-500)}#recent-device-wrapper #recent-device-header .details .badges{margin-top:.5rem}#recent-device-wrapper #recent-device-header .details .badges .badge{border:1px dashed var(--color-gray-300);padding:.5rem 1rem;border-radius:.475rem!important;min-width:125px;margin:.5rem 0;color:#000;text-align:left;font-size:1rem}#recent-device-wrapper #recent-device-header .details .badges .badge .badge-value{font-size:1.25rem}#recent-device-wrapper #recent-device-header .details .badges .badge .badge-value i{margin-right:.5rem}#recent-device-wrapper #recent-device-header .details .badges .badge .badge-label{font-weight:200;margin:0;margin-top:.3rem;color:var(--color-gray-500)} diff --git a/public/build/assets/_recent_trip-90e9616b.css b/public/build/assets/_recent_trip-90e9616b.css new file mode 100644 index 00000000..46b37ebd --- /dev/null +++ b/public/build/assets/_recent_trip-90e9616b.css @@ -0,0 +1 @@ +#recent_trip_wrapper .page-item:not(#datatable_previous,#datatable_next) a{background-color:var(--color-secondary-color);border-color:var(--color-secondary-color)}#recent_trip_wrapper .page-item:not(#datatable_previous,#datatable_next) a:hover{background-color:var(--color-secondary-color-hover);border-color:var(--color-secondary-color-hover)}.dt-recent-trip-wrapper{display:inline-block;background-color:var(--color-tertiary-color);color:#fff;border-radius:50%;padding:.5em;font-size:1.25em;font-weight:700;width:2.8em;height:2.8em}.dt-recent-trip-wrapper .number{display:flex;justify-content:center;align-items:center;height:100%;font-size:.75em}.r-type-inline-d{font-size:1.5rem}.r-type-inline-l{color:gray;text-overflow:ellipsis}.trip-review-container{max-height:125px;height:125px;display:flex;justify-content:space-evenly;padding-left:1rem;flex-direction:column}.trip-review-container .trip-review{display:flex;align-items:center;margin-top:.25rem}.trip-review-container .trip-review-title-wrapper{display:flex;justify-content:center;width:100%;flex-direction:column}.trip-review-container .trip-review-title-wrapper .trip-review-title{font-size:1.25rem;font-weight:500}.trip-review-container .trip-review-title-wrapper .trip-review-unit{font-size:.75rem;font-weight:400;color:var(--color-gray-500)}.trip-review-container .trip-review-value-wrapper{width:70px;height:35px;margin-right:1rem;display:flex;justify-content:center;align-items:center;background-color:var(--color-tertiary-color);border-radius:.25rem}.trip-review-container .trip-review-value-wrapper .trip-review-value{margin-top:3px;font-size:1.25rem;font-weight:700;color:#fff} diff --git a/public/build/manifest.json b/public/build/manifest.json index 07ed7912..ec6cf43d 100644 --- a/public/build/manifest.json +++ b/public/build/manifest.json @@ -19,20 +19,20 @@ "isEntry": true, "src": "app/UserInterface/Domain/Homepage/Resources/js/homepage.js" }, - "app/UserInterface/Domain/Homepage/Resources/sass/_homepage 2.scss": { - "file": "assets/_homepage 2-c5f9c697.css", + "app/UserInterface/Domain/Homepage/Resources/sass/_homepage.scss": { + "file": "assets/_homepage-09252892.css", "isEntry": true, - "src": "app/UserInterface/Domain/Homepage/Resources/sass/_homepage 3.scss" + "src": "app/UserInterface/Domain/Homepage/Resources/sass/_homepage.scss" }, - "app/UserInterface/Domain/Homepage/Resources/sass/_homepage 3.scss": { - "file": "assets/_homepage 2-c5f9c697.css", + "app/UserInterface/Domain/Homepage/Resources/sass/_recent_device.scss": { + "file": "assets/_recent_device-b591bfdb.css", "isEntry": true, - "src": "app/UserInterface/Domain/Homepage/Resources/sass/_homepage 3.scss" + "src": "app/UserInterface/Domain/Homepage/Resources/sass/_recent_device.scss" }, - "app/UserInterface/Domain/Homepage/Resources/sass/_homepage.scss": { - "file": "assets/_homepage-ed0cff5d.css", + "app/UserInterface/Domain/Homepage/Resources/sass/_recent_trip.scss": { + "file": "assets/_recent_trip-90e9616b.css", "isEntry": true, - "src": "app/UserInterface/Domain/Homepage/Resources/sass/_homepage.scss" + "src": "app/UserInterface/Domain/Homepage/Resources/sass/_recent_trip.scss" }, "app/UserInterface/Domain/Trip/Resources/sass/_trips.scss": { "file": "assets/_trips-fe4fedc2.css",