CORS error cleaned
This commit is contained in:
10
001.BACKEND/.dockerignore
Normal file
10
001.BACKEND/.dockerignore
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
venv/
|
||||||
|
.venv/
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
.git/
|
||||||
|
.gitignore
|
||||||
|
db.sqlite3
|
||||||
|
.env
|
||||||
|
staticfiles/
|
||||||
|
media/
|
||||||
50
001.BACKEND/Dockerfile
Normal file
50
001.BACKEND/Dockerfile
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
M python:3.12-slim AS builder
|
||||||
|
|
||||||
|
# Sprječava Python da zapisuje .pyc datoteke na disk
|
||||||
|
ENV PYTHONDONTWRITEBYTECODE=1
|
||||||
|
# Sprječava Python da sprema ispis u međumemoriju (odmah vidiš logove)
|
||||||
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Instalacija sistemskih ovisnosti potrebnih za kompajliranje pojedinih Python paketa
|
||||||
|
# (npr. gcc i libpq-dev ako koristiš PostgreSQL)
|
||||||
|
RUN apt-get update && apt-get install --no-install-recommends -y \
|
||||||
|
build-essential \
|
||||||
|
libpq-dev \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Nadogradnja pip-a i kopiranje requirements datoteke
|
||||||
|
RUN pip install --no-cache-dir --upgrade pip
|
||||||
|
COPY requirements.txt .
|
||||||
|
|
||||||
|
# Instalacija paketa u lokalni direktorij unutar builder faze
|
||||||
|
RUN pip install --no-cache-dir --user -r requirements.txt
|
||||||
|
|
||||||
|
|
||||||
|
# --- 2. FAZA: Pokretanje (Prodajni Runtime) ---
|
||||||
|
FROM python:3.12-slim AS runner
|
||||||
|
|
||||||
|
ENV PYTHONDONTWRITEBYTECODE=1
|
||||||
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
ENV PATH=/root/.local/bin:$PATH
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Ako koristiš PostgreSQL na produkciji, ovdje ti treba samo lagana runtime knjižnica
|
||||||
|
RUN apt-get update && apt-get install --no-install-recommends -y \
|
||||||
|
libpq5 \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Kopiramo instalirane Python pakete iz prve faze
|
||||||
|
COPY --from=builder /root/.local /root/.local
|
||||||
|
# Kopiramo ostatak izvornog koda Django aplikacije
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Otvaramo port 8000 na kojem će slušati Gunicorn
|
||||||
|
EXPOSE 8000
|
||||||
|
|
||||||
|
# Pokretanje aplikacije produkcijskim Gunicorn serverom
|
||||||
|
# Zamijeni "core" s točnim nazivom mape u kojoj ti se nalazi wsgi.py datoteka!
|
||||||
|
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "3", "core.wsgi:application"]
|
||||||
|
|
||||||
@@ -1,13 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
Django settings for core project.
|
Django settings for core project.
|
||||||
|
|
||||||
Generated by 'django-admin startproject' using Django 6.0.5.
|
|
||||||
|
|
||||||
For more information on this file, see
|
|
||||||
https://docs.djangoproject.com/en/6.0/topics/settings/
|
|
||||||
|
|
||||||
For the full list of settings and their values, see
|
|
||||||
https://docs.djangoproject.com/en/6.0/ref/settings/
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@@ -20,16 +12,11 @@ BASE_DIR = Path(__file__).resolve().parent.parent
|
|||||||
|
|
||||||
load_dotenv(BASE_DIR / '.env')
|
load_dotenv(BASE_DIR / '.env')
|
||||||
|
|
||||||
# Quick-start development settings - unsuitable for production
|
|
||||||
# See https://docs.djangoproject.com/en/6.0/howto/deployment/checklist/
|
|
||||||
|
|
||||||
# SECURITY WARNING: keep the secret key used in production secret!
|
|
||||||
SECRET_KEY = os.getenv(
|
SECRET_KEY = os.getenv(
|
||||||
'DJANGO_SECRET_KEY',
|
'DJANGO_SECRET_KEY',
|
||||||
'django-insecure-!228(8gy#3a7l-@_^g1s4bipj&@*+_415+ulx0^-9jw(%ksdvy',
|
'django-insecure-!228(8gy#3a7l-@_^g1s4bipj&@*+_415+ulx0^-9jw(%ksdvy',
|
||||||
)
|
)
|
||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
|
||||||
DEBUG = os.getenv('DJANGO_DEBUG', 'True').lower() in ('1', 'true', 'yes', 'on')
|
DEBUG = os.getenv('DJANGO_DEBUG', 'True').lower() in ('1', 'true', 'yes', 'on')
|
||||||
|
|
||||||
# Custom user model
|
# Custom user model
|
||||||
@@ -42,7 +29,6 @@ ALLOWED_HOSTS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
# Application definition
|
# Application definition
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
'django.contrib.admin',
|
'django.contrib.admin',
|
||||||
'django.contrib.auth',
|
'django.contrib.auth',
|
||||||
@@ -93,10 +79,6 @@ TEMPLATES = [
|
|||||||
|
|
||||||
WSGI_APPLICATION = 'core.wsgi.application'
|
WSGI_APPLICATION = 'core.wsgi.application'
|
||||||
|
|
||||||
|
|
||||||
# Database
|
|
||||||
# https://docs.djangoproject.com/en/6.0/ref/settings/#databases
|
|
||||||
|
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
@@ -104,93 +86,56 @@ DATABASES = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# Password validation
|
|
||||||
# https://docs.djangoproject.com/en/6.0/ref/settings/#auth-password-validators
|
|
||||||
|
|
||||||
AUTH_PASSWORD_VALIDATORS = [
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
{
|
{ 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator' },
|
||||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
{ 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator' },
|
||||||
},
|
{ 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator' },
|
||||||
{
|
{ 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator' },
|
||||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
# Internationalization
|
|
||||||
# https://docs.djangoproject.com/en/6.0/topics/i18n/
|
|
||||||
|
|
||||||
LANGUAGE_CODE = 'en-us'
|
LANGUAGE_CODE = 'en-us'
|
||||||
|
|
||||||
TIME_ZONE = 'Europe/Zagreb'
|
TIME_ZONE = 'Europe/Zagreb'
|
||||||
|
|
||||||
USE_I18N = True
|
USE_I18N = True
|
||||||
|
|
||||||
USE_TZ = True
|
USE_TZ = True
|
||||||
|
|
||||||
|
|
||||||
# Static files (CSS, JavaScript, Images)
|
|
||||||
# https://docs.djangoproject.com/en/6.0/howto/static-files/
|
|
||||||
|
|
||||||
STATIC_URL = 'static/'
|
STATIC_URL = 'static/'
|
||||||
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
|
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
|
||||||
|
|
||||||
|
|
||||||
# Automatski koristi filtriranje na svim API endpointima koji podržavaju filtriranje
|
|
||||||
|
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
# Razvojni način: Svatko može čitati i pisati bez tokena
|
DEFAULT_PERMISSION_CLASSES = [ 'rest_framework.permissions.AllowAny' ]
|
||||||
DEFAULT_PERMISSION_CLASSES = [
|
|
||||||
'rest_framework.permissions.AllowAny',
|
|
||||||
]
|
|
||||||
else:
|
else:
|
||||||
# Produkcijski način: Pristup samo uz ispravan JWT token
|
DEFAULT_PERMISSION_CLASSES = [ 'rest_framework.permissions.IsAuthenticated' ]
|
||||||
DEFAULT_PERMISSION_CLASSES = [
|
|
||||||
'rest_framework.permissions.IsAuthenticated',
|
|
||||||
]
|
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'DEFAULT_FILTER_BACKENDS': [
|
'DEFAULT_FILTER_BACKENDS': [
|
||||||
'django_filters.rest_framework.DjangoFilterBackend'
|
'django_filters.rest_framework.DjangoFilterBackend'
|
||||||
],
|
],
|
||||||
# JWT Autentikacija
|
|
||||||
'DEFAULT_AUTHENTICATION_CLASSES': (
|
'DEFAULT_AUTHENTICATION_CLASSES': (
|
||||||
'rest_framework_simplejwt.authentication.JWTAuthentication',
|
'rest_framework_simplejwt.authentication.JWTAuthentication',
|
||||||
),
|
),
|
||||||
# Postavi da su po defaultu svi API-ji zaključani (samo za prijavljene)
|
|
||||||
'DEFAULT_PERMISSION_CLASSES': DEFAULT_PERMISSION_CLASSES
|
'DEFAULT_PERMISSION_CLASSES': DEFAULT_PERMISSION_CLASSES
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# Podesiti koliko dugo vrijede JWT tokeni (npr. 1 sat za pristup, 30 dana za refresh)
|
|
||||||
SIMPLE_JWT = {
|
SIMPLE_JWT = {
|
||||||
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60),
|
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60),
|
||||||
'REFRESH_TOKEN_LIFETIME': timedelta(days=30),
|
'REFRESH_TOKEN_LIFETIME': timedelta(days=30),
|
||||||
'AUTH_HEADER_TYPES': ('Bearer',),
|
'AUTH_HEADER_TYPES': ('Bearer',),
|
||||||
}
|
}
|
||||||
|
|
||||||
# Media files (npr. slike vozila)
|
|
||||||
|
|
||||||
MEDIA_URL = '/media/'
|
MEDIA_URL = '/media/'
|
||||||
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
|
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
|
||||||
|
|
||||||
|
# CORS POSTAVKE - POPRAVLJENI ZAREZI I FORMALNI ORIGINI
|
||||||
# CORS postavke - dozvoli frontend aplikaciji da komunicira s backendom
|
|
||||||
|
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
CORS_ALLOW_ALL_ORIGINS = True
|
CORS_ALLOW_ALL_ORIGINS = True
|
||||||
else:
|
else:
|
||||||
|
CORS_ALLOW_ALL_ORIGINS = False
|
||||||
CORS_ALLOWED_ORIGINS = [
|
CORS_ALLOWED_ORIGINS = [
|
||||||
"http://localhost:4321", # Ovo je adresa na kojoj će Astro frontend biti dostupan
|
host.strip()
|
||||||
"http://127.0.0.1:4321",
|
for host in os.getenv('DJANGO_CORS_ALLOWED_ORIGINS', '').split(',')
|
||||||
|
if host.strip()
|
||||||
]
|
]
|
||||||
|
|
||||||
CORS_ALLOW_METHODS = [
|
CORS_ALLOW_METHODS = [
|
||||||
"DELETE",
|
"DELETE",
|
||||||
"GET",
|
"GET",
|
||||||
@@ -201,10 +146,19 @@ CORS_ALLOW_METHODS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
CORS_ALLOW_HEADERS = [
|
CORS_ALLOW_HEADERS = [
|
||||||
"accept",
|
'accept',
|
||||||
"authorization",
|
'accept-encoding',
|
||||||
"content-type",
|
'authorization',
|
||||||
"user-agent",
|
'content-type',
|
||||||
"x-csrftoken",
|
'dnt',
|
||||||
"x-requested-with",
|
'origin',
|
||||||
]
|
'user-agent',
|
||||||
|
'x-csrftoken',
|
||||||
|
'x-requested-with',
|
||||||
|
'access-control-request-private-network',
|
||||||
|
]
|
||||||
|
|
||||||
|
# Ako preglednik pošalje PNA preflight zahtjev sa lokalne mreže,
|
||||||
|
# corsheaders će ga s ovim u potpunosti odobriti bez redirecta
|
||||||
|
CORS_ALLOW_PRIVATE_NETWORK = True
|
||||||
|
CORS_PREFLIGHT_MAX_AGE = 86400
|
||||||
|
|||||||
2
001.FRONTEND/.dockerignore
Normal file
2
001.FRONTEND/.dockerignore
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
node_modules
|
||||||
|
.astro
|
||||||
30
001.FRONTEND/Dockerfile
Normal file
30
001.FRONTEND/Dockerfile
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# --- 1. FAZA: Izgradnja (Build) ---
|
||||||
|
FROM node:22-alpine AS builder
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Kopiramo samo datoteke ovisnosti kako bismo iskoristili Docker cache
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
# Kopiramo ostatak izvornog koda i pokrećemo build
|
||||||
|
COPY . .
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# --- 2. FAZA: Pokretanje (Run) ---
|
||||||
|
FROM node:22-alpine AS runner
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Definiramo produkcijsko okruženje
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
ENV HOST=0.0.0.0
|
||||||
|
ENV PORT=4321
|
||||||
|
|
||||||
|
# Kopiramo samo izgrađene datoteke iz prve faze (dist) i potrebne module
|
||||||
|
COPY --from=builder /app/dist ./dist
|
||||||
|
COPY --from=builder /app/node_modules ./node_modules
|
||||||
|
COPY --from=builder /app/package*.json ./
|
||||||
|
|
||||||
|
EXPOSE 4321
|
||||||
|
|
||||||
|
# Pokretanje aplikacije izravno preko Node-a
|
||||||
|
CMD ["node", "./dist/server/entry.mjs"]
|
||||||
@@ -1,25 +1,34 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
import { defineConfig } from 'astro/config';
|
import { defineConfig } from 'astro/config';
|
||||||
|
|
||||||
import node from '@astrojs/node';
|
import node from '@astrojs/node';
|
||||||
|
|
||||||
import tailwindcss from '@tailwindcss/vite';
|
import tailwindcss from '@tailwindcss/vite';
|
||||||
|
|
||||||
// https://astro.build/config
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
// Ovo omogućuje dinamičke rute bez getStaticPaths
|
|
||||||
output: 'server',
|
output: 'server',
|
||||||
|
|
||||||
adapter: node({
|
adapter: node({
|
||||||
mode: 'standalone'
|
mode: 'standalone',
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
server: {
|
||||||
|
host: true,
|
||||||
|
port: 4321,
|
||||||
|
},
|
||||||
|
|
||||||
image: {
|
image: {
|
||||||
// Dodaj domene s kojih Astro smije povlačiti i optimizirati slike
|
// Dodaj domene s kojih Astro smije povlačiti i optimizirati slike
|
||||||
domains: ['localhost', '127.0.0.1'],
|
domains: ['localhost', '127.0.0.1','v003-backend.captain.mitteworkspace.cloud'],
|
||||||
|
},
|
||||||
|
|
||||||
|
build: {
|
||||||
|
inlineStylesheets: 'always'
|
||||||
},
|
},
|
||||||
|
|
||||||
vite: {
|
vite: {
|
||||||
plugins: [tailwindcss()]
|
plugins: [tailwindcss()],
|
||||||
|
// KLJUČNO ZA TAILWIND v4 + NODE standalone SSR:
|
||||||
|
ssr: {
|
||||||
|
// Prisiljava Vite da uključi Tailwind v4 stilove u serverski bundle
|
||||||
|
noExternal: ['tailwindcss', '@tailwindcss/vite']
|
||||||
|
},
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
164
001.FRONTEND/package-lock.json
generated
164
001.FRONTEND/package-lock.json
generated
@@ -8,7 +8,7 @@
|
|||||||
"name": "poslovanje",
|
"name": "poslovanje",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/node": "^10.1.1",
|
"@astrojs/node": "^10.0.6",
|
||||||
"@tailwindcss/vite": "^4.2.4",
|
"@tailwindcss/vite": "^4.2.4",
|
||||||
"astro": "^6.1.9",
|
"astro": "^6.1.9",
|
||||||
"flowbite": "^4.0.1",
|
"flowbite": "^4.0.1",
|
||||||
@@ -1186,9 +1186,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@oxc-project/types": {
|
"node_modules/@oxc-project/types": {
|
||||||
"version": "0.130.0",
|
"version": "0.132.0",
|
||||||
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.130.0.tgz",
|
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.132.0.tgz",
|
||||||
"integrity": "sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q==",
|
"integrity": "sha512-FESMOxil5Se014ui/Eq8fT5uHJo6nIRwH0PfJrZJXs6Gek3ZVFOrpUv3YIZT20m+extU98Hg1Ym72U58rlsxUQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
"peer": true,
|
||||||
"funding": {
|
"funding": {
|
||||||
@@ -1206,9 +1206,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rolldown/binding-android-arm64": {
|
"node_modules/@rolldown/binding-android-arm64": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.2.tgz",
|
||||||
"integrity": "sha512-fJI3I0r3C3Oj/zdBCpaCmBRZYf07xpaq4yCfDDoSFm+beWNzbIl26puW8RraUdugoJw/95zerNOn6jasAhzSmg==",
|
"integrity": "sha512-ZS4D1JPGn/MYQN/SYDWftIE/nVsM8j/AFOYEzAoOE2O3NktQOZru+/vYXGbR/qtdLdIfGCP0lcoJiYVzsEz+iQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1223,9 +1223,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rolldown/binding-darwin-arm64": {
|
"node_modules/@rolldown/binding-darwin-arm64": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.2.tgz",
|
||||||
"integrity": "sha512-cKnAhWEsV7TPcA/5EAteDp6KcJZBQ2G+BqE7zayMMi7kMvwRsbv7WT9aOnn0WNl4SKEIf43vjS31iUPu80nzXg==",
|
"integrity": "sha512-vdFA9+C/rekyGce7WqHs/xoT0ioZEWaOFyZLIV1mEeNFaFDUQrPIo8Vs2GvJ6eetb3rzDUtUBgzto3ExpXJB3w==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1240,9 +1240,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rolldown/binding-darwin-x64": {
|
"node_modules/@rolldown/binding-darwin-x64": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.2.tgz",
|
||||||
"integrity": "sha512-YKrVwQjIRBPo+5G/u03wGjbdy4q7pyzCe93DK9VJ7zkVmeg8LJ7GbgsiHWdR4xSoe4CAXRD7Bcjgbtr64bkXNg==",
|
"integrity": "sha512-BewSOwTHazv77DTYiAZXSqqKZ4KP/KonFisDMVU7PImxoWfB2aepnPhd2E4SWz3zDzYgDNbs6jBmTdgNnF02GA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1257,9 +1257,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rolldown/binding-freebsd-x64": {
|
"node_modules/@rolldown/binding-freebsd-x64": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.2.tgz",
|
||||||
"integrity": "sha512-z/oBsREo46SsFqBwYtFe0kpJeBijAT48O/WXLI4suiCLBkr03RTtTJMCzSdDd2znlh8VJizL09XVkQgk8IZonw==",
|
"integrity": "sha512-m41o7M0YWtUdqk61Tb+jnKb2rN++iRdIASlExkUoKfIAH30DOHCB8fVLzSUpbWHHU8esmEioY62PxzexE8MBuA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1274,9 +1274,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rolldown/binding-linux-arm-gnueabihf": {
|
"node_modules/@rolldown/binding-linux-arm-gnueabihf": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.2.tgz",
|
||||||
"integrity": "sha512-ik8q7GM11zxvYxFc2PeDcT6TBvhCQMaUxfph/M5l9sKuTs/Sjg3L+Byw0F7w0ZVLBZmx30P+gG0ECzzN+MFcmQ==",
|
"integrity": "sha512-jcojB9H7W/jS29pMKWAK1N+fU99vXodHDTatS3b3y/XSOCiHo0kkA74pL3jJmkoQtYpOCxDvaKs1fo2Ij/1X5w==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -1291,9 +1291,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rolldown/binding-linux-arm64-gnu": {
|
"node_modules/@rolldown/binding-linux-arm64-gnu": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.2.tgz",
|
||||||
"integrity": "sha512-QoSx2EkyrrdZ6kcyE8stqZ62t0Yra8Fs5ia9lOxJrh6TMQJK7gQKmscdTHf7pOXKREKrVwOtJcQG3qVSfc866A==",
|
"integrity": "sha512-1jn6qDU5iiOgFgygDzKUuKP0maTi0/f1+sBLgvij/76C77Nm3ts6ufz9Bjg5q5dduxiUIxtq86JIoBvo1xQ4Ig==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1308,9 +1308,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rolldown/binding-linux-arm64-musl": {
|
"node_modules/@rolldown/binding-linux-arm64-musl": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.2.tgz",
|
||||||
"integrity": "sha512-uwNwFpwKeNiZawfAWBgg0VIztPTV3ihhh1vV334h9ivnNLorxnQMU6Fz8wG1Zb4Qh9LC1/MkcyT3YlDXG3Rsgg==",
|
"integrity": "sha512-QVLO/czFMdoMFSqlX3bcswcJNm/23r+qoa/jgtmFc/qEp6/jXmIkDjF/XIo8dPfGaiwy1xfQn8o77L79GeXFgw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1325,9 +1325,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rolldown/binding-linux-ppc64-gnu": {
|
"node_modules/@rolldown/binding-linux-ppc64-gnu": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.2.tgz",
|
||||||
"integrity": "sha512-zY1bul7OWr7DFBiJ++wofXvnr8B45ce3QsQUhKrIhXsygAh7bTkwyeM1bi1a2g5C/yC/N8TZyGDEoMfm/l9mpg==",
|
"integrity": "sha512-hgO5Abm0w5UL6FEa2iFnZqo2KlK7TQ5QhV5x09hujBf7t5KzHQ1VmfPuTpqRy/rNlSxua3eWH374xxiVrP+lcA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
@@ -1342,9 +1342,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rolldown/binding-linux-s390x-gnu": {
|
"node_modules/@rolldown/binding-linux-s390x-gnu": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.2.tgz",
|
||||||
"integrity": "sha512-0frlsT/f4Ft6I7SMESTKnF3cZsdicQn1dCMkF/jT9wDLE+gGoiQfv1nmT9e+s7s/fekvvy6tZM2jHvI2tkbJDQ==",
|
"integrity": "sha512-fy8rXxuYEu602abC8MUNaPjYLIFzReOaEIEMKMUa0rFEUxNpVXhs15KSSQ4qlqSaM7B6rcj9rDZgADh/IGDzLQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
@@ -1359,9 +1359,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rolldown/binding-linux-x64-gnu": {
|
"node_modules/@rolldown/binding-linux-x64-gnu": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.2.tgz",
|
||||||
"integrity": "sha512-XABVmGp9Tg0WspTVvwduTc4fpqy6JnAUrSQe6OuyqD/03nI7r0O9OWUkMIwFrjKAIqolvqoA4ZrJppgwE0Gxmw==",
|
"integrity": "sha512-0+bOkiQ779+r1WpoHOWHqncvyySci0vKph+myNDYb+im6meJAzHQXay6oEgnkHuUGouM1LKTZwqKpBow6Kj7CQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1376,9 +1376,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rolldown/binding-linux-x64-musl": {
|
"node_modules/@rolldown/binding-linux-x64-musl": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.2.tgz",
|
||||||
"integrity": "sha512-bV4fzswuzVcKD90o/VM6QqKxnxlDq0g2BISDLNVmxrnhpv1DDbyPhCIjYfvzYLV+MvkKKnQt2Q6AO86SEBULUQ==",
|
"integrity": "sha512-mjSkrzZK5Qsl0a9d1JgILOiuZOSDTVdKENcSXBoqbzSrspLR/4/IRVDo5wd2GgZjNss/viBFJdeq+j7qH2nypw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1393,9 +1393,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rolldown/binding-openharmony-arm64": {
|
"node_modules/@rolldown/binding-openharmony-arm64": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.2.tgz",
|
||||||
"integrity": "sha512-/Mh0Zhq3OP7fVs0kcQHZP6lZEthMGTaSf8UBQYSFEZDWGXXlEC+nJ6EqenaK2t4LBXMe3A+K/G2BVXXdtOr4PQ==",
|
"integrity": "sha512-1v5vHasdfQAZoEHakBV72LIFAC9JjnymsiKxp+GEr/ma3+NJCPSaYK+qavInOovJkgwFrs7GccX2d6IgDA3Z5w==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1410,9 +1410,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rolldown/binding-wasm32-wasi": {
|
"node_modules/@rolldown/binding-wasm32-wasi": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.2.tgz",
|
||||||
"integrity": "sha512-+1xc9X45l8ufsBAm6Gjvx2qDRIY9lTVt0cgWNcJ+1gdhXvkbxePA60yRTwSTuXL09CMhyJmjpV7E3NoyxbqFQQ==",
|
"integrity": "sha512-mb1VobWn6NheziTk5/WEaR6AKVbrwT5sOi6C7zk3gy/pD1qtJfU1j4PgTo2NJnOtbL9Dl3Aeei8w9jJ7qC2jZQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"wasm32"
|
"wasm32"
|
||||||
],
|
],
|
||||||
@@ -1429,9 +1429,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rolldown/binding-win32-arm64-msvc": {
|
"node_modules/@rolldown/binding-win32-arm64-msvc": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.2.tgz",
|
||||||
"integrity": "sha512-1D+UqZdfnuR+Jy1GgMJwi85bD40H21uNmOPRWQhw4oRSuolZ/B5rixZ45DK2KXOTCvmVCecauWgEhbw8bI7tOw==",
|
"integrity": "sha512-SqKonF56vA/L2yHwHYcEp2P34URpOZ7d1fS635cTkpDnUtEGdUbhI6NzsPdqeSWvAAeGDrxjWjNmibDIdFf9/A==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1446,9 +1446,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rolldown/binding-win32-x64-msvc": {
|
"node_modules/@rolldown/binding-win32-x64-msvc": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.2.tgz",
|
||||||
"integrity": "sha512-INAycaWuhlOK3wk4mRHGsdgwYWmd9cChdPdE9bwWmy6rn9VqVNYNFGhOdXrofXUxwHIncSiPNb8tNm8knDVIeQ==",
|
"integrity": "sha512-v7qRI7gXLRINcOGXt+7YmAZ6iFuyZVMIoXAxhd8oP+DR9dLfL9GfNIx7PLMxmhZdvq8waUJBQiWN9EKNy+TRBQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -2337,9 +2337,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/astro": {
|
"node_modules/astro": {
|
||||||
"version": "6.3.6",
|
"version": "6.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/astro/-/astro-6.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/astro/-/astro-6.3.7.tgz",
|
||||||
"integrity": "sha512-lM30gGI/iASK9Z1WQVnBBYzxVwDv8slkXbJOF7FNJdZQeBrFETpsQvYoLRupM/adt2ObP5hkYAWEeCjofoqlRw==",
|
"integrity": "sha512-zIeDRrI0qNgN1lcCjNqt6/IVCVej7VwSa326cO8uP9BOk1cg4QuffhLnOn2gCgWQr32/wxpSRFfXiLKHglu1Tw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/compiler": "^4.0.0",
|
"@astrojs/compiler": "^4.0.0",
|
||||||
@@ -2920,9 +2920,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/enhanced-resolve": {
|
"node_modules/enhanced-resolve": {
|
||||||
"version": "5.21.6",
|
"version": "5.22.0",
|
||||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.6.tgz",
|
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.22.0.tgz",
|
||||||
"integrity": "sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==",
|
"integrity": "sha512-xYcDWrpELkFzz9SpZ3PlI6Eu6eD93Yf0WLDRxikGhWJ3MAir2SNZTIVCVZqZ/NUyx8AdMc2gT9C0gPiw18kG+A==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"graceful-fs": "^4.2.4",
|
"graceful-fs": "^4.2.4",
|
||||||
@@ -5305,13 +5305,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/rolldown": {
|
"node_modules/rolldown": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.2.tgz",
|
||||||
"integrity": "sha512-X0KQHljNnEkWNqqiz9zJrGunh1B0HgOxLXvnFpCOcadzcy5qohZ3tqMEUg00vncoRovXuK3ZqCT9KnnKzoInFQ==",
|
"integrity": "sha512-oZx5zVDtVB44AW3eaifgDml1gWRDZGvjcfdxonE4swNPG98PrrXjaO/KrnUjzlMnztCCRVlUueA1kCXhARGk6g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@oxc-project/types": "=0.130.0",
|
"@oxc-project/types": "=0.132.0",
|
||||||
"@rolldown/pluginutils": "^1.0.0"
|
"@rolldown/pluginutils": "^1.0.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -5321,21 +5321,21 @@
|
|||||||
"node": "^20.19.0 || >=22.12.0"
|
"node": "^20.19.0 || >=22.12.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@rolldown/binding-android-arm64": "1.0.1",
|
"@rolldown/binding-android-arm64": "1.0.2",
|
||||||
"@rolldown/binding-darwin-arm64": "1.0.1",
|
"@rolldown/binding-darwin-arm64": "1.0.2",
|
||||||
"@rolldown/binding-darwin-x64": "1.0.1",
|
"@rolldown/binding-darwin-x64": "1.0.2",
|
||||||
"@rolldown/binding-freebsd-x64": "1.0.1",
|
"@rolldown/binding-freebsd-x64": "1.0.2",
|
||||||
"@rolldown/binding-linux-arm-gnueabihf": "1.0.1",
|
"@rolldown/binding-linux-arm-gnueabihf": "1.0.2",
|
||||||
"@rolldown/binding-linux-arm64-gnu": "1.0.1",
|
"@rolldown/binding-linux-arm64-gnu": "1.0.2",
|
||||||
"@rolldown/binding-linux-arm64-musl": "1.0.1",
|
"@rolldown/binding-linux-arm64-musl": "1.0.2",
|
||||||
"@rolldown/binding-linux-ppc64-gnu": "1.0.1",
|
"@rolldown/binding-linux-ppc64-gnu": "1.0.2",
|
||||||
"@rolldown/binding-linux-s390x-gnu": "1.0.1",
|
"@rolldown/binding-linux-s390x-gnu": "1.0.2",
|
||||||
"@rolldown/binding-linux-x64-gnu": "1.0.1",
|
"@rolldown/binding-linux-x64-gnu": "1.0.2",
|
||||||
"@rolldown/binding-linux-x64-musl": "1.0.1",
|
"@rolldown/binding-linux-x64-musl": "1.0.2",
|
||||||
"@rolldown/binding-openharmony-arm64": "1.0.1",
|
"@rolldown/binding-openharmony-arm64": "1.0.2",
|
||||||
"@rolldown/binding-wasm32-wasi": "1.0.1",
|
"@rolldown/binding-wasm32-wasi": "1.0.2",
|
||||||
"@rolldown/binding-win32-arm64-msvc": "1.0.1",
|
"@rolldown/binding-win32-arm64-msvc": "1.0.2",
|
||||||
"@rolldown/binding-win32-x64-msvc": "1.0.1"
|
"@rolldown/binding-win32-x64-msvc": "1.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/rollup": {
|
"node_modules/rollup": {
|
||||||
@@ -5398,9 +5398,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "7.8.0",
|
"version": "7.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz",
|
||||||
"integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==",
|
"integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"bin": {
|
"bin": {
|
||||||
"semver": "bin/semver.js"
|
"semver": "bin/semver.js"
|
||||||
@@ -6013,16 +6013,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "8.0.13",
|
"version": "8.0.14",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-8.0.13.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-8.0.14.tgz",
|
||||||
"integrity": "sha512-MFtjBYgzmSxmgA4RAfjIyXWpGe1oALnjgUTzzV7QLx/TKxCzjtMH6Fd9/eVK+5Fg1qNoz5VAwsmMs/NofrmJvw==",
|
"integrity": "sha512-s4BJJ+5y1pYL6Otw51FHhVJQhPnuRinKig64g/1+EUNaJsd3gCKdD31IPFvswUgW9/60QT9oFHbZHbQK5imcxw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lightningcss": "^1.32.0",
|
"lightningcss": "^1.32.0",
|
||||||
"picomatch": "^4.0.4",
|
"picomatch": "^4.0.4",
|
||||||
"postcss": "^8.5.14",
|
"postcss": "^8.5.15",
|
||||||
"rolldown": "1.0.1",
|
"rolldown": "1.0.2",
|
||||||
"tinyglobby": "^0.2.16"
|
"tinyglobby": "^0.2.16"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ interface Props {
|
|||||||
description?: string;
|
description?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
title = site.title,
|
title = site.title,
|
||||||
description = site.description
|
description = site.description
|
||||||
} = Astro.props;
|
} = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -24,16 +24,16 @@ const {
|
|||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
<meta name="generator" content={Astro.generator} />
|
<meta name="generator" content={Astro.generator} />
|
||||||
<meta name="description" content={description} />
|
<meta name="description" content={description} />
|
||||||
|
|
||||||
<title>{title} | {site.title}</title>
|
<title>{title} | {site.title}</title>
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" />
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" />
|
||||||
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-white antialiased min-h-screen flex flex-col">
|
<body class="bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-white antialiased min-h-screen flex flex-col">
|
||||||
|
|
||||||
<Nav />
|
<Nav />
|
||||||
|
|
||||||
<main class="flex-grow w-full max-w-7xl mx-auto pt-24 pb-12 px-4 sm:px-6 lg:px-8">
|
<main class="flex-grow w-full max-w-7xl mx-auto pt-24 pb-12 px-4 sm:px-6 lg:px-8">
|
||||||
@@ -55,13 +55,4 @@ const {
|
|||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
</style>
|
||||||
body {
|
|
||||||
font-family: 'Inter', system-ui, sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Osigurava da Dark Mode radi ispravno s Flowbite-om */
|
|
||||||
.dark {
|
|
||||||
color-scheme: dark;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
// src/lib/api.js
|
// src/lib/api.js
|
||||||
const API_BASE = import.meta.env.PUBLIC_API_URL;
|
|
||||||
|
// 1. Osiguravamo da API_BASE uvijek završava s točno jednom kosom crtom
|
||||||
|
const RAW_BASE = import.meta.env.PUBLIC_API_URL;
|
||||||
|
const API_BASE = RAW_BASE.endsWith('/') ? RAW_BASE : `${RAW_BASE}/`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* POMOĆNA FUNKCIJA:端 Dohvaća token i postavlja Headere
|
* POMOĆNA FUNKCIJA:端 Dohvaća token i postavlja Headere
|
||||||
@@ -66,42 +69,41 @@ async function handleResponse(res) {
|
|||||||
|
|
||||||
// --- RUTE ---
|
// --- RUTE ---
|
||||||
export const routes = {
|
export const routes = {
|
||||||
// Autentifikacija
|
// Autentifikacija (Maknute početne kose crte!)
|
||||||
login: () => '/token/',
|
login: () => 'token/',
|
||||||
trenutniKorisnik: () => '/users/me/',
|
trenutniKorisnik: () => 'users/me/',
|
||||||
|
|
||||||
// Radni nalozi
|
// Radni nalozi
|
||||||
radniNalozi: (params = {}) => {
|
radniNalozi: (params = {}) => {
|
||||||
const baseUrl = '/operativa/radni-nalozi/';
|
const baseUrl = 'operativa/radni-nalozi/';
|
||||||
// Čistimo null i undefined vrijednosti iz filtera
|
|
||||||
const cleanParams = Object.fromEntries(
|
const cleanParams = Object.fromEntries(
|
||||||
Object.entries(params).filter(([_, v]) => v != null)
|
Object.entries(params).filter(([_, v]) => v != null)
|
||||||
);
|
);
|
||||||
const queryString = new URLSearchParams(cleanParams).toString();
|
const queryString = new URLSearchParams(cleanParams).toString();
|
||||||
return queryString ? `${baseUrl}?${queryString}` : baseUrl;
|
return queryString ? `${baseUrl}?${queryString}` : baseUrl;
|
||||||
},
|
},
|
||||||
radniNalogDetalji: (id) => `/operativa/radni-nalozi/${id}/`,
|
radniNalogDetalji: (id) => `operativa/radni-nalozi/${id}/`,
|
||||||
sljedeciBrojNaloga: () => '/operativa/radni-nalozi/sljedeci-broj/',
|
sljedeciBrojNaloga: () => 'operativa/radni-nalozi/sljedeci-broj/',
|
||||||
|
|
||||||
// Putni nalozi i logistika
|
// Putni nalozi i logistika
|
||||||
putniNalozi: () => '/operativa/putni-nalozi/',
|
putniNalozi: () => 'operativa/putni-nalozi/',
|
||||||
|
|
||||||
// Vozila i strojevi (Fleet modul)
|
// Vozila i strojevi (Fleet modul)
|
||||||
vozila: () => '/fleet/vozila/', // USKLAĐENO: Prebačeno pod zajednički /fleet/ namespace
|
vozila: () => 'fleet/vozila/',
|
||||||
strojevi: (vlasnikId = null) => {
|
strojevi: (vlasnikId = null) => {
|
||||||
const baseUrl = '/fleet/strojevi/';
|
const baseUrl = 'fleet/strojevi/';
|
||||||
if (vlasnikId) return `${baseUrl}?vlasnik=${vlasnikId}`;
|
if (vlasnikId) return `${baseUrl}?vlasnik=${vlasnikId}`;
|
||||||
return baseUrl;
|
return baseUrl;
|
||||||
},
|
},
|
||||||
strojDetalji: (id) => `/fleet/strojevi/${id}/`,
|
strojDetalji: (id) => `fleet/strojevi/${id}/`,
|
||||||
|
|
||||||
// Kupci / Klijenti
|
// Kupci / Klijenti
|
||||||
kupciSvi: () => '/kupci/svi/',
|
kupciSvi: () => 'kupci/svi/',
|
||||||
kupacDetalji: (id) => `/kupci/svi/${id}/`,
|
kupacDetalji: (id) => `kupci/svi/${id}/`,
|
||||||
|
|
||||||
// Kalendar i raspored
|
// Kalendar i raspored
|
||||||
mojRaspored: () => '/kalendar/moj-raspored/',
|
mojRaspored: () => 'kalendar/moj-raspored/',
|
||||||
kalendarDogadaji: () => '/kalendar/dogadaji/'
|
kalendarDogadaji: () => 'kalendar/dogadaji/'
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- API METODE ---
|
// --- API METODE ---
|
||||||
@@ -418,16 +420,20 @@ export async function fetchPutniNaloziData() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dohvaća sljedeći slobodni broj radnog naloga s backenda
|
||||||
|
* Osigurano protiv duplih kosih crta i preflight redirecta
|
||||||
|
*/
|
||||||
export async function fetchSljedeciBrojNaloga() {
|
export async function fetchSljedeciBrojNaloga() {
|
||||||
try {
|
try {
|
||||||
// Koristimo novu rutu iz routes objekta
|
// Pametno spajanje baze i rute (isto kao u ostalim očišćenim metodama)
|
||||||
const url = `${API_BASE}${routes.sljedeciBrojNaloga()}`;
|
const base = API_BASE.endsWith('/') ? API_BASE : `${API_BASE}/`;
|
||||||
|
const ruta = routes.sljedeciBrojNaloga();
|
||||||
|
const url = `${base}${ruta}`;
|
||||||
|
|
||||||
const res = await fetch(url, {
|
const res = await fetch(url, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: getAuthHeaders() // Koristi centralizirane headere umjesto sirovog objekta
|
||||||
'Content-Type': 'application/json'
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
|
|||||||
@@ -1,34 +1,35 @@
|
|||||||
---
|
|
||||||
// src/pages/fleet/vozila/[id].astro
|
// src/pages/fleet/vozila/[id].astro
|
||||||
import Layout from "../../../layouts/Layout.astro"; // Prilagodi putanju svom glavnom layoutu
|
---
|
||||||
import { fetchCalendarEvents } from "../../../lib/api"; // Pretpostavka lokacije tvog centraliziranog API-ja
|
import Layout from "../../../layouts/Layout.astro";
|
||||||
|
import Button from "../../../components/Button.astro"; // Uvoz tvoje zajedničke komponente za gumbe
|
||||||
import { getStatusColorClass } from "../../../utils/ui";
|
import { getStatusColorClass } from "../../../utils/ui";
|
||||||
|
|
||||||
// 1. Dohvat ID-ja iz URL parametara
|
// 1. Dohvat ID-ja iz URL parametara
|
||||||
const { id } = Astro.params;
|
const { id } = Astro.params;
|
||||||
|
|
||||||
// 2. Dohvat podataka s Django API-ja
|
|
||||||
// Ovdje koristimo tvoj centralizirani API klijent. Ako imaš fetchVoziloDetails(id), iskoristi ga.
|
|
||||||
// Kao siguran fallback, dohvaćamo sva vozila i filtriramo ono koje nam treba.
|
|
||||||
const response = await fetch(`${Astro.url.origin}/api/fleet/vozila`); // ili izravno tvoj DRF endpoint ako lib nema pojedinačni fetch
|
|
||||||
let vozilo = null;
|
let vozilo = null;
|
||||||
|
let radniNalozi = [];
|
||||||
|
|
||||||
|
// 2. Dohvat podataka s Django API-ja (Backend)
|
||||||
try {
|
try {
|
||||||
// Simulacija dohvata preko tvog centraliziranog klijenta ili izravnog fetch-a
|
const voziloResponse = await fetch(`http://127.0.0.1:8000/api/fleet/vozila/${id}/`);
|
||||||
// Ako tvoj api.js ima metodu npr. fetchVozilo(id), zamijeni ovo s: vozilo = await fetchVozilo(id);
|
if (voziloResponse.ok) {
|
||||||
const svaVozilaResponse = await fetch("http://127.0.0.1:8000/api/fleet/vozila/"); // Primjer internog DRF endpointa
|
vozilo = await voziloResponse.json();
|
||||||
const vozila = await svaVozilaResponse.json();
|
}
|
||||||
vozilo = vozila.find((v) => v.id === parseInt(id));
|
|
||||||
|
const naloziResponse = await fetch(`http://127.0.0.1:8000/api/operativa/radni-nalozi/`);
|
||||||
|
if (naloziResponse.ok) {
|
||||||
|
const sviNalozi = await naloziResponse.json();
|
||||||
|
radniNalozi = sviNalozi.filter((nalog) => nalog.vozilo === parseInt(id) || nalog.vozilo_id === parseInt(id));
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Greška pri dohvaćanju podataka o vozilu:", error);
|
console.error("Greška pri dohvaćanju podataka s Django API-ja:", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ako vozilo ne postoji, preusmjeravamo na 404 ili na listu vozila
|
|
||||||
if (!vozilo) {
|
if (!vozilo) {
|
||||||
return Astro.redirect("/fleet/vozila?error=not-found");
|
return Astro.redirect("/fleet/vozila?error=not-found");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pomoćna funkcija za formatiranje statusa lokalno ako zakaže status_prikaz
|
|
||||||
function formatStatusLocal(status) {
|
function formatStatusLocal(status) {
|
||||||
const map = {
|
const map = {
|
||||||
'aktivan': 'Aktivan',
|
'aktivan': 'Aktivan',
|
||||||
@@ -38,21 +39,31 @@ function formatStatusLocal(status) {
|
|||||||
return map[status?.toLowerCase()] || status;
|
return map[status?.toLowerCase()] || status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getPrioritetClass(prioritet) {
|
||||||
|
const p = prioritet?.toLowerCase();
|
||||||
|
if (p === 'hitan' || p === 'visok') return 'bg-red-500/10 text-red-500 border-red-500/20';
|
||||||
|
if (p === 'srednji') return 'bg-amber-500/10 text-amber-500 border-amber-500/20';
|
||||||
|
return 'bg-blue-500/10 text-blue-500 border-blue-500/20';
|
||||||
|
}
|
||||||
|
|
||||||
const statusKlasa = getStatusColorClass(vozilo.status?.toLowerCase());
|
const statusKlasa = getStatusColorClass(vozilo.status?.toLowerCase());
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout title={`Vozilo | ${vozilo.naziv}`}>
|
<Layout title={`Vozilo | ${vozilo.naziv}`}>
|
||||||
<div class="max-w-4xl mx-auto px-4 py-8 font-sans">
|
<div class="max-w-4xl mx-auto px-4 py-8 font-sans">
|
||||||
|
|
||||||
<a
|
<div class="mb-6">
|
||||||
href="/fleet/vozila"
|
<Button
|
||||||
class="inline-flex items-center gap-2 text-sm font-black uppercase tracking-widest text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors mb-6"
|
href="/fleet/vozila"
|
||||||
>
|
variant="ghost"
|
||||||
<i class="fa-solid fa-arrow-left-long"></i> Povratak na popis
|
class="!px-0 text-sm font-black uppercase tracking-widest text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
|
||||||
</a>
|
>
|
||||||
|
<i class="fa-solid fa-arrow-left-long mr-2"></i> Povratak na popis
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="w-full bg-white dark:bg-gray-800 text-gray-900 dark:text-white shadow-2xl rounded-[3rem] border border-gray-100 dark:border-gray-700 overflow-hidden transition-all mb-8">
|
||||||
|
|
||||||
<div class="w-full bg-white dark:bg-gray-800 text-gray-900 dark:text-white shadow-2xl rounded-[3rem] border border-gray-100 dark:border-gray-700 overflow-hidden transition-all">
|
|
||||||
|
|
||||||
<div class="flex flex-wrap justify-between items-center bg-gray-50/50 dark:bg-gray-900/50 px-8 py-8 border-b border-gray-100 dark:border-gray-700 gap-4">
|
<div class="flex flex-wrap justify-between items-center bg-gray-50/50 dark:bg-gray-900/50 px-8 py-8 border-b border-gray-100 dark:border-gray-700 gap-4">
|
||||||
<div class="flex items-center gap-5">
|
<div class="flex items-center gap-5">
|
||||||
<div class="bg-blue-600/10 text-blue-600 dark:text-blue-400 p-5 rounded-2xl shadow-md">
|
<div class="bg-blue-600/10 text-blue-600 dark:text-blue-400 p-5 rounded-2xl shadow-md">
|
||||||
@@ -74,7 +85,6 @@ const statusKlasa = getStatusColorClass(vozilo.status?.toLowerCase());
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="p-8 grid grid-cols-1 md:grid-cols-2 gap-6">
|
<div class="p-8 grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
|
|
||||||
<div class="bg-gray-50 dark:bg-gray-900/40 p-6 rounded-2xl border border-gray-100 dark:border-gray-700/50">
|
<div class="bg-gray-50 dark:bg-gray-900/40 p-6 rounded-2xl border border-gray-100 dark:border-gray-700/50">
|
||||||
<span class="text-[10px] font-black uppercase tracking-[0.2em] text-gray-400 dark:text-gray-500 block mb-1">
|
<span class="text-[10px] font-black uppercase tracking-[0.2em] text-gray-400 dark:text-gray-500 block mb-1">
|
||||||
Registracijska oznaka
|
Registracijska oznaka
|
||||||
@@ -113,44 +123,106 @@ const statusKlasa = getStatusColorClass(vozilo.status?.toLowerCase());
|
|||||||
Vozilo je mapirano na centralni logistički sustav fleet managementa. Sve izmjene kilometara i servisnih naloga sinkroniziraju se u realnom vremenu s radnim nalozima operativnog tima.
|
Vozilo je mapirano na centralni logistički sustav fleet managementa. Sve izmjene kilometara i servisnih naloga sinkroniziraju se u realnom vremenu s radnim nalozima operativnog tima.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="px-8 py-5 bg-gray-50 dark:bg-gray-900/30 border-t border-gray-100 dark:border-gray-700 flex justify-end gap-3">
|
<div class="px-8 py-5 bg-gray-50 dark:bg-gray-900/30 border-t border-gray-100 dark:border-gray-700 flex justify-end gap-3">
|
||||||
<a
|
<Button
|
||||||
href={`/operativa/radni-nalozi?vozilo=${vozilo.id}`}
|
href={`/operativa/radni-nalozi?vozilo=${vozilo.id}`}
|
||||||
class="px-5 py-2.5 bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-200 text-xs font-black uppercase tracking-widest rounded-xl border border-gray-200 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 transition-all active:scale-95 shadow-sm"
|
variant="secondary"
|
||||||
|
class="text-xs font-black uppercase tracking-widest rounded-xl shadow-sm"
|
||||||
>
|
>
|
||||||
<i class="fa-solid fa-file-invoice mr-1.5 opacity-70"></i> Radni Nalozi
|
<i class="fa-solid fa-file-invoice mr-1.5 opacity-70"></i> Otvori u operativi
|
||||||
</a>
|
</Button>
|
||||||
<button
|
<Button
|
||||||
id="btn-brzi-servis"
|
id="btn-brzi-servis"
|
||||||
data-id={vozilo.id}
|
data-id={vozilo.id}
|
||||||
class="px-5 py-2.5 bg-blue-600 text-white text-xs font-black uppercase tracking-widest rounded-xl hover:bg-blue-700 transition-all active:scale-95 shadow-lg shadow-blue-600/20"
|
variant="primary"
|
||||||
|
class="text-xs font-black uppercase tracking-widest rounded-xl shadow-lg shadow-blue-600/20"
|
||||||
>
|
>
|
||||||
<i class="fa-solid fa-screwdriver-wrench mr-1.5"></i> Otvori Servis
|
<i class="fa-solid fa-screwdriver-wrench mr-1.5"></i> Otvori Servis
|
||||||
</button>
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="w-full bg-white dark:bg-gray-800 text-gray-900 dark:text-white shadow-2xl rounded-[3rem] border border-gray-100 dark:border-gray-700 overflow-hidden p-8">
|
||||||
|
<div class="flex items-center justify-between mb-6 border-b border-gray-100 dark:border-gray-700 pb-4">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<i class="fa-solid fa-clipboard-list text-2xl text-blue-600 dark:text-blue-400"></i>
|
||||||
|
<h2 class="text-xl font-black uppercase tracking-tight italic">Povijest Radnih Naloga</h2>
|
||||||
|
</div>
|
||||||
|
<span class="text-xs font-black bg-gray-100 dark:bg-gray-900 px-3 py-1.5 rounded-xl uppercase tracking-widest border border-gray-200 dark:border-gray-700">
|
||||||
|
Ukupno: {radniNalozi.length}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{radniNalozi.length === 0 ? (
|
||||||
|
<div class="text-center py-12 bg-gray-50 dark:bg-gray-900/20 rounded-2xl border border-dashed border-gray-200 dark:border-gray-700">
|
||||||
|
<i class="fa-solid fa-folder-open text-4xl text-gray-300 dark:text-gray-600 mb-3"></i>
|
||||||
|
<p class="text-sm font-bold text-gray-400 uppercase tracking-wider">Nema evidentiranih radnih naloga za ovo vozilo.</p>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div class="space-y-4">
|
||||||
|
{radniNalozi.map((nalog) => (
|
||||||
|
<div class="flex flex-wrap items-center justify-between p-5 bg-gray-50 dark:bg-gray-900/30 rounded-2xl border border-gray-100 dark:border-gray-700/50 hover:border-blue-600 dark:hover:border-blue-400 transition-all gap-4">
|
||||||
|
<div class="flex items-start gap-4">
|
||||||
|
<div class="bg-gray-200 dark:bg-gray-800 text-gray-700 dark:text-gray-300 p-3 rounded-xl font-black text-xs">
|
||||||
|
#{nalog.broj_naloga || nalog.id}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h4 class="text-sm font-black uppercase tracking-tight text-gray-800 dark:text-gray-100">
|
||||||
|
{nalog.opis_kvara || nalog.naslov || "Opis radova nije definiran"}
|
||||||
|
</h4>
|
||||||
|
<div class="flex items-center gap-4 mt-1 text-xs text-gray-400 font-medium">
|
||||||
|
<span>
|
||||||
|
<i class="fa-solid fa-calendar-days mr-1 text-blue-600/60"></i>
|
||||||
|
{nalog.datum_otvaranja ? new Date(nalog.datum_otvaranja).toLocaleDateString('hr-HR') : "Nepoznat datum"}
|
||||||
|
</span>
|
||||||
|
{nalog.kilometraža_prijave && (
|
||||||
|
<span>
|
||||||
|
<i class="fa-solid fa-gauge-high mr-1 text-blue-600/60"></i>
|
||||||
|
{nalog.kilometraža_prijave.toLocaleString('hr-HR')} KM
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<span class={`text-[10px] font-black px-2.5 py-1 rounded-lg border uppercase tracking-wider ${getPrioritetClass(nalog.prioritet)}`}>
|
||||||
|
{nalog.prioritet || "Normalno"}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
href={`/operativa/radni-nalozi/${nalog.id}`}
|
||||||
|
variant="ghost"
|
||||||
|
class="!p-2.5 bg-white dark:bg-gray-700 text-gray-500 dark:text-gray-300 rounded-xl border border-gray-200 dark:border-gray-600 hover:text-blue-600 dark:hover:text-blue-400 transition-colors shadow-sm"
|
||||||
|
title="Pregledaj nalog"
|
||||||
|
>
|
||||||
|
<i class="fa-solid fa-chevron-right"></i>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Klijentska skripta za brze akcije na stranici vozila
|
|
||||||
function initDetaljiVozila() {
|
function initDetaljiVozila() {
|
||||||
const servisBtn = document.getElementById('btn-brzi-servis');
|
const servisBtn = document.getElementById('btn-brzi-servis');
|
||||||
if (servisBtn) {
|
if (servisBtn) {
|
||||||
servisBtn.addEventListener('click', () => {
|
servisBtn.addEventListener('click', () => {
|
||||||
const voziloId = servisBtn.getAttribute('data-id');
|
const voziloId = servisBtn.getAttribute('data-id');
|
||||||
// Primjer brze operativne akcije (npr. otvaranje modala ili preusmjeravanje)
|
|
||||||
console.log(`Otvaram brzu servisnu prijavu za vozilo ID: ${voziloId}`);
|
console.log(`Otvaram brzu servisnu prijavu za vozilo ID: ${voziloId}`);
|
||||||
window.location.href = `/operativa/radni-nalozi/novo?vozilo_id=${voziloId}&tip=servis`;
|
window.location.href = `/operativa/radni-nalozi/novo?vozilo_id=${voziloId}&tip=servis`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Podrška za Astro View Transitions i standardno učitavanje
|
|
||||||
initDetaljiVozila();
|
initDetaljiVozila();
|
||||||
document.addEventListener('astro:after-swap', initDetaljiVozila);
|
document.addEventListener('astro:after-swap', initDetaljiVozila);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1 +1,8 @@
|
|||||||
@import "tailwindcss";
|
/* src/styles/global.css */
|
||||||
|
@import "tailwindcss";
|
||||||
|
|
||||||
|
/* Eksplicitne putanje za Tailwind v4 skener na tvom LXC-u */
|
||||||
|
@source "../**/*.astro";
|
||||||
|
@source "../components/**/*.astro";
|
||||||
|
@source "../layouts/**/*.astro";
|
||||||
|
@source "../pages/**/*.astro";
|
||||||
|
|||||||
Reference in New Issue
Block a user