Skip to content

Commit

Permalink
Merge pull request #128 from Facts-and-Files/feat/userItems
Browse files Browse the repository at this point in the history
feat: user items endpoint with latest edited items
  • Loading branch information
trenc authored Nov 27, 2024
2 parents 8ec175e + 9f334ba commit 6afd5aa
Show file tree
Hide file tree
Showing 17 changed files with 576 additions and 55 deletions.
123 changes: 123 additions & 0 deletions src/app/Http/Controllers/UserItemsController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
<?php

namespace App\Http\Controllers;

use App\Http\Controllers\ResponseController;
use App\Http\Resources\UserItemsResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

class UserItemsController extends ResponseController
{
public function index(Request $request, int $id): JsonResponse
{
try {
$queries = $request->query();

// set defaults
$queries['limit'] = intval($queries['limit'] ?? 9);
$queries['page'] = intval($queries['page'] ?? 1);
$queries['threshold'] = intval($queries['threshold'] ?? 500);

$data = DB::table('Score as s')
->join('Item as i', 's.ItemId', '=', 'i.ItemId')
->join('Story as st', 'i.StoryId', '=', 'st.StoryId')
->join('Project as p', 'st.ProjectId', '=', 'p.ProjectId')
->join('ScoreType as stype', 's.ScoreTypeId', '=', 'stype.ScoreTypeId')
->join('CompletionStatus as cs', 'i.CompletionStatusId', '=', 'cs.CompletionStatusId')
->select(
'p.Name as ProjectName',
'i.ItemId',
'i.Title AS ItemTitle',
'i.ImageLink AS ItemImageLink',
'cs.Name AS CompletionStatus',
DB::raw('MAX(s.Timestamp) AS LastEdit'),
'stype.Name AS ScoreType',
DB::raw('SUM(s.Amount) AS Amount')
)
->where('s.UserId', $id)
->groupBy('p.Name', 'i.ItemId', 's.ScoreTypeId')
->orderBy('p.Name')
->orderBy('LastEdit', 'desc')
->limit($queries['threshold'])
->get();

$grouped = $this->groupCollection($queries, $data);

$collection = UserItemsResource::collection($grouped);

return $this->sendResponseWithMeta($collection, 'Items fetched.');
} catch(\Exception $exception) {
return $this->sendError('Invalid data', $exception->getMessage(), 400);
}
}

private function groupCollection(array $queries, Collection $data): array
{
$limit = $queries['limit'];
$page = $queries['page'];
$offset = $limit * ($page - 1);
$threshold = $queries['threshold'];

$this->meta = [
'limit' => $limit,
'currentPage' => $page,
'threshold' => $threshold,
];

$groupedData = [];

foreach ($data as $row) {
$projectName = $row->ProjectName;
$itemId = $row->ItemId;
$itemTitle = $row->ItemTitle;
$itemImageLink = $row->ItemImageLink;
$itemLastEdit = $row->LastEdit;
$completionStatus = $row->CompletionStatus;
$scoreType = $row->ScoreType;

// initialize project group if it doesn't exist
if (!isset($groupedData[$projectName])) {
$groupedData[$projectName] = [
'ProjectName' => $projectName,
'Items' => [],
];
}

// initialize item group within the project if it doesn't exist
if (!isset($groupedData[$projectName]['Items'][$itemId])) {
$groupedData[$projectName]['Items'][$itemId] = [
'ItemId' => (int) $itemId,
'ItemTitle' => $itemTitle ?? '',
'ItemImageLink' => $itemImageLink,
'CompletionStatus' => $completionStatus,
'LastEdit' => $itemLastEdit,
'Scores' => [],
];
}

// add score details to the item's scores
$groupedData[$projectName]['Items'][$itemId]['Scores'][] = [
'ScoreType' => $scoreType,
'Amount' => (int) $row->Amount,
];
}

$groupedData = $this->limitAndOffsetItems($groupedData, $offset, $limit);

return array_values($groupedData);
}

private function limitAndOffsetItems(array $data, int $offset, int $limit): array
{
foreach ($data as $key => $project) {
if (isset($project['Items']) && is_array($project['Items'])) {
$data[$key]['Items'] = array_slice($project['Items'], $offset, $limit);
}
}

return $data;
}
}
13 changes: 13 additions & 0 deletions src/app/Http/Resources/UserItemsResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class UserItemsResource extends JsonResource
{
public function toArray($request): array
{
return parent::toArray($request);
}
}
2 changes: 1 addition & 1 deletion src/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"doctrine/dbal": "^3.9",
"fruitcake/laravel-cors": "^2.0",
"guzzlehttp/guzzle": "^7.0.1",
"laravel/framework": "^9.0",
"laravel/framework": "^9.52",
"laravel/sanctum": "^2.14",
"laravel/tinker": "^2.5",
"nesbot/carbon": "^2.72"
Expand Down
Loading

0 comments on commit 6afd5aa

Please sign in to comment.