feat(reviews): ordenar por recentes/completas, só com foto, cartão com foto grande

A Places API (New) não tem parâmetro de ordenação e devolve no máximo 5
reviews, por isso ordem e filtro aplicam-se a essas 5: relevância (ordem da
Google), mais recentes (publishTime) ou mais completas (texto mais longo), e
opcionalmente só quem tem foto de perfil. Mudar estas opções já não apaga a
cache — só uma nova chave ou Place ID obriga a um novo pedido pago.

Cartão: foto de 84px (ou inicial), nome, data e estrelas grandes em cima;
texto mais pequeno por baixo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
andreandClaude Opus 5.5 committed 2026-09-24 15:46:00 +01:00
1 parent f95c9ebc52
commit 1614bf327b
4 files changed
+101 -37

No files matched your search

+23 -1
View File
@@ -10,6 +10,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$action = (string) ($_POST['action'] ?? '');
if ($action === 'save') {
$before = reviews_config();
// Key: blank keeps the stored one; the "remover" box clears it.
$key = trim((string) ($_POST['google_places_api_key'] ?? ''));
if (!empty($_POST['clear_key'])) {
@@ -21,7 +22,15 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
db_update_setting($pdo, 'google_reviews_min_rating', (string) max(1, min(5, (int) ($_POST['min_rating'] ?? 4))), $uid);
db_update_setting($pdo, 'google_reviews_max', (string) max(1, min(5, (int) ($_POST['max'] ?? 3))), $uid);
db_update_setting($pdo, 'google_reviews_cache_hours', (string) max(1, (int) ($_POST['cache_hours'] ?? 24)), $uid);
reviews_cache_clear(); // new settings → next view fetches fresh
$sort = (string) ($_POST['sort'] ?? 'relevance');
db_update_setting($pdo, 'google_reviews_sort', isset(reviews_sort_options()[$sort]) ? $sort : 'relevance', $uid);
db_update_setting($pdo, 'google_reviews_photo_only', !empty($_POST['photo_only']) ? '1' : '0', $uid);
// Only a new key / place needs a new (billed) fetch; rating, count, sort
// and photo filters are applied to the cached 5 at render time.
// (setting() is cached per request, so compare with what was posted.)
$key_changed = !empty($_POST['clear_key']) || ($key !== '' && $key !== $before['api_key']);
$place_changed = trim((string) ($_POST['google_place_id'] ?? '')) !== $before['place_id'];
if ($key_changed || $place_changed) reviews_cache_clear();
session()->setFlashdata('success', 'Definições guardadas.');
header('Location: ' . base_url('views/admin/reviews/index.php'));
exit;
@@ -97,6 +106,19 @@ include __DIR__ . '/../../../includes/header.php';
<input type="number" class="form-control" name="cache_hours" min="1" value="<?= $cfg['cache_hours'] ?>">
<div class="form-text">Cada atualização é um pedido pago à Google.</div>
</div>
<div class="col-md-6">
<label class="form-label">Ordenar por</label>
<select class="form-select" name="sort">
<?php foreach (reviews_sort_options() as $k => $label): ?><option value="<?= $k ?>" <?= $cfg['sort'] === $k ? 'selected' : '' ?>><?= $label ?></option><?php endforeach; ?>
</select>
</div>
<div class="col-md-6 d-flex align-items-end">
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" name="photo_only" id="photo_only" value="1" <?= $cfg['photo_only'] ? 'checked' : '' ?>>
<label class="form-check-label" for="photo_only">Só pessoas com foto de perfil</label>
</div>
</div>
<div class="col-12"><div class="form-text mt-0">A Google não permite pedir reviews ordenadas nem mais do que 5: filtros e ordem aplicam-se às 5 que ela devolve. «Mais úteis» não existe na API — «Mais completas» é a aproximação.</div></div>
</div>
<button class="btn btn-primary mt-3">Guardar</button>
</form>