fix: zamijeni auth polling health endpointom
Some checks failed
ERP CI/CD Pipeline / test (push) Has been cancelled
ERP CI/CD Pipeline / Deploy (server git pull + compose) (push) Has been cancelled

Dodaje backend /api/health/ endpoint i prebacuje frontend heartbeat sa /api/token/ OPTIONS na /api/health/ GET kako bi se izbjeglo periodicko gadanje auth rute.

Dodaje TTL cache za clientStore (lastFetchedAt + force opcija) kako bi se smanjili redundantni crm/clients pozivi pri navigaciji.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
mariomitte
2026-07-19 16:27:20 +02:00
parent bbdd02c9e9
commit 8485431180
3 changed files with 26 additions and 5 deletions

View File

@@ -2,14 +2,19 @@
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.http import JsonResponse
from django.urls import path, include
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
)
def api_health(_request):
return JsonResponse({'status': 'ok'})
urlpatterns = [
path('admin/', admin.site.urls),
path('api/health/', api_health, name='api_health'),
# Uključujemo rute iz modula (svaki modul ima svoj urls.py)
path('api/crm/', include('modules.crm.urls')),

View File

@@ -8,12 +8,25 @@ export const $clients = atom([]);
export const $clientsLoading = atom(false);
export const $clientsError = atom(null);
export async function fetchClients(signal) {
let _lastClientsFetchAt = 0;
const CLIENTS_FETCH_TTL_MS = 30_000; // 30 sekundi
export async function fetchClients(arg) {
const options = (arg && typeof arg === 'object' && !('aborted' in arg))
? arg
: { signal: arg };
const { signal, force = false } = options;
if (!force && $clients.get().length > 0 && Date.now() - _lastClientsFetchAt < CLIENTS_FETCH_TTL_MS) {
return;
}
$clientsLoading.set(true);
$clientsError.set(null);
try {
const data = await api.get('crm/clients/', { signal });
$clients.set(Array.isArray(data) ? data : (data.results ?? []));
_lastClientsFetchAt = Date.now();
} catch (err) {
if (err?.name !== 'AbortError') $clientsError.set(err.message ?? 'Greška');
} finally {
@@ -24,16 +37,19 @@ export async function fetchClients(signal) {
export async function createClient(payload) {
const data = await api.post('crm/clients/', payload);
$clients.set([...$clients.get(), data]);
_lastClientsFetchAt = Date.now();
return data;
}
export async function updateClient(id, payload) {
const data = await api.patch(`crm/clients/${id}/`, payload);
$clients.set($clients.get().map((c) => (c.id === id ? data : c)));
_lastClientsFetchAt = Date.now();
return data;
}
export async function deleteClient(id) {
await api.delete(`crm/clients/${id}/`);
$clients.set($clients.get().filter((c) => c.id !== id));
_lastClientsFetchAt = Date.now();
}

View File

@@ -4,14 +4,14 @@ export const $isOffline = atom(false);
const API_BASE = import.meta.env.PUBLIC_API_URL || 'http://localhost:8001/api/';
// Heartbeat endpoint: OPTIONS /api/token/
// DRF odgovara bez 405 greške i dovoljno je za provjeru dostupnosti backenda.
const HEARTBEAT_URL = new URL('token/', API_BASE).toString();
// Heartbeat endpoint: GET /api/health/
// Time izbjegavamo periodično gađanje auth/token endpointa.
const HEARTBEAT_URL = new URL('health/', API_BASE).toString();
async function provjeriStvarnuVezu() {
try {
const response = await fetch(HEARTBEAT_URL, {
method: 'OPTIONS',
method: 'GET',
cache: 'no-store',
});