Compare commits
2 Commits
feature/fi
...
feature/gi
| Author | SHA1 | Date | |
|---|---|---|---|
| 484a288da1 | |||
| 7e1560c11f |
@@ -1,5 +1,7 @@
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
deploy-job:
|
||||
|
||||
@@ -118,66 +118,6 @@ class Migrate extends Command
|
||||
]
|
||||
);
|
||||
}
|
||||
if (Capsule::schema()->hasTable('countries') && !Country::where('countryName', 'Netherlands')->exists()) {
|
||||
Capsule::table('countries')->insert([
|
||||
'countryName' => 'Netherlands',
|
||||
'productsUrl' => 'https://nl.ryobitools.eu/api/product-listing/get-products',
|
||||
'cultureCode' => 'nl-NL',
|
||||
'currency' => 'EUR',
|
||||
'locale' => 'nl',
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]
|
||||
);
|
||||
}
|
||||
if (Capsule::schema()->hasTable('countries') && !Country::where('countryName', 'France')->exists()) {
|
||||
Capsule::table('countries')->insert([
|
||||
'countryName' => 'France',
|
||||
'productsUrl' => 'https://fr.ryobitools.eu/api/product-listing/get-products',
|
||||
'cultureCode' => 'fr-FR',
|
||||
'currency' => 'EUR',
|
||||
'locale' => 'fr',
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]
|
||||
);
|
||||
}
|
||||
if (Capsule::schema()->hasTable('countries') && !Country::where('countryName', 'Spain')->exists()) {
|
||||
Capsule::table('countries')->insert([
|
||||
'countryName' => 'Spain',
|
||||
'productsUrl' => 'https://es.ryobitools.eu/api/product-listing/get-products',
|
||||
'cultureCode' => 'es-ES',
|
||||
'currency' => 'EUR',
|
||||
'locale' => 'es',
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]
|
||||
);
|
||||
}
|
||||
if (Capsule::schema()->hasTable('countries') && !Country::where('countryName', 'Poland')->exists()) {
|
||||
$id = Capsule::table('countries')->insertGetId(
|
||||
[
|
||||
'countryName' => 'Poland',
|
||||
'productsUrl' => 'https://pl.ryobitools.eu/api/product-listing/get-products',
|
||||
'cultureCode' => 'pl-PL',
|
||||
'currency' => 'PLN',
|
||||
'locale' => 'pl',
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
}
|
||||
if (Capsule::schema()->hasTable('countries') && !Country::where('countryName', 'UK')->exists()) {
|
||||
Capsule::table('countries')->insert([
|
||||
'countryName' => 'UK',
|
||||
'productsUrl' => 'https://uk.ryobitools.eu/api/product-listing/get-products',
|
||||
'cultureCode' => 'en-GB',
|
||||
'currency' => 'GBP',
|
||||
'locale' => 'uk',
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
if (!Capsule::schema()->hasColumn('products', 'country_id')) {
|
||||
Capsule::schema()->table('products', function (Blueprint $table) use ($id) {
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Krzysiej\RyobiCrawler\Controller;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Krzysiej\RyobiCrawler\Models\Country;
|
||||
use Krzysiej\RyobiCrawler\Models\Product;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
final class CountryController extends BaseController
|
||||
{
|
||||
#[Route('/country/{countryName?}', name: 'app_country')]
|
||||
public function __invoke(?string $countryName): Response
|
||||
{
|
||||
/** @var Product[] $products */
|
||||
$products = Product::with(['price', 'lowestPrice', 'country'])
|
||||
->join('countries', 'countries.id', '=', 'products.country_id')
|
||||
->where('countryName', $countryName)
|
||||
->orderByDesc('starred')
|
||||
->orderByDesc('created_by')
|
||||
->get();
|
||||
|
||||
$country = Country::where('countryName', $countryName)->first();
|
||||
|
||||
return $this->render('productList.html.twig', ['products' => $products, 'listType' => 'country', 'country' => $country, 'countryStats' => $this->countryStats($countryName)]);
|
||||
}
|
||||
|
||||
private function countryStats(string $country): array
|
||||
{
|
||||
$countryProducts = Product::join('countries', 'countries.id', '=', 'products.country_id')
|
||||
->where('countryName', $country);
|
||||
|
||||
$stats = [];
|
||||
$stats['items'] = $countryProducts->get()->count();
|
||||
// $stats['items2'] = $countryProducts->dd();
|
||||
|
||||
return $stats;
|
||||
}
|
||||
}
|
||||
@@ -32,32 +32,6 @@ final class ProductController extends BaseController
|
||||
ksort($stockList);
|
||||
ksort($priceList);
|
||||
|
||||
return $this->render('product.html.twig', [
|
||||
'product' => $product,
|
||||
'price_list' => $this->prepareChartData($priceList),
|
||||
'stock_list' => $this->prepareChartData($stockList),
|
||||
'price_dates' => implode("','", $this->dateRange(array_key_first($priceList), array_key_last($priceList))),
|
||||
]);
|
||||
}
|
||||
#[Route('/product/model/{productModel}', name: 'app_product_model')]
|
||||
public function productModel(string $productModel): Response
|
||||
{
|
||||
|
||||
$product = Product::with([
|
||||
'price' => fn($query) => $query->orderBy('created_at', 'desc'),
|
||||
'stock' => fn($query) => $query->orderBy('created_at', 'desc'),
|
||||
])->where('subTitle', $productModel)->first();
|
||||
|
||||
if (null === $product) {
|
||||
throw $this->createNotFoundException('Product not found');
|
||||
}
|
||||
$priceList = $product->price()->pluck('price', 'created_at')->mapWithKeys(fn($price, $createdAt) => [explode(' ', $createdAt)[0] => $price])->toArray();
|
||||
$stockList = $product->stock()->pluck('stock', 'created_at')->mapWithKeys(fn($stock, $createdAt) => [explode(' ', $createdAt)[0] => $stock])->toArray();
|
||||
|
||||
ksort($stockList);
|
||||
ksort($priceList);
|
||||
|
||||
|
||||
return $this->render('product.html.twig', [
|
||||
'product' => $product,
|
||||
'price_list' => $this->prepareChartData($priceList),
|
||||
|
||||
@@ -20,11 +20,8 @@ final class PromosController extends BaseController
|
||||
|
||||
|
||||
$promos = Product::select($this->database->getConnection()->raw("distinct json_extract(promotions, '$.slug') as slug, json_extract(promotions, '$.tag') as tag"))
|
||||
->addSelect('countries.locale')
|
||||
->whereRaw("json_extract(promotions, '$.tag') is not null")
|
||||
->join('countries', 'products.country_id', '=', 'countries.id')
|
||||
->get()
|
||||
->groupBy('locale');
|
||||
->get();
|
||||
|
||||
return $this->render('productList.html.twig', ['products' => $products, 'listType' => 'promos' . $promo, 'promos' => $promos->toArray()]);
|
||||
}
|
||||
|
||||
@@ -7,13 +7,9 @@ use Krzysiej\RyobiCrawler\Twig\AppExtension;
|
||||
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
|
||||
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
|
||||
use Symfony\Bundle\TwigBundle\TwigBundle;
|
||||
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
|
||||
use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
|
||||
use Twig\Extra\Cache\CacheExtension;
|
||||
use Twig\Extra\Cache\CacheRuntime;
|
||||
use Twig\Extra\TwigExtraBundle\TwigExtraBundle;
|
||||
|
||||
class Kernel extends BaseKernel
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace Krzysiej\RyobiCrawler\Twig;
|
||||
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Krzysiej\RyobiCrawler\Models\Country;
|
||||
use Krzysiej\RyobiCrawler\Models\Price;
|
||||
use Krzysiej\RyobiCrawler\Models\Product;
|
||||
use Krzysiej\RyobiCrawler\Models\Stock;
|
||||
@@ -29,7 +28,6 @@ class AppExtension extends AbstractExtension
|
||||
new TwigFunction('discontinuedCount', [$this, 'discontinuedCount']),
|
||||
new TwigFunction('lowestPriceCount', [$this, 'lowestPriceCount']),
|
||||
new TwigFunction('renderCategoryTree', [$this, 'renderCategoryTree']),
|
||||
new TwigFunction('getCountries', [$this, 'getCountries']),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -68,11 +66,6 @@ class AppExtension extends AbstractExtension
|
||||
->count();
|
||||
}
|
||||
|
||||
public function getCountries(): array
|
||||
{
|
||||
return Country::get()->toArray();
|
||||
}
|
||||
|
||||
public function findByCreatedAtDate(Collection $items, string $date): Stock|Price|null
|
||||
{
|
||||
return $items->first(fn($item) => str_starts_with($item->created_at, $date));
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<td>
|
||||
<a href='{{ path('app_product', {'productId': product.id}) }}'
|
||||
class="text-decoration-none">{{ product.name }}</a>
|
||||
<span class="badge text-bg-light"><a href="{{ path('app_product_model', {'productModel': product.subTitle}) }}"
|
||||
<span class="badge text-bg-light"><a href="{{ path('app_search', {'search': product.subTitle}) }}"
|
||||
class="link-underline link-underline-opacity-0 link-dark">{{ product.subTitle }}</a></span>
|
||||
{% if product.promotions is not null and product.promotions.hasPromotion %}<a
|
||||
href="{{ path('app_promos', {'promo': product.promotions.slug}) }}"><span class="badge bg-info">PROMO: {{ product.promotions.tag }}</span>
|
||||
|
||||
@@ -6,25 +6,11 @@
|
||||
{% endif %}
|
||||
|
||||
{% if listType starts with 'promos' %}
|
||||
<ul class="list-group list-group-flush">
|
||||
{% for locale, promoByLocale in promos %}
|
||||
<li class="list-group-item">
|
||||
<h5 class="d-inline-block"><span class="badge bg-info">{{ locale | upper }}</span></h5>
|
||||
{% for promo in promoByLocale %}
|
||||
<a href="{{ path('app_promos', {'promo': promo.slug}) }}"><span
|
||||
class="badge bg-info">PROMO: {{ promo.tag }} [{{ promo.locale | upper }}]</span></a>
|
||||
{% endfor %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% for promo in promos %}
|
||||
<a href="{{ path('app_promos', {'promo': promo.slug}) }}"><span class="badge bg-info">PROMO: {{ promo.tag }}</span></a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if listType == 'country' and country is not null%}
|
||||
<h2 class="text-muted mt-4 mx-4">{{ country.countryName }}</h2>
|
||||
<h5 class="mx-4 my-0">Currency: {{ country.currency }}</h5>
|
||||
{{ dump(countryStats) }}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if (listType starts with 'category_' and category == null) or not (listType starts with 'category_') or (listType starts with 'category_' and category is not null) %}
|
||||
<div class="table-responsive">
|
||||
@@ -52,24 +38,22 @@
|
||||
<td class="align-middle">
|
||||
<a href='{{ path('app_product', {'productId': product.id}) }}'
|
||||
class="text-decoration-none">{{ product.name }}</a>
|
||||
<br>
|
||||
{% if product.stock > 0 %}
|
||||
<span class="badge text-bg-light">stock: {{ product.stock }}</span>
|
||||
{% else %}
|
||||
<span class="badge text-bg-warning">out of stock</span>
|
||||
{% endif %}
|
||||
{% if product.isDiscontinued() %}
|
||||
<a href="{{ path('app_discontinued') }}"><span class="badge text-bg-secondary" data-bs-toggle="tooltip"
|
||||
data-bs-title="Last update: {{ product.lastSeen }}">is discontinued</span></a>
|
||||
<span class="badge text-bg-secondary" data-bs-toggle="tooltip"
|
||||
data-bs-title="Last update: {{ product.lastSeen }}">is discontinued</span>
|
||||
{% endif %}
|
||||
{% if product.isNew() %}
|
||||
<a href="{{ path('app_new') }}"><span class="badge text-bg-success">is new</span></a>
|
||||
<span class="badge text-bg-success">is new</span>
|
||||
{% endif %}
|
||||
<span class="badge text-bg-light"><a
|
||||
href="{{ path('app_product_model', {'productModel': product.subTitle}) }}"
|
||||
href="{{ path('app_search', {'search': product.subTitle}) }}"
|
||||
class="link-underline link-underline-opacity-0 link-dark">{{ product.subTitle }}</a></span>
|
||||
{% if product.promotions is not null and product.promotions.hasPromotion %}<a href="{{ path('app_promos', {'promo': product.promotions.slug}) }}"><span class="badge bg-info">PROMO: {{ product.promotions.tag }}</span></a>{% endif %}
|
||||
<span class="badge text-bg-light"><a href="{{ path('app_country', {'countryName': product.country.countryName}) }}" class="link-underline link-underline-opacity-0 link-dark">{{ product.country.countryName }}</a></span>
|
||||
</td>
|
||||
<td class="align-middle">
|
||||
<nav aria-label="breadcrumb" style="--bs-breadcrumb-divider: '>';">
|
||||
@@ -89,7 +73,7 @@
|
||||
{{ product.priceLowest | format_currency(product.country.currency, {}, product.country.locale) }}
|
||||
{% else %}
|
||||
{% if product.priceLowest != product.priceCurrent %}{{ product.priceLowest | format_currency(product.country.currency, {}, product.country.locale) }}{% else %}
|
||||
<a href="{{ path('app_lowest_price') }}"><span class="badge bg-info">now lowest</span></a>{% endif %}</td>
|
||||
<span class="badge text-bg-info">now lowest</span>{% endif %}</td>
|
||||
{% endif %}
|
||||
|
||||
<td class="align-middle text-end">{{ product.priceCurrent | format_currency(product.country.currency, {}, product.country.locale) }}</td>
|
||||
|
||||
@@ -33,16 +33,6 @@
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if app.request.pathinfo == path('app_discontinued') %}active shadow-sm bg-body rounded{% endif %}" aria-current="page" href="{{ path('app_discontinued') }}">Discontinued <span class="badge text-bg-secondary">{{ discontinuedCount() }}</span></a>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Countries
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
{% for country in getCountries() %}
|
||||
<li><a class="dropdown-item" href="{{ path('app_country', {'countryName': country.countryName}) }}">{{ country.countryName }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<form class="form-floating d-flex col-lg-6 col-sm-8" role="search" action="{{ path('app_search') }}">
|
||||
|
||||
Reference in New Issue
Block a user