diff --git a/index.php b/index.php index 2f928bc..16f500f 100644 --- a/index.php +++ b/index.php @@ -5,6 +5,7 @@ include_once 'vendor/autoload.php'; use Krzysiej\RyobiCrawler\Controller\CategoryController; use Krzysiej\RyobiCrawler\Controller\IndexController; use Krzysiej\RyobiCrawler\Controller\ProductController; +use Krzysiej\RyobiCrawler\Controller\PromosController; use Krzysiej\RyobiCrawler\Controller\SearchController; use Krzysiej\RyobiCrawler\Controller\StarController; use Symfony\Component\Routing\Matcher\UrlMatcher; @@ -15,10 +16,11 @@ use Symfony\Component\Routing\RouteCollection; if (!file_exists('database.sqlite')) { exit('Database file database.sqlite missing. Run docker compose
docker compose exec php-app php index.php app:migrate
to create it.'); } -$productRoute = new Route('/product/{product_id}', ['_controller' => ProductController::class], ['product_id' => '\d+']); +$productRoute = new Route('/product/{product_id<\d+>}', ['_controller' => ProductController::class]); $searchRoute = new Route('/?search={search_term}', ['_controller' => SearchController::class]); $categoryRoute = new Route('/category/{category_name}', ['_controller' => CategoryController::class]); $starRoute = new Route('/star/{product_id}', ['_controller' => StarController::class]); +$promosRoute = new Route('/promos', ['_controller' => PromosController::class]); $indexRoute = new Route('/', ['_controller' => IndexController::class]); $routes = new RouteCollection(); @@ -26,6 +28,7 @@ $routes->add('product_show', $productRoute); $routes->add('search_show', $searchRoute); $routes->add('category_show', $categoryRoute); $routes->add('start_show', $starRoute); +$routes->add('promos_show', $promosRoute); $routes->add('index_show', $indexRoute); $context = new RequestContext(); @@ -40,6 +43,7 @@ match ($parameters['_controller']) { SearchController::class => (new $parameters['_controller']())($parameters['search_term']), CategoryController::class => (new $parameters['_controller']())($parameters['category_name']), ProductController::class, StarController::class => (new $parameters['_controller']())($parameters['product_id']), + PromosController::class => (new $parameters['_controller']())(), IndexController::class => (new $parameters['_controller']())(), default => throw new Exception('Route not found') }; diff --git a/src/Controller/ProductController.php b/src/Controller/ProductController.php index 32189ba..5a36f49 100644 --- a/src/Controller/ProductController.php +++ b/src/Controller/ProductController.php @@ -2,17 +2,31 @@ namespace Krzysiej\RyobiCrawler\Controller; +use Illuminate\Support\ItemNotFoundException; use Krzysiej\RyobiCrawler\Models\Product; +use Twig\Error\LoaderError; +use Twig\Error\RuntimeError; +use Twig\Error\SyntaxError; final class ProductController extends BaseController { + /** + * @throws SyntaxError + * @throws RuntimeError + * @throws LoaderError + */ public function __invoke(int $productId): void { $product = Product::with([ 'price' => fn($query) => $query->orderBy('created_at', 'desc') ])->find($productId); + + if(null === $product) { + throw new ItemNotFoundException('Product not found'); + } + $priceList = $product->price()->pluck('price')->implode(','); $priceDates = $product->price()->pluck('created_at')->map(fn($date) => $date->format('Y-m-d'))->implode("','"); - $this->twig->display('product.html.twig', ['product' => $product ?? [], 'price_list' => $priceList, 'price_dates' => $priceDates]); + $this->twig->display('product.html.twig', ['product' => $product, 'price_list' => $priceList, 'price_dates' => $priceDates]); } } diff --git a/src/Controller/PromosController.php b/src/Controller/PromosController.php new file mode 100644 index 0000000..cdba55d --- /dev/null +++ b/src/Controller/PromosController.php @@ -0,0 +1,15 @@ + $query->whereColumn('price', '<', 'productStandardPrice'))->with(['currentPrice'])->get(); + $this->twig->display('productList.html.twig', ['products' => $products]); + } +} diff --git a/src/Models/Product.php b/src/Models/Product.php index 1fdc49b..3ea318b 100644 --- a/src/Models/Product.php +++ b/src/Models/Product.php @@ -5,6 +5,7 @@ namespace Krzysiej\RyobiCrawler\Models; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\HasOne; /** * @property integer $skuID @@ -28,6 +29,11 @@ class Product extends Model { return $this->hasMany(Price::class); } + + public function currentPrice(): HasOne + { + return $this->hasOne(Price::class)->latestOfMany('created_at'); + } public function stock(): HasMany { return $this->hasMany(Stock::class); diff --git a/src/templates/productList.html.twig b/src/templates/productList.html.twig index 5781bb9..fc4842d 100644 --- a/src/templates/productList.html.twig +++ b/src/templates/productList.html.twig @@ -2,6 +2,17 @@ {% block content %} + + + + + + + + + + + {% for product in products %} diff --git a/src/templates/template.html.twig b/src/templates/template.html.twig index 540b3d2..4002ad4 100644 --- a/src/templates/template.html.twig +++ b/src/templates/template.html.twig @@ -9,14 +9,26 @@ crossorigin="anonymous"/> -
NameCodeCategoriesPrice
{% if product.starred %}★{% else %} ☆ {% endif %}