Merge branch <prisma> to <main> #6
71 changed files with 14386 additions and 1162 deletions
7
.dockerignore
Normal file
7
.dockerignore
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Dockerfile
|
||||
.dockerignore
|
||||
node_modules
|
||||
npm-debug.log
|
||||
README.md
|
||||
.next
|
||||
.git
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -39,3 +39,5 @@ yarn-error.log*
|
|||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
|
||||
/prisma/generated/prisma
|
||||
|
|
|
|||
4
.prettierrc
Normal file
4
.prettierrc
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"tabWidth": 2,
|
||||
"useTabs": false
|
||||
}
|
||||
50
Dockerfile
50
Dockerfile
|
|
@ -1,38 +1,44 @@
|
|||
# Fase 1: Build
|
||||
FROM node:18-alpine AS builder
|
||||
FROM node:22-alpine AS base
|
||||
|
||||
RUN apk add --no-cache libc6-compat openssl
|
||||
|
||||
# Imposta la directory di lavoro
|
||||
WORKDIR /app
|
||||
|
||||
# Copia i file di configurazione e dipendenze
|
||||
COPY package.json pnpm-lock.yaml* ./
|
||||
# --- STAGE 1 ---
|
||||
FROM base AS deps
|
||||
COPY package.json ./
|
||||
RUN npm install
|
||||
|
||||
# Installa le dipendenze
|
||||
RUN npm install --force
|
||||
|
||||
# Copia il resto dei file dell'app
|
||||
# --- STAGE 2 ---
|
||||
FROM base AS builder
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
|
||||
# Build dell'app Next.js
|
||||
RUN npx prisma generate
|
||||
|
||||
ENV NEXT_TELEMETRY_DISABLED=1
|
||||
|
||||
RUN npm run build
|
||||
|
||||
# Fase 2: Runtime (immagine più leggera)
|
||||
FROM node:18-alpine AS runner
|
||||
|
||||
# Imposta la directory di lavoro
|
||||
# --- STAGE 3 ---
|
||||
FROM base AS runner
|
||||
WORKDIR /app
|
||||
|
||||
# Imposta variabile d'ambiente per produzione
|
||||
ENV NODE_ENV=production
|
||||
ENV NEXT_TELEMETRY_DISABLED=1
|
||||
ENV PORT=3000
|
||||
ENV HOSTNAME="0.0.0.0"
|
||||
|
||||
RUN addgroup --system --gid 1001 nodejs
|
||||
RUN adduser --system --uid 1001 nextjs
|
||||
|
||||
# Copia solo ciò che serve per l'esecuzione
|
||||
COPY --from=builder /app/public ./public
|
||||
COPY --from=builder /app/.next ./.next
|
||||
COPY --from=builder /app/node_modules ./node_modules
|
||||
COPY --from=builder /app/package.json ./package.json
|
||||
|
||||
# Porta esposta (3000 di default per Next.js)
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||
|
||||
USER nextjs
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
# Comando di avvio
|
||||
CMD ["npm", "start"]
|
||||
CMD ["node", "server.js"]
|
||||
|
|
|
|||
|
|
@ -1,11 +1,27 @@
|
|||
services:
|
||||
app:
|
||||
container_name: dashregistratori
|
||||
build:
|
||||
context: .
|
||||
webapp:
|
||||
build: .
|
||||
container_name: dash-registratori
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 3001:3000
|
||||
dns: 1.1.1.1
|
||||
- "3000:3000"
|
||||
environment:
|
||||
NODE_ENV: development
|
||||
DATABASE_URL: "postgresql://postgres:postgres@db:5432/db?schema=public"
|
||||
depends_on:
|
||||
- db
|
||||
|
||||
db:
|
||||
image: postgres:alpine
|
||||
container_name: db
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_DB: db
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
|
|
|
|||
|
|
@ -2,6 +2,14 @@ import type { NextConfig } from "next";
|
|||
|
||||
const nextConfig: NextConfig = {
|
||||
output: "standalone",
|
||||
|
||||
typescript: {
|
||||
ignoreBuildErrors: true,
|
||||
},
|
||||
|
||||
eslint: {
|
||||
ignoreDuringBuilds: true,
|
||||
},
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
|
|
|
|||
1239
package-lock.json
generated
1239
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -8,23 +8,29 @@
|
|||
"start": "next start"
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "^6.18.0",
|
||||
"@radix-ui/react-avatar": "^1.1.10",
|
||||
"@radix-ui/react-checkbox": "^1.3.3",
|
||||
"@radix-ui/react-collapsible": "^1.1.12",
|
||||
"@radix-ui/react-dialog": "^1.1.15",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
||||
"@radix-ui/react-label": "^2.1.7",
|
||||
"@radix-ui/react-popover": "^1.1.15",
|
||||
"@radix-ui/react-separator": "^1.1.7",
|
||||
"@radix-ui/react-slot": "^1.2.3",
|
||||
"@radix-ui/react-slot": "^1.2.4",
|
||||
"@radix-ui/react-switch": "^1.2.6",
|
||||
"@radix-ui/react-tooltip": "^1.2.8",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"cmdk": "^1.1.1",
|
||||
"date-fns": "^4.1.0",
|
||||
"leaflet": "^1.9.4",
|
||||
"leaflet-defaulticon-compatibility": "^0.1.2",
|
||||
"lucide-react": "^0.546.0",
|
||||
"next": "15.5.5",
|
||||
"prisma": "^6.17.1",
|
||||
"react": "19.1.0",
|
||||
"react-day-picker": "^9.11.1",
|
||||
"react-dom": "19.1.0",
|
||||
"react-leaflet": "^5.0.0",
|
||||
"tailwind-merge": "^3.3.1"
|
||||
|
|
@ -35,6 +41,7 @@
|
|||
"@types/node": "^20",
|
||||
"@types/react": "^19",
|
||||
"@types/react-dom": "^19",
|
||||
"prisma": "^6.18.0",
|
||||
"tailwindcss": "^4",
|
||||
"tw-animate-css": "^1.4.0",
|
||||
"typescript": "^5"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "Intervento" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"id_registratore" INTEGER NOT NULL,
|
||||
"data" DATE NOT NULL,
|
||||
"lavoro" TEXT NOT NULL,
|
||||
"fattura" BOOLEAN NOT NULL,
|
||||
|
||||
CONSTRAINT "Intervento_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Registratore" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"id_cliente" INTEGER NOT NULL,
|
||||
|
||||
CONSTRAINT "Registratore_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Cliente" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"ragione_sociale" VARCHAR(255) NOT NULL,
|
||||
"email" VARCHAR(255) NOT NULL,
|
||||
"partita_iva" VARCHAR(255) NOT NULL,
|
||||
"telefono" VARCHAR(255) NOT NULL,
|
||||
"sede" VARCHAR(255) NOT NULL,
|
||||
"sede_url" VARCHAR(255) NOT NULL,
|
||||
"contratto" VARCHAR(255) NOT NULL,
|
||||
|
||||
CONSTRAINT "Cliente_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Cliente_ragione_sociale_key" ON "Cliente"("ragione_sociale");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Intervento" ADD CONSTRAINT "Intervento_id_registratore_fkey" FOREIGN KEY ("id_registratore") REFERENCES "Registratore"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Registratore" ADD CONSTRAINT "Registratore_id_cliente_fkey" FOREIGN KEY ("id_cliente") REFERENCES "Cliente"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
5
prisma/migrations/20251104102414_002/migration.sql
Normal file
5
prisma/migrations/20251104102414_002/migration.sql
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "Registratore" ADD COLUMN "data_acquisto" DATE,
|
||||
ADD COLUMN "prossima_verifica" DATE,
|
||||
ADD COLUMN "seriale" VARCHAR(255),
|
||||
ADD COLUMN "ultima_verifica" DATE;
|
||||
21
prisma/migrations/20251111124743_002/migration.sql
Normal file
21
prisma/migrations/20251111124743_002/migration.sql
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
Warnings:
|
||||
|
||||
- The primary key for the `Registratore` table will be changed. If it partially fails, the table could be left without primary key constraint.
|
||||
|
||||
*/
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "public"."Intervento" DROP CONSTRAINT "Intervento_id_registratore_fkey";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "Intervento" ALTER COLUMN "id_registratore" SET DATA TYPE TEXT;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "Registratore" DROP CONSTRAINT "Registratore_pkey",
|
||||
ALTER COLUMN "id" DROP DEFAULT,
|
||||
ALTER COLUMN "id" SET DATA TYPE TEXT,
|
||||
ADD CONSTRAINT "Registratore_pkey" PRIMARY KEY ("id");
|
||||
DROP SEQUENCE "Registratore_id_seq";
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Intervento" ADD CONSTRAINT "Intervento_id_registratore_fkey" FOREIGN KEY ("id_registratore") REFERENCES "Registratore"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
8
prisma/migrations/20251111124854_003/migration.sql
Normal file
8
prisma/migrations/20251111124854_003/migration.sql
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `seriale` on the `Registratore` table. All the data in the column will be lost.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "Registratore" DROP COLUMN "seriale";
|
||||
5
prisma/migrations/20251111125913_004/migration.sql
Normal file
5
prisma/migrations/20251111125913_004/migration.sql
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
-- CreateEnum
|
||||
CREATE TYPE "Modello" AS ENUM ('FORM100', 'FORM200', 'FORM500');
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "Registratore" ADD COLUMN "modello" "Modello";
|
||||
2
prisma/migrations/20251111130324_005/migration.sql
Normal file
2
prisma/migrations/20251111130324_005/migration.sql
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
-- AlterEnum
|
||||
ALTER TYPE "Modello" ADD VALUE 'FORM200PLUS';
|
||||
2
prisma/migrations/20251111140337_006/migration.sql
Normal file
2
prisma/migrations/20251111140337_006/migration.sql
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "Cliente" ADD COLUMN "coordinate" DOUBLE PRECISION[];
|
||||
10
prisma/migrations/20251111161412_007/migration.sql
Normal file
10
prisma/migrations/20251111161412_007/migration.sql
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `coordinate` on the `Cliente` table. All the data in the column will be lost.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "Cliente" DROP COLUMN "coordinate",
|
||||
ADD COLUMN "lat" DOUBLE PRECISION,
|
||||
ADD COLUMN "lon" DOUBLE PRECISION;
|
||||
10
prisma/migrations/20251111164927_008/migration.sql
Normal file
10
prisma/migrations/20251111164927_008/migration.sql
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
Warnings:
|
||||
|
||||
- Made the column `lat` on table `Cliente` required. This step will fail if there are existing NULL values in that column.
|
||||
- Made the column `lon` on table `Cliente` required. This step will fail if there are existing NULL values in that column.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "Cliente" ALTER COLUMN "lat" SET NOT NULL,
|
||||
ALTER COLUMN "lon" SET NOT NULL;
|
||||
2
prisma/migrations/20251120094202_009/migration.sql
Normal file
2
prisma/migrations/20251120094202_009/migration.sql
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "Cliente" ALTER COLUMN "sede_url" SET DATA TYPE TEXT;
|
||||
3
prisma/migrations/migration_lock.toml
Normal file
3
prisma/migrations/migration_lock.toml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Please do not edit this file manually
|
||||
# It should be added in your version-control system (e.g., Git)
|
||||
provider = "postgresql"
|
||||
50
prisma/schema.prisma
Normal file
50
prisma/schema.prisma
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
output = "../src/generated/prisma"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
enum Modello {
|
||||
FORM100
|
||||
FORM200
|
||||
FORM200PLUS
|
||||
FORM500
|
||||
}
|
||||
|
||||
model Intervento {
|
||||
id Int @id @default(autoincrement())
|
||||
id_registratore String
|
||||
data DateTime @db.Date
|
||||
lavoro String @db.Text
|
||||
fattura Boolean @db.Boolean
|
||||
registratore Registratore @relation(fields: [id_registratore], references: [id])
|
||||
}
|
||||
|
||||
model Registratore {
|
||||
id String @id
|
||||
id_cliente Int
|
||||
modello Modello?
|
||||
data_acquisto DateTime? @db.Date
|
||||
ultima_verifica DateTime? @db.Date
|
||||
prossima_verifica DateTime? @db.Date
|
||||
cliente Cliente @relation(fields: [id_cliente], references: [id])
|
||||
interventi Intervento[]
|
||||
}
|
||||
|
||||
model Cliente {
|
||||
id Int @id @default(autoincrement())
|
||||
ragione_sociale String @unique @db.VarChar(255)
|
||||
email String @db.VarChar(255)
|
||||
partita_iva String @db.VarChar(255)
|
||||
telefono String @db.VarChar(255)
|
||||
sede String @db.VarChar(255)
|
||||
sede_url String
|
||||
contratto String @db.VarChar(255)
|
||||
lat Float
|
||||
lon Float
|
||||
registratori Registratore[]
|
||||
}
|
||||
24
src/app/api/clienti/[id]/route.ts
Normal file
24
src/app/api/clienti/[id]/route.ts
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import { PrismaClient } from "@/generated/prisma";
|
||||
|
||||
export async function GET(
|
||||
request: Request,
|
||||
{ params }: { params: Promise<{ id: string }> },
|
||||
) {
|
||||
const prisma = new PrismaClient();
|
||||
const { id } = await params;
|
||||
|
||||
const cliente = await prisma.cliente.findUnique({
|
||||
where: {
|
||||
id: Number(id),
|
||||
},
|
||||
include: {
|
||||
registratori: {
|
||||
include: {
|
||||
interventi: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return Response.json({ cliente });
|
||||
}
|
||||
66
src/app/api/clienti/route.ts
Normal file
66
src/app/api/clienti/route.ts
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
import { Modello, PrismaClient } from "@/generated/prisma";
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
const clients = await prisma.cliente.findMany({
|
||||
include: {
|
||||
registratori: {
|
||||
include: {
|
||||
interventi: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return Response.json({ clients });
|
||||
}
|
||||
|
||||
function extractLatLonFromGmapsUrl(url: string) {
|
||||
// Usa una regex per cercare la latitudine e la longitudine nell'URL
|
||||
const regex = /@(-?\d+\.\d+),(-?\d+\.\d+)/;
|
||||
const match = url.match(regex);
|
||||
|
||||
if (match) {
|
||||
const lat = parseFloat(match[1]);
|
||||
const lon = parseFloat(match[2]);
|
||||
return [lat, lon]; // Restituisce un array con latitudine e longitudine
|
||||
} else {
|
||||
return [0, 0]; // Se non trova latitudine e longitudine
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const prisma = new PrismaClient();
|
||||
const data = await request.json();
|
||||
const [lat, lon] = extractLatLonFromGmapsUrl(data.sede_url);
|
||||
|
||||
await prisma.cliente.create({
|
||||
data: {
|
||||
contratto: data.contratto,
|
||||
email: data.email,
|
||||
partita_iva: data.partita_iva,
|
||||
ragione_sociale: data.ragione_sociale,
|
||||
sede: data.sede,
|
||||
sede_url: data.sede_url,
|
||||
telefono: data.telefono,
|
||||
lat: lat,
|
||||
lon: lon,
|
||||
/*registratori: {
|
||||
create: {
|
||||
id: "80E1758414",
|
||||
modello: Modello.FORM100,
|
||||
interventi: {
|
||||
create: {
|
||||
data: new Date("2025-10-30"),
|
||||
fattura: true,
|
||||
lavoro: "Boh, cazzeggiato tutto il tempo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},*/
|
||||
},
|
||||
});
|
||||
|
||||
return Response.json({ message: "fatto bastardo" });
|
||||
}
|
||||
17
src/app/api/interventi/route.ts
Normal file
17
src/app/api/interventi/route.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import { PrismaClient } from "@/generated/prisma";
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const prisma = new PrismaClient();
|
||||
const data = await request.json();
|
||||
|
||||
await prisma.intervento.create({
|
||||
data: {
|
||||
id_registratore: data.id,
|
||||
data: new Date(data.data),
|
||||
lavoro: data.lavoro,
|
||||
fattura: data.fattura,
|
||||
},
|
||||
});
|
||||
|
||||
return Response.json({ message: "fatto bastardo" });
|
||||
}
|
||||
17
src/app/api/registratori/interventi/[id]/route.ts
Normal file
17
src/app/api/registratori/interventi/[id]/route.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import { PrismaClient } from "@/generated/prisma";
|
||||
|
||||
export async function GET(
|
||||
request: Request,
|
||||
{ params }: { params: Promise<{ id: string }> },
|
||||
) {
|
||||
const prisma = new PrismaClient();
|
||||
const { id }: { id: string } = await params;
|
||||
|
||||
const cliente = await prisma.intervento.findMany({
|
||||
where: {
|
||||
id_registratore: id,
|
||||
},
|
||||
});
|
||||
|
||||
return Response.json({ cliente });
|
||||
}
|
||||
24
src/app/api/registratori/route.ts
Normal file
24
src/app/api/registratori/route.ts
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import { Modello, PrismaClient } from "@/generated/prisma";
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const prisma = new PrismaClient();
|
||||
const data = await request.json();
|
||||
|
||||
await prisma.registratore.create({
|
||||
data: {
|
||||
id: data.seriale,
|
||||
id_cliente: data.id,
|
||||
data_acquisto: new Date(data.data),
|
||||
modello:
|
||||
data.modello === "FORM100"
|
||||
? Modello.FORM100
|
||||
: data.modello === "FORM200"
|
||||
? Modello.FORM200
|
||||
: data.modello === "FORM200PLUS"
|
||||
? Modello.FORM200PLUS
|
||||
: Modello.FORM500,
|
||||
},
|
||||
});
|
||||
|
||||
return Response.json({ message: "fatto bastardo" });
|
||||
}
|
||||
|
|
@ -2,97 +2,49 @@
|
|||
|
||||
import ClientCard from "@/components/client-card";
|
||||
import DeviceCard from "@/components/device-card";
|
||||
import { Cliente, Intervento, Registratore } from "@/generated/prisma";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import { useEffect, useState, Suspense } from "react";
|
||||
|
||||
export default function Page() {
|
||||
function ClientComponent() {
|
||||
const searchParams = useSearchParams();
|
||||
const client = searchParams.get("client");
|
||||
const id = searchParams.get("client");
|
||||
const [cliente, setCliente] = useState<Cliente>();
|
||||
const [registratori, setRegistratori] = useState<Array<Registratore>>();
|
||||
|
||||
const clienti = [
|
||||
{
|
||||
name: "Savoldi Ettore",
|
||||
email: "savoldi.ettore@gmail.com",
|
||||
ragione_sociale: "Acconciature Uomo",
|
||||
p_iva: "13407520172",
|
||||
telefono: "0301547854",
|
||||
sede: "Via Umberto I 60/T, Flero (BS)",
|
||||
sede_url: "https://maps.app.goo.gl/9uNbw2a62ZCCjkQc7",
|
||||
contratto: "https://google.com",
|
||||
registratori: [
|
||||
{
|
||||
seriale: "80E100548745",
|
||||
acquisto: "15/10/2019",
|
||||
ultima_verifica: "15/10/2025",
|
||||
prossima_verifica: "15/10/2026",
|
||||
interventi: [
|
||||
{
|
||||
id: "0001",
|
||||
data: "15/10/2025",
|
||||
lavoro: "VERIFICA FISCALE - AGGIORNAMENTO FIRMWARE",
|
||||
fattura: true,
|
||||
},
|
||||
{
|
||||
id: "0002",
|
||||
data: "28/05/2025",
|
||||
lavoro: "SOSTITUZIONE DGFE",
|
||||
fattura: false,
|
||||
},
|
||||
{
|
||||
id: "0003",
|
||||
data: "08/10/2024",
|
||||
lavoro: "VERIFICA FISCALE",
|
||||
fattura: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Forno Tagliaferri",
|
||||
email: "info@tagliaferri.it",
|
||||
ragione_sociale: "Forno Tagliaferri",
|
||||
p_iva: "12901475639",
|
||||
telefono: "0309183573",
|
||||
sede: "Via Corso dei Martiri 11, Brescia (BS)",
|
||||
sede_url: "https://maps.app.goo.gl/9uNbw2a62ZCCjkQc7",
|
||||
contratto: "https://google.com",
|
||||
registratori: [
|
||||
{
|
||||
seriale: "80E1002587545",
|
||||
acquisto: "24/02/2020",
|
||||
ultima_verifica: "24/02/2025",
|
||||
prossima_verifica: "24/02/2026",
|
||||
interventi: [
|
||||
{
|
||||
id: "0004",
|
||||
data: "24/02/2025",
|
||||
lavoro: "VERIFICA FISCALE",
|
||||
fattura: true,
|
||||
},
|
||||
{
|
||||
id: "0005",
|
||||
data: "06/04/2025",
|
||||
lavoro: "SOSTITUZIONE DGFE",
|
||||
fattura: false,
|
||||
},
|
||||
{
|
||||
id: "0006",
|
||||
data: "24/02/2025",
|
||||
lavoro: "VERIFICA FISCALE - AGGIORNAMENTO FIRMWARE",
|
||||
fattura: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
useEffect(() => {
|
||||
async function getCliente() {
|
||||
const req = await fetch(`/api/clienti/${id}`);
|
||||
const data = await req.json();
|
||||
setCliente(data.cliente);
|
||||
setRegistratori(data.cliente.registratori);
|
||||
}
|
||||
|
||||
getCliente();
|
||||
}, [id]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-1 flex-col gap-4 p-4">
|
||||
<div className="*:data-[slot=card]:from-primary/5 *:data-[slot=card]:to-card dark:*:data-[slot=card]:bg-card grid grid-cols-1 gap-4 px-4 *:data-[slot=card]:bg-gradient-to-t *:data-[slot=card]:shadow-xs lg:px-6 @xl/main:grid-cols-2 @5xl/main:grid-cols-4">
|
||||
<ClientCard client={client} />
|
||||
<DeviceCard clienti={clienti} />
|
||||
{cliente ? <ClientCard cliente={cliente} /> : <></>}
|
||||
{registratori ? (
|
||||
registratori.map((registratore) => (
|
||||
<DeviceCard registratore={registratore} key={registratore.id} />
|
||||
))
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<Suspense
|
||||
fallback={<div className="p-8 text-center">Caricamento cliente...</div>}
|
||||
>
|
||||
<ClientComponent />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ import {
|
|||
} from "@/components/ui/table";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -2,18 +2,41 @@
|
|||
|
||||
import dynamic from "next/dynamic";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import { useEffect, useState, Suspense } from "react";
|
||||
import { Cliente } from "@/generated/prisma";
|
||||
|
||||
export default function Page() {
|
||||
function MapContent() {
|
||||
const MapWithNoSSR = dynamic(() => import("../../components/map"), {
|
||||
ssr: false,
|
||||
});
|
||||
|
||||
const [clienti, setClienti] = useState<Array<Cliente>>();
|
||||
const searchParams = useSearchParams();
|
||||
const client = searchParams.get("client");
|
||||
|
||||
useEffect(() => {
|
||||
async function getClienti() {
|
||||
const req = await fetch(`/api/clienti`);
|
||||
const data = await req.json();
|
||||
setClienti(data.clients);
|
||||
}
|
||||
|
||||
getClienti();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div id="map" className="w-full h-full border rounded-md m-0 p-0">
|
||||
<MapWithNoSSR highlight={client} />
|
||||
<MapWithNoSSR
|
||||
highlight={clienti?.find((cliente) => cliente.id == +(client || -1))}
|
||||
clienti={clienti || undefined}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<Suspense fallback={<div>Caricamento mappa...</div>}>
|
||||
<MapContent />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
153
src/components/add-client.tsx
Normal file
153
src/components/add-client.tsx
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
"use client";
|
||||
|
||||
import {
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useState } from "react";
|
||||
|
||||
const AddClientDialog = () => {
|
||||
const [open, setOpen] = useState<Boolean>(false);
|
||||
const [nome, setNome] = useState("");
|
||||
const [ragione_sociale, setRagione_sociale] = useState("");
|
||||
const [partita_iva, setPartita_iva] = useState("");
|
||||
const [telefono, setTelefono] = useState("");
|
||||
const [email, setEmail] = useState("");
|
||||
const [sede, setSede] = useState("");
|
||||
const [sede_url, setSede_url] = useState("");
|
||||
const [contratto, setContratto] = useState("");
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<form className="z-10">
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline">Aggiungi cliente</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Aggiungi cliente</DialogTitle>
|
||||
{/*<DialogDescription>
|
||||
Make changes to your profile here. Click save when you're
|
||||
done.
|
||||
</DialogDescription>*/}
|
||||
</DialogHeader>
|
||||
<div className="grid gap-4">
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="name">Nome</Label>
|
||||
<Input
|
||||
id="name"
|
||||
name="name"
|
||||
placeholder="Nome"
|
||||
onChange={(e) => setNome(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="ragione_sociale">Ragione sociale</Label>
|
||||
<Input
|
||||
id="ragione_sociale"
|
||||
name="ragione_sociale"
|
||||
placeholder="Ragione sociale"
|
||||
onChange={(e) => setRagione_sociale(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="p_iva">Partita IVA</Label>
|
||||
<Input
|
||||
id="p_iva"
|
||||
name="p_iva"
|
||||
placeholder="Partita IVA"
|
||||
onChange={(e) => setPartita_iva(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="tel">Numero di telefono</Label>
|
||||
<Input
|
||||
id="tel"
|
||||
name="tel"
|
||||
placeholder="Numero di telefono"
|
||||
onChange={(e) => setTelefono(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="tel">Indirizzo e-mail</Label>
|
||||
<Input
|
||||
id="mail"
|
||||
name="mail"
|
||||
placeholder="Indirizzo e-mail"
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="sede_desc">Sede (descrizione)</Label>
|
||||
<Input
|
||||
id="sede_desc"
|
||||
name="sede_desc"
|
||||
placeholder="Sede - descrizione"
|
||||
onChange={(e) => setSede(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="sede_link">Sede (link GMaps)</Label>
|
||||
<Input
|
||||
id="sede_link"
|
||||
name="sede_link"
|
||||
placeholder="Sede - link"
|
||||
onChange={(e) => setSede_url(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="contratto">Contratto (link)</Label>
|
||||
<Input
|
||||
id="contratto"
|
||||
name="contratto"
|
||||
placeholder="Contratto - link"
|
||||
onChange={(e) => setContratto(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline">Cancella</Button>
|
||||
</DialogClose>
|
||||
<Button
|
||||
onClick={async () => {
|
||||
const res = await fetch("/api/clienti", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
nome: nome,
|
||||
ragione_sociale: ragione_sociale,
|
||||
partita_iva: partita_iva,
|
||||
telefono: telefono,
|
||||
email: email,
|
||||
sede: sede,
|
||||
sede_url: sede_url,
|
||||
contratto: contratto,
|
||||
}),
|
||||
});
|
||||
|
||||
if (res.status == 200) {
|
||||
setOpen(false);
|
||||
}
|
||||
}}
|
||||
type="submit"
|
||||
>
|
||||
Aggiungi
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</form>
|
||||
</Dialog>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddClientDialog;
|
||||
117
src/components/add-intervento.tsx
Normal file
117
src/components/add-intervento.tsx
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
"use client";
|
||||
|
||||
import {
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
import { Plus } from "lucide-react";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useEffect, useState } from "react";
|
||||
import DatePicker from "./date-picker";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
|
||||
const AddInterventoDialog = ({ id }: { id: string }) => {
|
||||
//const [nome, setNome] = useState("");
|
||||
const [open, setOpen] = useState(false);
|
||||
const [data, setData] = useState<Date | undefined>(new Date());
|
||||
const [lavoro, setLavoro] = useState<string>("");
|
||||
const [fattura, setFattura] = useState<Boolean>(false);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Dialog>
|
||||
<form className="z-10">
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline" type="button">
|
||||
<Plus className="size-4" />
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Aggiungi intervento</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Aggiungi intervento</DialogTitle>
|
||||
{/*<DialogDescription>
|
||||
Make changes to your profile here. Click save when you're
|
||||
done.
|
||||
</DialogDescription>*/}
|
||||
</DialogHeader>
|
||||
<div className="grid gap-4">
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="date">Data</Label>
|
||||
<DatePicker
|
||||
open={open}
|
||||
setOpen={setOpen}
|
||||
date={data}
|
||||
setDate={setData}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="lavoro">Lavoro</Label>
|
||||
<Input
|
||||
id="lavoro"
|
||||
name="lavoro"
|
||||
placeholder="Lavoro eseguito..."
|
||||
onChange={(e) => setLavoro(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="gap-3 flex items-center mt-2">
|
||||
<Checkbox
|
||||
id="fattura"
|
||||
onCheckedChange={(checked) => {
|
||||
checked === "indeterminate"
|
||||
? setFattura(false)
|
||||
: checked
|
||||
? setFattura(true)
|
||||
: setFattura(false);
|
||||
}}
|
||||
/>
|
||||
<Label htmlFor="fattura">Fattura</Label>
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline">Cancella</Button>
|
||||
</DialogClose>
|
||||
<Button
|
||||
onClick={async () =>
|
||||
await fetch("/api/interventi", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
id: id,
|
||||
data: data,
|
||||
fattura: fattura,
|
||||
lavoro: lavoro,
|
||||
}),
|
||||
})
|
||||
}
|
||||
type="submit"
|
||||
>
|
||||
Aggiungi
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</form>
|
||||
</Dialog>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddInterventoDialog;
|
||||
132
src/components/add-registratore.tsx
Normal file
132
src/components/add-registratore.tsx
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
"use client";
|
||||
|
||||
import {
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
import { Plus } from "lucide-react";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useState } from "react";
|
||||
import DatePicker from "./date-picker";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import ModelPicker from "./model-picker";
|
||||
|
||||
const AddRegistratoreDialog = ({ id }: { id: Number }) => {
|
||||
//const [nome, setNome] = useState("");
|
||||
const [openData, setOpenData] = useState(false);
|
||||
const [openModello, setOpenModello] = useState(false);
|
||||
const [data, setData] = useState<Date | undefined>();
|
||||
const [seriale, setSeriale] = useState<string>("");
|
||||
const [modello, setModello] = useState<Date | undefined>();
|
||||
const [fattura, setFattura] = useState<Boolean>();
|
||||
|
||||
const modelli = [
|
||||
{
|
||||
value: "FORM100",
|
||||
label: "Form 100",
|
||||
},
|
||||
{
|
||||
value: "FORM200",
|
||||
label: "Form 200",
|
||||
},
|
||||
{
|
||||
value: "FORM200PLUS",
|
||||
label: "Form 200 Plus",
|
||||
},
|
||||
{
|
||||
value: "FORM500",
|
||||
label: "Form 500",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Dialog>
|
||||
<form className="z-10">
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline" type="button">
|
||||
<Plus className="size-4" />
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Aggiungi registratore</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Aggiungi registratore</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div className="grid gap-4">
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="seriale">Seriale</Label>
|
||||
<Input
|
||||
id="seriale"
|
||||
name="seriale"
|
||||
placeholder="Seriale"
|
||||
onChange={(e) => setSeriale(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="date">Data di acquisto</Label>
|
||||
<DatePicker
|
||||
open={openData}
|
||||
setOpen={setOpenData}
|
||||
date={data}
|
||||
setDate={setData}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="lavoro">Modello</Label>
|
||||
<ModelPicker
|
||||
open={openModello}
|
||||
setOpen={setOpenModello}
|
||||
value={modello}
|
||||
setValue={setModello}
|
||||
modelli={modelli}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline">Cancella</Button>
|
||||
</DialogClose>
|
||||
<Button
|
||||
onClick={async () =>
|
||||
await fetch("/api/registratori", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
id: id,
|
||||
seriale: seriale,
|
||||
data: data,
|
||||
modello: modello,
|
||||
}),
|
||||
})
|
||||
}
|
||||
type="submit"
|
||||
>
|
||||
Aggiungi
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</form>
|
||||
</Dialog>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddRegistratoreDialog;
|
||||
|
|
@ -26,18 +26,8 @@ import {
|
|||
} from "@/components/ui/tooltip";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { XIcon } from "lucide-react";
|
||||
import {
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Label } from "@/components/ui/label"
|
||||
import AddClientDialog from "./add-client";
|
||||
import { Cliente } from "@/generated/prisma";
|
||||
|
||||
const data = {
|
||||
user: {
|
||||
|
|
@ -68,8 +58,8 @@ const data = {
|
|||
url: "/client",
|
||||
icon: Home,
|
||||
isVisible: false,
|
||||
}
|
||||
],
|
||||
},
|
||||
] /*
|
||||
clienti: [
|
||||
{
|
||||
name: "Savoldi Ettore",
|
||||
|
|
@ -141,24 +131,30 @@ const data = {
|
|||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
],*/,
|
||||
};
|
||||
|
||||
export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
||||
const pathname = usePathname();
|
||||
const router = useRouter();
|
||||
const [clientPathname, setClientPathname] = useState("");
|
||||
const [clienti, setClienti] = React.useState(data.clienti);
|
||||
const [clienti, setClienti] = useState<Array<Cliente>>();
|
||||
const { setOpen } = useSidebar();
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const data = await fetch("/api/clienti");
|
||||
const x = await data.json();
|
||||
console.log(x.clients);
|
||||
setClienti(x.clients);
|
||||
console.log(clienti);
|
||||
})();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setClientPathname(pathname);
|
||||
}, [pathname]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log();
|
||||
}, [clientPathname]);
|
||||
|
||||
return (
|
||||
<Sidebar
|
||||
collapsible="icon"
|
||||
|
|
@ -207,34 +203,25 @@ export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
|||
return;
|
||||
}
|
||||
return (
|
||||
<SidebarMenuItem key={item.title}>
|
||||
<SidebarMenuButton
|
||||
tooltip={{
|
||||
children: item.title,
|
||||
hidden: false,
|
||||
}}
|
||||
onClick={() => {
|
||||
const clienti = data.clienti.sort(
|
||||
() => Math.random() - 0.5,
|
||||
);
|
||||
setClienti(
|
||||
clienti.slice(
|
||||
0,
|
||||
Math.max(5, Math.floor(Math.random() * 10) + 1),
|
||||
),
|
||||
);
|
||||
setOpen(true);
|
||||
if (clientPathname != item.url) {
|
||||
router.push(item.url);
|
||||
}
|
||||
}}
|
||||
isActive={clientPathname === item.url}
|
||||
className="px-2.5 md:px-2"
|
||||
>
|
||||
<item.icon />
|
||||
<span>{item.title}</span>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
<SidebarMenuItem key={item.title}>
|
||||
<SidebarMenuButton
|
||||
tooltip={{
|
||||
children: item.title,
|
||||
hidden: false,
|
||||
}}
|
||||
onClick={() => {
|
||||
setOpen(true);
|
||||
if (clientPathname != item.url) {
|
||||
router.push(item.url);
|
||||
}
|
||||
}}
|
||||
isActive={clientPathname === item.url}
|
||||
className="px-2.5 md:px-2"
|
||||
>
|
||||
<item.icon />
|
||||
<span>{item.title}</span>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
);
|
||||
})}
|
||||
</SidebarMenu>
|
||||
|
|
@ -257,99 +244,53 @@ export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
|||
</div>
|
||||
</div>
|
||||
<div className="flex flex-row max-h-max gap-2">
|
||||
<SidebarInput placeholder="Digita per cercare..." className="h-full" />
|
||||
<SidebarInput
|
||||
placeholder="Digita per cercare..."
|
||||
className="h-full"
|
||||
/>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button variant="outline" onClick={() => {
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
if (clientPathname.split("/")[1] == "map") {
|
||||
router.replace('/map', undefined);
|
||||
router.replace("/map", undefined);
|
||||
}
|
||||
}}>
|
||||
<XIcon className="size-4" />
|
||||
</Button>
|
||||
}}
|
||||
>
|
||||
<XIcon className="size-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Resetta ricerca</p>
|
||||
<p>Resetta ricerca</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div>
|
||||
<Dialog>
|
||||
<form className="z-10">
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline">Aggiungi cliente</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Aggiungi cliente</DialogTitle>
|
||||
{/*<DialogDescription>
|
||||
Make changes to your profile here. Click save when you're
|
||||
done.
|
||||
</DialogDescription>*/}
|
||||
</DialogHeader>
|
||||
<div className="grid gap-4">
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="name">Nome</Label>
|
||||
<Input id="name" name="name" placeholder="Nome" />
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="ragione_sociale">Ragione sociale</Label>
|
||||
<Input id="ragione_sociale" name="ragione_sociale" placeholder="Ragione sociale" />
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="p_iva">Partita IVA</Label>
|
||||
<Input id="p_iva" name="p_iva" placeholder="Partita IVA" />
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="tel">Numero di telefono</Label>
|
||||
<Input id="tel" name="tel" placeholder="Numero di telefono" />
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="sede_desc">Sede (descrizione)</Label>
|
||||
<Input id="sede_desc" name="sede_desc" placeholder="Sede - descrizione" />
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="sede_link">Sede (link GMaps)</Label>
|
||||
<Input id="sede_link" name="sede_link" placeholder="Sede - link" />
|
||||
</div>
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="contratto">Contratto (link)</Label>
|
||||
<Input id="contratto" name="contratto" placeholder="Contratto - link" />
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline">Cancella</Button>
|
||||
</DialogClose>
|
||||
<Button type="submit">Aggiungi</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</form>
|
||||
</Dialog>
|
||||
</div>
|
||||
<AddClientDialog />
|
||||
</SidebarHeader>
|
||||
<SidebarContent>
|
||||
<SidebarGroup className="px-0">
|
||||
<SidebarGroupContent className="">
|
||||
{clienti.map((cliente) => (
|
||||
{clienti?.map((cliente) => (
|
||||
<span
|
||||
onClick={() => {
|
||||
let path = clientPathname.split("/")[1];
|
||||
if (path == "dashboard") {
|
||||
path = "client"
|
||||
if (path == "dashboard" || path == "") {
|
||||
path = "client";
|
||||
}
|
||||
router.push(`/${path}?client=${cliente.name}`)
|
||||
router.push(`/${path}?client=${cliente.id}`);
|
||||
}}
|
||||
key={cliente.name}
|
||||
key={cliente.id}
|
||||
className="hover:cursor-pointer w-11/12 mx-auto rounded-md hover:bg-sidebar-accent hover:text-sidebar-accent-foreground flex flex-col items-start gap-2 border-b p-4 text-sm leading-tight whitespace-nowrap last:border-b-0"
|
||||
>
|
||||
<span className="font-medium">{cliente.name}</span>
|
||||
<span className="font-medium">{cliente.ragione_sociale}</span>
|
||||
<div className="flex w-full items-center gap-2">
|
||||
<span className="text-xs">{cliente.sede}</span>
|
||||
<span className="text-xs">
|
||||
{cliente.sede.length > 35
|
||||
? cliente.sede.substring(0, 35) + "..."
|
||||
: cliente.sede}
|
||||
</span>
|
||||
</div>
|
||||
<span className="line-clamp-2 w-[260px] text-xs whitespace-break-spaces">
|
||||
{cliente.registratori[0].prossima_verifica}
|
||||
</span>
|
||||
</span>
|
||||
))}
|
||||
</SidebarGroupContent>
|
||||
|
|
|
|||
|
|
@ -12,85 +12,70 @@ import {
|
|||
} from "@/components/ui/tooltip";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Edit, Plus } from "lucide-react";
|
||||
import { Cliente } from "@/generated/prisma";
|
||||
import AddRegistratoreDialog from "./add-registratore";
|
||||
|
||||
const ClientCard = ({client}: {client: any}) => {
|
||||
return (
|
||||
<Card className="@container/card">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-xl font-semibold tabular-nums @[250px]/card:text-2xl">
|
||||
{client}
|
||||
</CardTitle>
|
||||
<CardAction className="flex items-center gap-4">
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button variant="outline">
|
||||
<Edit className="size-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Modifica dettagli</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button variant="outline">
|
||||
<Plus className="size-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Aggiungi registratore</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</CardAction>
|
||||
</CardHeader>
|
||||
<CardContent className="flex items-start gap-20 text-md">
|
||||
<div className="flex-col items-start gap-1.5 text-md">
|
||||
<div className="text-muted-foreground">Ragione Sociale</div>
|
||||
<div className="line-clamp-1 flex gap-2 font-medium">
|
||||
Acconciature Uomo
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-col items-start gap-1.5 text-md">
|
||||
<div className="text-muted-foreground">Partita IVA</div>
|
||||
<div className="line-clamp-1 flex gap-2 font-medium">
|
||||
13407520172
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-col items-start gap-1.5 text-md">
|
||||
<div className="text-muted-foreground">
|
||||
Numero di Telefono
|
||||
</div>
|
||||
<div className="line-clamp-1 flex gap-2 font-medium">
|
||||
0301547854
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-col items-start gap-1.5 text-md">
|
||||
<div className="text-muted-foreground">Sede</div>
|
||||
<div className="line-clamp-1 flex gap-2 font-medium">
|
||||
<a
|
||||
className="text-blue-700 italic underline"
|
||||
target="blank"
|
||||
href="https://maps.app.goo.gl/9uNbw2a62ZCCjkQc7"
|
||||
>
|
||||
Via Umberto I 60/T, Flero (BS)
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-col items-start gap-1.5 text-md">
|
||||
<div className="text-muted-foreground">Contratto</div>
|
||||
<div className="line-clamp-1 flex gap-2 font-medium">
|
||||
<a
|
||||
className="text-blue-700 italic underline"
|
||||
target="blank"
|
||||
href="https://google.com"
|
||||
>
|
||||
LINK
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
const ClientCard = ({ cliente }: { cliente: Cliente }) => {
|
||||
return (
|
||||
<Card className="@container/card">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-xl font-semibold tabular-nums @[250px]/card:text-2xl">
|
||||
{cliente.ragione_sociale}
|
||||
</CardTitle>
|
||||
<CardAction className="flex items-center gap-4">
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button variant="outline">
|
||||
<Edit className="size-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Modifica dettagli</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<AddRegistratoreDialog id={cliente.id} />
|
||||
</CardAction>
|
||||
</CardHeader>
|
||||
<CardContent className="flex items-start gap-20 text-md">
|
||||
<div className="flex-col items-start gap-1.5 text-md">
|
||||
<div className="text-muted-foreground">Partita IVA</div>
|
||||
<div className="line-clamp-1 flex gap-2 font-medium">
|
||||
{cliente.partita_iva}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-col items-start gap-1.5 text-md">
|
||||
<div className="text-muted-foreground">Numero di Telefono</div>
|
||||
<div className="line-clamp-1 flex gap-2 font-medium">
|
||||
{cliente.telefono}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-col items-start gap-1.5 text-md">
|
||||
<div className="text-muted-foreground">Sede</div>
|
||||
<div className="line-clamp-1 flex gap-2 font-medium">
|
||||
<a
|
||||
className="text-blue-700 italic underline"
|
||||
target="blank"
|
||||
href={cliente.sede_url}
|
||||
>
|
||||
{cliente.sede}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-col items-start gap-1.5 text-md">
|
||||
<div className="text-muted-foreground">Contratto</div>
|
||||
<div className="line-clamp-1 flex gap-2 font-medium">
|
||||
<a
|
||||
className="text-blue-700 italic underline"
|
||||
target="blank"
|
||||
href={cliente.contratto}
|
||||
>
|
||||
LINK
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default ClientCard;
|
||||
49
src/components/date-picker.tsx
Normal file
49
src/components/date-picker.tsx
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover";
|
||||
import { Calendar } from "@/components/ui/calendar";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { ChevronDownIcon } from "lucide-react";
|
||||
import { Dispatch, SetStateAction } from "react";
|
||||
|
||||
const DatePicker = ({
|
||||
open,
|
||||
setOpen,
|
||||
date,
|
||||
setDate,
|
||||
}: {
|
||||
open: boolean;
|
||||
setOpen: Dispatch<SetStateAction<boolean>>;
|
||||
date: Date | undefined;
|
||||
setDate: Dispatch<SetStateAction<Date | undefined>>;
|
||||
}) => {
|
||||
return (
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
id="date"
|
||||
className="w-full justify-between font-normal"
|
||||
>
|
||||
{date ? date.toLocaleDateString() : "Select date"}
|
||||
<ChevronDownIcon />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-auto overflow-hidden p-0" align="start">
|
||||
<Calendar
|
||||
mode="single"
|
||||
selected={date}
|
||||
captionLayout="dropdown"
|
||||
onSelect={(date) => {
|
||||
setDate(date);
|
||||
setOpen(false);
|
||||
}}
|
||||
/>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
export default DatePicker;
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import {
|
||||
Card,
|
||||
CardAction,
|
||||
|
|
@ -24,146 +26,113 @@ import { Button } from "@/components/ui/button";
|
|||
import { Edit, Plus } from "lucide-react";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import { Cliente, Registratore } from "@/generated/prisma";
|
||||
import AddInterventoDialog from "./add-intervento";
|
||||
|
||||
type Invervento = {
|
||||
id: string,
|
||||
data: string,
|
||||
lavoro: string,
|
||||
fattura: boolean
|
||||
}
|
||||
|
||||
type Registratore = {
|
||||
seriale: string,
|
||||
acquisto: string,
|
||||
ultima_verifica: string,
|
||||
prossima_verifica: string,
|
||||
interventi: Array<Invervento>
|
||||
}
|
||||
|
||||
type Cliente = {
|
||||
name: string,
|
||||
email: string,
|
||||
ragione_sociale: string,
|
||||
p_iva: string,
|
||||
telefono: string,
|
||||
sede: string,
|
||||
sede_url: string,
|
||||
contratto: string,
|
||||
registratori: Array<Registratore>
|
||||
}
|
||||
|
||||
const DeviceCard = ({clienti}: {clienti:Array<Cliente>}) => {
|
||||
const searchParams = useSearchParams();
|
||||
const client = searchParams.get("client");
|
||||
|
||||
return (
|
||||
<Card className="@container/card">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-xl font-semibold tabular-nums @[250px]/card:text-2xl">
|
||||
FORM 100
|
||||
</CardTitle>
|
||||
<CardAction className="flex items-center gap-4">
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button variant="outline">
|
||||
<Edit className="size-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Modifica dettagli</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button variant="outline">
|
||||
<Plus className="size-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Aggiungi intervento</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</CardAction>
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col gap-5 text-md">
|
||||
<div className="flex items-start gap-20 text-md">
|
||||
<div className="flex-col items-start gap-1.5 text-md">
|
||||
<div className="text-muted-foreground">Seriale</div>
|
||||
<div className="line-clamp-1 flex gap-2 font-medium">
|
||||
80E100548745
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-col items-start gap-1.5 text-md">
|
||||
<div className="text-muted-foreground">Data acquisto</div>
|
||||
<div className="line-clamp-1 flex gap-2 font-medium">
|
||||
15/10/2019
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-col items-start gap-1.5 text-md">
|
||||
<div className="text-muted-foreground">Ultima verifica</div>
|
||||
<div className="line-clamp-1 flex gap-2 font-medium">
|
||||
15/10/2025
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-col items-start gap-1.5 text-md">
|
||||
<div className="text-muted-foreground">
|
||||
Prossima verifica
|
||||
</div>
|
||||
<div className="line-clamp-1 flex gap-2 font-medium">
|
||||
15/10/2026
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<Table className={cn("caption-top")}>
|
||||
<TableCaption className="text-lg text-start">
|
||||
Lista interventi
|
||||
</TableCaption>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="w-[100px]">Data</TableHead>
|
||||
<TableHead>Lavoro</TableHead>
|
||||
<TableHead className="text-right">Fattura</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{clienti
|
||||
.find(
|
||||
(cliente) =>
|
||||
cliente.name == decodeURIComponent(client?.toString() || ""),
|
||||
)
|
||||
?.registratori[0].interventi.map((intervento) => (
|
||||
<TableRow key={intervento.id}>
|
||||
<TableCell className="font-medium">
|
||||
{intervento.data}
|
||||
</TableCell>
|
||||
<TableCell>{intervento.lavoro}</TableCell>
|
||||
<TableCell className="text-right">
|
||||
<Checkbox checked={intervento.fattura} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="flex gap-5">
|
||||
<Button
|
||||
variant="destructive"
|
||||
className="hover:bg-red-800 transition-colors"
|
||||
>
|
||||
DISMETTI
|
||||
</Button>
|
||||
<Button
|
||||
variant="destructive"
|
||||
className="hover:bg-red-800 transition-colors"
|
||||
>
|
||||
ROTTAMA
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
const DeviceCard = ({ registratore }: { registratore: Registratore }) => {
|
||||
return (
|
||||
<Card className="@container/card">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-xl font-semibold tabular-nums @[250px]/card:text-2xl">
|
||||
{registratore.modello}
|
||||
</CardTitle>
|
||||
<CardAction className="flex items-center gap-4">
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button variant="outline">
|
||||
<Edit className="size-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Modifica dettagli</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<AddInterventoDialog id={registratore.id} />
|
||||
</CardAction>
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col gap-5 text-md">
|
||||
<div className="flex items-start gap-20 text-md">
|
||||
<div className="flex-col items-start gap-1.5 text-md">
|
||||
<div className="text-muted-foreground">Seriale</div>
|
||||
<div className="line-clamp-1 flex gap-2 font-medium">
|
||||
{registratore.id}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-col items-start gap-1.5 text-md">
|
||||
<div className="text-muted-foreground">Data acquisto</div>
|
||||
<div className="line-clamp-1 flex gap-2 font-medium">
|
||||
{registratore.data_acquisto
|
||||
? new Date(registratore.data_acquisto).toLocaleDateString(
|
||||
"it-IT",
|
||||
)
|
||||
: "--"}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-col items-start gap-1.5 text-md">
|
||||
<div className="text-muted-foreground">Ultima verifica</div>
|
||||
<div className="line-clamp-1 flex gap-2 font-medium">
|
||||
{registratore.ultima_verifica
|
||||
? new Date(registratore.ultima_verifica).toLocaleDateString(
|
||||
"it-IT",
|
||||
)
|
||||
: "--"}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-col items-start gap-1.5 text-md">
|
||||
<div className="text-muted-foreground">Prossima verifica</div>
|
||||
<div className="line-clamp-1 flex gap-2 font-medium">
|
||||
{registratore.prossima_verifica
|
||||
? new Date(registratore.prossima_verifica).toLocaleDateString(
|
||||
"it-IT",
|
||||
)
|
||||
: "--"}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<Table className={cn("caption-top")}>
|
||||
<TableCaption className="text-lg text-start">
|
||||
Lista interventi
|
||||
</TableCaption>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="w-[100px]">Data</TableHead>
|
||||
<TableHead>Lavoro</TableHead>
|
||||
<TableHead className="text-right">Fattura</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{registratore.interventi.map((intervento) => (
|
||||
<TableRow key={intervento.id}>
|
||||
<TableCell className="font-medium">
|
||||
{new Date(intervento.data).toLocaleDateString("it-IT")}
|
||||
</TableCell>
|
||||
<TableCell>{intervento.lavoro}</TableCell>
|
||||
<TableCell className="text-right">
|
||||
<Checkbox checked={intervento.fattura} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="flex gap-5">
|
||||
<Button
|
||||
variant="destructive"
|
||||
className="hover:bg-red-800 transition-colors"
|
||||
>
|
||||
DISMETTI
|
||||
</Button>
|
||||
<Button
|
||||
variant="destructive"
|
||||
className="hover:bg-red-800 transition-colors"
|
||||
>
|
||||
ROTTAMA
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeviceCard;
|
||||
|
|
@ -8,8 +8,15 @@ import {
|
|||
} from "@/components/ui/tooltip";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Map as MapIcon } from "lucide-react";
|
||||
import { Cliente } from "@/generated/prisma";
|
||||
|
||||
const Map = ({highlight}: {highlight?: string}) => {
|
||||
const Map = ({
|
||||
highlight,
|
||||
clienti,
|
||||
}: {
|
||||
highlight?: Cliente;
|
||||
clienti?: Array<Cliente>;
|
||||
}) => {
|
||||
const positions = [
|
||||
{
|
||||
name: "Autogeneral",
|
||||
|
|
@ -38,9 +45,6 @@ const Map = ({highlight}: {highlight?: string}) => {
|
|||
},
|
||||
];
|
||||
|
||||
console.log(highlight);
|
||||
console.log(positions.find((client) => client.name == highlight));
|
||||
|
||||
const customMarker = new Icon({
|
||||
iconUrl: "marker-icon-red.png",
|
||||
iconAnchor: [10, 20],
|
||||
|
|
@ -49,7 +53,11 @@ const Map = ({highlight}: {highlight?: string}) => {
|
|||
|
||||
return (
|
||||
<MapContainer
|
||||
center={highlight ? positions.find((client) => client.name == highlight)?.position : [45.54157745559809, 10.211896906975962]}
|
||||
center={
|
||||
highlight
|
||||
? [highlight.lat, highlight.lon]
|
||||
: [45.54157745559809, 10.211896906975962]
|
||||
}
|
||||
zoom={13}
|
||||
scrollWheelZoom={true}
|
||||
className="m-0 p-0 h-[99%] w-[99%] mx-[0.5%] my-[0.5%] rounded-md z-0"
|
||||
|
|
@ -58,9 +66,50 @@ const Map = ({highlight}: {highlight?: string}) => {
|
|||
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
url={`https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png`}
|
||||
/>
|
||||
{ highlight == null ? positions.map((client) => (
|
||||
{highlight == null ? (
|
||||
clienti ? (
|
||||
clienti.map((client) => (
|
||||
<Marker
|
||||
position={[client.lat, client.lon]}
|
||||
draggable={false}
|
||||
animate={false}
|
||||
icon={customMarker}
|
||||
key={client.id}
|
||||
>
|
||||
<Popup className="">
|
||||
<div className="flex flex-row gap-5">
|
||||
<div>
|
||||
<span className="block text-sm font-bold">
|
||||
{client.ragione_sociale}
|
||||
</span>
|
||||
<div className="flex gap-2">
|
||||
<span className="text-xs font-semibold">P.IVA</span>
|
||||
<span className="text-xs">{client.partita_iva}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<a href={client.sede_url} target="blank">
|
||||
<Button variant="outline">
|
||||
<MapIcon className="size-4" />
|
||||
</Button>
|
||||
</a>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Resetta ricerca</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</Popup>
|
||||
</Marker>
|
||||
))
|
||||
) : (
|
||||
<></>
|
||||
)
|
||||
) : (
|
||||
<Marker
|
||||
position={client.position}
|
||||
position={[highlight.lat, highlight.lon]}
|
||||
draggable={false}
|
||||
animate={false}
|
||||
icon={customMarker}
|
||||
|
|
@ -68,7 +117,9 @@ const Map = ({highlight}: {highlight?: string}) => {
|
|||
<Popup className="">
|
||||
<div className="flex flex-row gap-5">
|
||||
<div>
|
||||
<span className="block text-sm font-bold">{client.name}</span>
|
||||
<span className="block text-sm font-bold">
|
||||
{highlight.ragione_sociale}
|
||||
</span>
|
||||
<div className="flex gap-2">
|
||||
<span className="text-xs font-semibold">P.IVA</span>
|
||||
<span className="text-xs">03417520172</span>
|
||||
|
|
@ -77,52 +128,20 @@ const Map = ({highlight}: {highlight?: string}) => {
|
|||
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<a href={client.sede_url} target="blank">
|
||||
<Button variant="outline">
|
||||
<MapIcon className="size-4" />
|
||||
</Button>
|
||||
</a>
|
||||
<a href={highlight.sede_url} target="blank">
|
||||
<Button variant="outline">
|
||||
<MapIcon className="size-4" />
|
||||
</Button>
|
||||
</a>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Resetta ricerca</p>
|
||||
<p>Resetta ricerca</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</Popup>
|
||||
</Marker>
|
||||
)) :
|
||||
<Marker
|
||||
position={positions.find((client) => client.name == highlight)?.position}
|
||||
draggable={false}
|
||||
animate={false}
|
||||
icon={customMarker}
|
||||
>
|
||||
<Popup className="">
|
||||
<div className="flex flex-row gap-5">
|
||||
<div>
|
||||
<span className="block text-sm font-bold">{positions.find((client) => client.name == highlight)?.name}</span>
|
||||
<div className="flex gap-2">
|
||||
<span className="text-xs font-semibold">P.IVA</span>
|
||||
<span className="text-xs">03417520172</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<a href={positions.find((client) => client.name == highlight)?.sede_url} target="blank">
|
||||
<Button variant="outline">
|
||||
<MapIcon className="size-4" />
|
||||
</Button>
|
||||
</a>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Resetta ricerca</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</Popup>
|
||||
</Marker>
|
||||
}
|
||||
)}
|
||||
</MapContainer>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
79
src/components/model-picker.tsx
Normal file
79
src/components/model-picker.tsx
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
import { Check, ChevronsUpDown } from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Command,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
} from "@/components/ui/command";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover";
|
||||
import { Dispatch, SetStateAction } from "react";
|
||||
|
||||
const ModelPicker = ({
|
||||
open,
|
||||
setOpen,
|
||||
value,
|
||||
setValue,
|
||||
modelli,
|
||||
}: {
|
||||
open: boolean;
|
||||
setOpen: Dispatch<SetStateAction<boolean>>;
|
||||
value: any;
|
||||
setValue: Dispatch<SetStateAction<any>>;
|
||||
modelli: Array<any>;
|
||||
}) => {
|
||||
return (
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
aria-expanded={open}
|
||||
className="w-full justify-between"
|
||||
>
|
||||
{value
|
||||
? modelli.find((modello) => modello.value === value)?.label
|
||||
: "Select framework..."}
|
||||
<ChevronsUpDown className="opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-full p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder="Search framework..." className="h-9" />
|
||||
<CommandList>
|
||||
<CommandEmpty>No framework found.</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{modelli.map((modello) => (
|
||||
<CommandItem
|
||||
key={modello.value}
|
||||
value={modello.value}
|
||||
onSelect={(currentValue) => {
|
||||
setValue(currentValue === value ? "" : currentValue);
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
{modello.label}
|
||||
<Check
|
||||
className={cn(
|
||||
"ml-auto",
|
||||
value === modello.value ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
/>
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
export default ModelPicker;
|
||||
216
src/components/ui/calendar.tsx
Normal file
216
src/components/ui/calendar.tsx
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import {
|
||||
ChevronDownIcon,
|
||||
ChevronLeftIcon,
|
||||
ChevronRightIcon,
|
||||
} from "lucide-react"
|
||||
import { DayButton, DayPicker, getDefaultClassNames } from "react-day-picker"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { Button, buttonVariants } from "@/components/ui/button"
|
||||
|
||||
function Calendar({
|
||||
className,
|
||||
classNames,
|
||||
showOutsideDays = true,
|
||||
captionLayout = "label",
|
||||
buttonVariant = "ghost",
|
||||
formatters,
|
||||
components,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DayPicker> & {
|
||||
buttonVariant?: React.ComponentProps<typeof Button>["variant"]
|
||||
}) {
|
||||
const defaultClassNames = getDefaultClassNames()
|
||||
|
||||
return (
|
||||
<DayPicker
|
||||
showOutsideDays={showOutsideDays}
|
||||
className={cn(
|
||||
"bg-background group/calendar p-3 [--cell-size:--spacing(8)] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent",
|
||||
String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
|
||||
String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
|
||||
className
|
||||
)}
|
||||
captionLayout={captionLayout}
|
||||
formatters={{
|
||||
formatMonthDropdown: (date) =>
|
||||
date.toLocaleString("default", { month: "short" }),
|
||||
...formatters,
|
||||
}}
|
||||
classNames={{
|
||||
root: cn("w-fit", defaultClassNames.root),
|
||||
months: cn(
|
||||
"flex gap-4 flex-col md:flex-row relative",
|
||||
defaultClassNames.months
|
||||
),
|
||||
month: cn("flex flex-col w-full gap-4", defaultClassNames.month),
|
||||
nav: cn(
|
||||
"flex items-center gap-1 w-full absolute top-0 inset-x-0 justify-between",
|
||||
defaultClassNames.nav
|
||||
),
|
||||
button_previous: cn(
|
||||
buttonVariants({ variant: buttonVariant }),
|
||||
"size-(--cell-size) aria-disabled:opacity-50 p-0 select-none",
|
||||
defaultClassNames.button_previous
|
||||
),
|
||||
button_next: cn(
|
||||
buttonVariants({ variant: buttonVariant }),
|
||||
"size-(--cell-size) aria-disabled:opacity-50 p-0 select-none",
|
||||
defaultClassNames.button_next
|
||||
),
|
||||
month_caption: cn(
|
||||
"flex items-center justify-center h-(--cell-size) w-full px-(--cell-size)",
|
||||
defaultClassNames.month_caption
|
||||
),
|
||||
dropdowns: cn(
|
||||
"w-full flex items-center text-sm font-medium justify-center h-(--cell-size) gap-1.5",
|
||||
defaultClassNames.dropdowns
|
||||
),
|
||||
dropdown_root: cn(
|
||||
"relative has-focus:border-ring border border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] rounded-md",
|
||||
defaultClassNames.dropdown_root
|
||||
),
|
||||
dropdown: cn(
|
||||
"absolute bg-popover inset-0 opacity-0",
|
||||
defaultClassNames.dropdown
|
||||
),
|
||||
caption_label: cn(
|
||||
"select-none font-medium",
|
||||
captionLayout === "label"
|
||||
? "text-sm"
|
||||
: "rounded-md pl-2 pr-1 flex items-center gap-1 text-sm h-8 [&>svg]:text-muted-foreground [&>svg]:size-3.5",
|
||||
defaultClassNames.caption_label
|
||||
),
|
||||
table: "w-full border-collapse",
|
||||
weekdays: cn("flex", defaultClassNames.weekdays),
|
||||
weekday: cn(
|
||||
"text-muted-foreground rounded-md flex-1 font-normal text-[0.8rem] select-none",
|
||||
defaultClassNames.weekday
|
||||
),
|
||||
week: cn("flex w-full mt-2", defaultClassNames.week),
|
||||
week_number_header: cn(
|
||||
"select-none w-(--cell-size)",
|
||||
defaultClassNames.week_number_header
|
||||
),
|
||||
week_number: cn(
|
||||
"text-[0.8rem] select-none text-muted-foreground",
|
||||
defaultClassNames.week_number
|
||||
),
|
||||
day: cn(
|
||||
"relative w-full h-full p-0 text-center [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none",
|
||||
props.showWeekNumber
|
||||
? "[&:nth-child(2)[data-selected=true]_button]:rounded-l-md"
|
||||
: "[&:first-child[data-selected=true]_button]:rounded-l-md",
|
||||
defaultClassNames.day
|
||||
),
|
||||
range_start: cn(
|
||||
"rounded-l-md bg-accent",
|
||||
defaultClassNames.range_start
|
||||
),
|
||||
range_middle: cn("rounded-none", defaultClassNames.range_middle),
|
||||
range_end: cn("rounded-r-md bg-accent", defaultClassNames.range_end),
|
||||
today: cn(
|
||||
"bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none",
|
||||
defaultClassNames.today
|
||||
),
|
||||
outside: cn(
|
||||
"text-muted-foreground aria-selected:text-muted-foreground",
|
||||
defaultClassNames.outside
|
||||
),
|
||||
disabled: cn(
|
||||
"text-muted-foreground opacity-50",
|
||||
defaultClassNames.disabled
|
||||
),
|
||||
hidden: cn("invisible", defaultClassNames.hidden),
|
||||
...classNames,
|
||||
}}
|
||||
components={{
|
||||
Root: ({ className, rootRef, ...props }) => {
|
||||
return (
|
||||
<div
|
||||
data-slot="calendar"
|
||||
ref={rootRef}
|
||||
className={cn(className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
},
|
||||
Chevron: ({ className, orientation, ...props }) => {
|
||||
if (orientation === "left") {
|
||||
return (
|
||||
<ChevronLeftIcon className={cn("size-4", className)} {...props} />
|
||||
)
|
||||
}
|
||||
|
||||
if (orientation === "right") {
|
||||
return (
|
||||
<ChevronRightIcon
|
||||
className={cn("size-4", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<ChevronDownIcon className={cn("size-4", className)} {...props} />
|
||||
)
|
||||
},
|
||||
DayButton: CalendarDayButton,
|
||||
WeekNumber: ({ children, ...props }) => {
|
||||
return (
|
||||
<td {...props}>
|
||||
<div className="flex size-(--cell-size) items-center justify-center text-center">
|
||||
{children}
|
||||
</div>
|
||||
</td>
|
||||
)
|
||||
},
|
||||
...components,
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CalendarDayButton({
|
||||
className,
|
||||
day,
|
||||
modifiers,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DayButton>) {
|
||||
const defaultClassNames = getDefaultClassNames()
|
||||
|
||||
const ref = React.useRef<HTMLButtonElement>(null)
|
||||
React.useEffect(() => {
|
||||
if (modifiers.focused) ref.current?.focus()
|
||||
}, [modifiers.focused])
|
||||
|
||||
return (
|
||||
<Button
|
||||
ref={ref}
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
data-day={day.date.toLocaleDateString()}
|
||||
data-selected-single={
|
||||
modifiers.selected &&
|
||||
!modifiers.range_start &&
|
||||
!modifiers.range_end &&
|
||||
!modifiers.range_middle
|
||||
}
|
||||
data-range-start={modifiers.range_start}
|
||||
data-range-end={modifiers.range_end}
|
||||
data-range-middle={modifiers.range_middle}
|
||||
className={cn(
|
||||
"data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 dark:hover:text-accent-foreground flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] data-[range-end=true]:rounded-md data-[range-end=true]:rounded-r-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md data-[range-start=true]:rounded-l-md [&>span]:text-xs [&>span]:opacity-70",
|
||||
defaultClassNames.day,
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export { Calendar, CalendarDayButton }
|
||||
184
src/components/ui/command.tsx
Normal file
184
src/components/ui/command.tsx
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { Command as CommandPrimitive } from "cmdk"
|
||||
import { SearchIcon } from "lucide-react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog"
|
||||
|
||||
function Command({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof CommandPrimitive>) {
|
||||
return (
|
||||
<CommandPrimitive
|
||||
data-slot="command"
|
||||
className={cn(
|
||||
"bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CommandDialog({
|
||||
title = "Command Palette",
|
||||
description = "Search for a command to run...",
|
||||
children,
|
||||
className,
|
||||
showCloseButton = true,
|
||||
...props
|
||||
}: React.ComponentProps<typeof Dialog> & {
|
||||
title?: string
|
||||
description?: string
|
||||
className?: string
|
||||
showCloseButton?: boolean
|
||||
}) {
|
||||
return (
|
||||
<Dialog {...props}>
|
||||
<DialogHeader className="sr-only">
|
||||
<DialogTitle>{title}</DialogTitle>
|
||||
<DialogDescription>{description}</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogContent
|
||||
className={cn("overflow-hidden p-0", className)}
|
||||
showCloseButton={showCloseButton}
|
||||
>
|
||||
<Command className="[&_[cmdk-group-heading]]:text-muted-foreground **:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
|
||||
{children}
|
||||
</Command>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
function CommandInput({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof CommandPrimitive.Input>) {
|
||||
return (
|
||||
<div
|
||||
data-slot="command-input-wrapper"
|
||||
className="flex h-9 items-center gap-2 border-b px-3"
|
||||
>
|
||||
<SearchIcon className="size-4 shrink-0 opacity-50" />
|
||||
<CommandPrimitive.Input
|
||||
data-slot="command-input"
|
||||
className={cn(
|
||||
"placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function CommandList({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof CommandPrimitive.List>) {
|
||||
return (
|
||||
<CommandPrimitive.List
|
||||
data-slot="command-list"
|
||||
className={cn(
|
||||
"max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CommandEmpty({
|
||||
...props
|
||||
}: React.ComponentProps<typeof CommandPrimitive.Empty>) {
|
||||
return (
|
||||
<CommandPrimitive.Empty
|
||||
data-slot="command-empty"
|
||||
className="py-6 text-center text-sm"
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CommandGroup({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof CommandPrimitive.Group>) {
|
||||
return (
|
||||
<CommandPrimitive.Group
|
||||
data-slot="command-group"
|
||||
className={cn(
|
||||
"text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CommandSeparator({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof CommandPrimitive.Separator>) {
|
||||
return (
|
||||
<CommandPrimitive.Separator
|
||||
data-slot="command-separator"
|
||||
className={cn("bg-border -mx-1 h-px", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CommandItem({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof CommandPrimitive.Item>) {
|
||||
return (
|
||||
<CommandPrimitive.Item
|
||||
data-slot="command-item"
|
||||
className={cn(
|
||||
"data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CommandShortcut({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<"span">) {
|
||||
return (
|
||||
<span
|
||||
data-slot="command-shortcut"
|
||||
className={cn(
|
||||
"text-muted-foreground ml-auto text-xs tracking-widest",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
Command,
|
||||
CommandDialog,
|
||||
CommandInput,
|
||||
CommandList,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandItem,
|
||||
CommandShortcut,
|
||||
CommandSeparator,
|
||||
}
|
||||
48
src/components/ui/popover.tsx
Normal file
48
src/components/ui/popover.tsx
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import * as PopoverPrimitive from "@radix-ui/react-popover"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function Popover({
|
||||
...props
|
||||
}: React.ComponentProps<typeof PopoverPrimitive.Root>) {
|
||||
return <PopoverPrimitive.Root data-slot="popover" {...props} />
|
||||
}
|
||||
|
||||
function PopoverTrigger({
|
||||
...props
|
||||
}: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {
|
||||
return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />
|
||||
}
|
||||
|
||||
function PopoverContent({
|
||||
className,
|
||||
align = "center",
|
||||
sideOffset = 4,
|
||||
...props
|
||||
}: React.ComponentProps<typeof PopoverPrimitive.Content>) {
|
||||
return (
|
||||
<PopoverPrimitive.Portal>
|
||||
<PopoverPrimitive.Content
|
||||
data-slot="popover-content"
|
||||
align={align}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</PopoverPrimitive.Portal>
|
||||
)
|
||||
}
|
||||
|
||||
function PopoverAnchor({
|
||||
...props
|
||||
}: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {
|
||||
return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} />
|
||||
}
|
||||
|
||||
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }
|
||||
1
src/generated/prisma/client.d.ts
vendored
Normal file
1
src/generated/prisma/client.d.ts
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from "./index"
|
||||
4
src/generated/prisma/client.js
Normal file
4
src/generated/prisma/client.js
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
/* !!! This is code generated by Prisma. Do not edit directly. !!!
|
||||
/* eslint-disable */
|
||||
module.exports = { ...require('.') }
|
||||
1
src/generated/prisma/default.d.ts
vendored
Normal file
1
src/generated/prisma/default.d.ts
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from "./index"
|
||||
4
src/generated/prisma/default.js
Normal file
4
src/generated/prisma/default.js
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
/* !!! This is code generated by Prisma. Do not edit directly. !!!
|
||||
/* eslint-disable */
|
||||
module.exports = { ...require('#main-entry-point') }
|
||||
1
src/generated/prisma/edge.d.ts
vendored
Normal file
1
src/generated/prisma/edge.d.ts
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from "./default"
|
||||
222
src/generated/prisma/edge.js
Normal file
222
src/generated/prisma/edge.js
Normal file
File diff suppressed because one or more lines are too long
209
src/generated/prisma/index-browser.js
Normal file
209
src/generated/prisma/index-browser.js
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
|
||||
/* !!! This is code generated by Prisma. Do not edit directly. !!!
|
||||
/* eslint-disable */
|
||||
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
|
||||
const {
|
||||
Decimal,
|
||||
objectEnumValues,
|
||||
makeStrictEnum,
|
||||
Public,
|
||||
getRuntime,
|
||||
skip
|
||||
} = require('./runtime/index-browser.js')
|
||||
|
||||
|
||||
const Prisma = {}
|
||||
|
||||
exports.Prisma = Prisma
|
||||
exports.$Enums = {}
|
||||
|
||||
/**
|
||||
* Prisma Client JS version: 6.18.0
|
||||
* Query Engine version: 34b5a692b7bd79939a9a2c3ef97d816e749cda2f
|
||||
*/
|
||||
Prisma.prismaVersion = {
|
||||
client: "6.18.0",
|
||||
engine: "34b5a692b7bd79939a9a2c3ef97d816e749cda2f"
|
||||
}
|
||||
|
||||
Prisma.PrismaClientKnownRequestError = () => {
|
||||
const runtimeName = getRuntime().prettyName;
|
||||
throw new Error(`PrismaClientKnownRequestError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
|
||||
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
|
||||
)};
|
||||
Prisma.PrismaClientUnknownRequestError = () => {
|
||||
const runtimeName = getRuntime().prettyName;
|
||||
throw new Error(`PrismaClientUnknownRequestError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
|
||||
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
|
||||
)}
|
||||
Prisma.PrismaClientRustPanicError = () => {
|
||||
const runtimeName = getRuntime().prettyName;
|
||||
throw new Error(`PrismaClientRustPanicError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
|
||||
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
|
||||
)}
|
||||
Prisma.PrismaClientInitializationError = () => {
|
||||
const runtimeName = getRuntime().prettyName;
|
||||
throw new Error(`PrismaClientInitializationError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
|
||||
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
|
||||
)}
|
||||
Prisma.PrismaClientValidationError = () => {
|
||||
const runtimeName = getRuntime().prettyName;
|
||||
throw new Error(`PrismaClientValidationError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
|
||||
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
|
||||
)}
|
||||
Prisma.Decimal = Decimal
|
||||
|
||||
/**
|
||||
* Re-export of sql-template-tag
|
||||
*/
|
||||
Prisma.sql = () => {
|
||||
const runtimeName = getRuntime().prettyName;
|
||||
throw new Error(`sqltag is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
|
||||
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
|
||||
)}
|
||||
Prisma.empty = () => {
|
||||
const runtimeName = getRuntime().prettyName;
|
||||
throw new Error(`empty is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
|
||||
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
|
||||
)}
|
||||
Prisma.join = () => {
|
||||
const runtimeName = getRuntime().prettyName;
|
||||
throw new Error(`join is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
|
||||
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
|
||||
)}
|
||||
Prisma.raw = () => {
|
||||
const runtimeName = getRuntime().prettyName;
|
||||
throw new Error(`raw is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
|
||||
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
|
||||
)}
|
||||
Prisma.validator = Public.validator
|
||||
|
||||
/**
|
||||
* Extensions
|
||||
*/
|
||||
Prisma.getExtensionContext = () => {
|
||||
const runtimeName = getRuntime().prettyName;
|
||||
throw new Error(`Extensions.getExtensionContext is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
|
||||
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
|
||||
)}
|
||||
Prisma.defineExtension = () => {
|
||||
const runtimeName = getRuntime().prettyName;
|
||||
throw new Error(`Extensions.defineExtension is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
|
||||
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
|
||||
)}
|
||||
|
||||
/**
|
||||
* Shorthand utilities for JSON filtering
|
||||
*/
|
||||
Prisma.DbNull = objectEnumValues.instances.DbNull
|
||||
Prisma.JsonNull = objectEnumValues.instances.JsonNull
|
||||
Prisma.AnyNull = objectEnumValues.instances.AnyNull
|
||||
|
||||
Prisma.NullTypes = {
|
||||
DbNull: objectEnumValues.classes.DbNull,
|
||||
JsonNull: objectEnumValues.classes.JsonNull,
|
||||
AnyNull: objectEnumValues.classes.AnyNull
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Enums
|
||||
*/
|
||||
|
||||
exports.Prisma.TransactionIsolationLevel = makeStrictEnum({
|
||||
ReadUncommitted: 'ReadUncommitted',
|
||||
ReadCommitted: 'ReadCommitted',
|
||||
RepeatableRead: 'RepeatableRead',
|
||||
Serializable: 'Serializable'
|
||||
});
|
||||
|
||||
exports.Prisma.InterventoScalarFieldEnum = {
|
||||
id: 'id',
|
||||
id_registratore: 'id_registratore',
|
||||
data: 'data',
|
||||
lavoro: 'lavoro',
|
||||
fattura: 'fattura'
|
||||
};
|
||||
|
||||
exports.Prisma.RegistratoreScalarFieldEnum = {
|
||||
id: 'id',
|
||||
id_cliente: 'id_cliente',
|
||||
modello: 'modello',
|
||||
data_acquisto: 'data_acquisto',
|
||||
ultima_verifica: 'ultima_verifica',
|
||||
prossima_verifica: 'prossima_verifica'
|
||||
};
|
||||
|
||||
exports.Prisma.ClienteScalarFieldEnum = {
|
||||
id: 'id',
|
||||
ragione_sociale: 'ragione_sociale',
|
||||
email: 'email',
|
||||
partita_iva: 'partita_iva',
|
||||
telefono: 'telefono',
|
||||
sede: 'sede',
|
||||
sede_url: 'sede_url',
|
||||
contratto: 'contratto',
|
||||
lat: 'lat',
|
||||
lon: 'lon'
|
||||
};
|
||||
|
||||
exports.Prisma.SortOrder = {
|
||||
asc: 'asc',
|
||||
desc: 'desc'
|
||||
};
|
||||
|
||||
exports.Prisma.QueryMode = {
|
||||
default: 'default',
|
||||
insensitive: 'insensitive'
|
||||
};
|
||||
|
||||
exports.Prisma.NullsOrder = {
|
||||
first: 'first',
|
||||
last: 'last'
|
||||
};
|
||||
exports.Modello = exports.$Enums.Modello = {
|
||||
FORM100: 'FORM100',
|
||||
FORM200: 'FORM200',
|
||||
FORM200PLUS: 'FORM200PLUS',
|
||||
FORM500: 'FORM500'
|
||||
};
|
||||
|
||||
exports.Prisma.ModelName = {
|
||||
Intervento: 'Intervento',
|
||||
Registratore: 'Registratore',
|
||||
Cliente: 'Cliente'
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a stub Prisma Client that will error at runtime if called.
|
||||
*/
|
||||
class PrismaClient {
|
||||
constructor() {
|
||||
return new Proxy(this, {
|
||||
get(target, prop) {
|
||||
let message
|
||||
const runtime = getRuntime()
|
||||
if (runtime.isEdge) {
|
||||
message = `PrismaClient is not configured to run in ${runtime.prettyName}. In order to run Prisma Client on edge runtime, either:
|
||||
- Use Prisma Accelerate: https://pris.ly/d/accelerate
|
||||
- Use Driver Adapters: https://pris.ly/d/driver-adapters
|
||||
`;
|
||||
} else {
|
||||
message = 'PrismaClient is unable to run in this browser environment, or has been bundled for the browser (running in `' + runtime.prettyName + '`).'
|
||||
}
|
||||
|
||||
message += `
|
||||
If this is unexpected, please open an issue: https://pris.ly/prisma-prisma-bug-report`
|
||||
|
||||
throw new Error(message)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
exports.PrismaClient = PrismaClient
|
||||
|
||||
Object.assign(exports, Prisma)
|
||||
6049
src/generated/prisma/index.d.ts
vendored
Normal file
6049
src/generated/prisma/index.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load diff
243
src/generated/prisma/index.js
Normal file
243
src/generated/prisma/index.js
Normal file
File diff suppressed because one or more lines are too long
183
src/generated/prisma/package.json
Normal file
183
src/generated/prisma/package.json
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
{
|
||||
"name": "prisma-client-5f7d234f39789de56f24e3f97fcb730daf5c78fb0ef54bab42a661559a87fb78",
|
||||
"main": "index.js",
|
||||
"types": "index.d.ts",
|
||||
"browser": "default.js",
|
||||
"exports": {
|
||||
"./client": {
|
||||
"require": {
|
||||
"node": "./index.js",
|
||||
"edge-light": "./wasm.js",
|
||||
"workerd": "./wasm.js",
|
||||
"worker": "./wasm.js",
|
||||
"browser": "./index-browser.js",
|
||||
"default": "./index.js"
|
||||
},
|
||||
"import": {
|
||||
"node": "./index.js",
|
||||
"edge-light": "./wasm.js",
|
||||
"workerd": "./wasm.js",
|
||||
"worker": "./wasm.js",
|
||||
"browser": "./index-browser.js",
|
||||
"default": "./index.js"
|
||||
},
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./package.json": "./package.json",
|
||||
".": {
|
||||
"require": {
|
||||
"node": "./index.js",
|
||||
"edge-light": "./wasm.js",
|
||||
"workerd": "./wasm.js",
|
||||
"worker": "./wasm.js",
|
||||
"browser": "./index-browser.js",
|
||||
"default": "./index.js"
|
||||
},
|
||||
"import": {
|
||||
"node": "./index.js",
|
||||
"edge-light": "./wasm.js",
|
||||
"workerd": "./wasm.js",
|
||||
"worker": "./wasm.js",
|
||||
"browser": "./index-browser.js",
|
||||
"default": "./index.js"
|
||||
},
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./edge": {
|
||||
"types": "./edge.d.ts",
|
||||
"require": "./edge.js",
|
||||
"import": "./edge.js",
|
||||
"default": "./edge.js"
|
||||
},
|
||||
"./react-native": {
|
||||
"types": "./react-native.d.ts",
|
||||
"require": "./react-native.js",
|
||||
"import": "./react-native.js",
|
||||
"default": "./react-native.js"
|
||||
},
|
||||
"./extension": {
|
||||
"types": "./extension.d.ts",
|
||||
"require": "./extension.js",
|
||||
"import": "./extension.js",
|
||||
"default": "./extension.js"
|
||||
},
|
||||
"./index-browser": {
|
||||
"types": "./index.d.ts",
|
||||
"require": "./index-browser.js",
|
||||
"import": "./index-browser.js",
|
||||
"default": "./index-browser.js"
|
||||
},
|
||||
"./index": {
|
||||
"types": "./index.d.ts",
|
||||
"require": "./index.js",
|
||||
"import": "./index.js",
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./wasm": {
|
||||
"types": "./wasm.d.ts",
|
||||
"require": "./wasm.js",
|
||||
"import": "./wasm.mjs",
|
||||
"default": "./wasm.mjs"
|
||||
},
|
||||
"./runtime/client": {
|
||||
"types": "./runtime/client.d.ts",
|
||||
"node": {
|
||||
"require": "./runtime/client.js",
|
||||
"default": "./runtime/client.js"
|
||||
},
|
||||
"require": "./runtime/client.js",
|
||||
"import": "./runtime/client.mjs",
|
||||
"default": "./runtime/client.mjs"
|
||||
},
|
||||
"./runtime/library": {
|
||||
"types": "./runtime/library.d.ts",
|
||||
"require": "./runtime/library.js",
|
||||
"import": "./runtime/library.mjs",
|
||||
"default": "./runtime/library.mjs"
|
||||
},
|
||||
"./runtime/binary": {
|
||||
"types": "./runtime/binary.d.ts",
|
||||
"require": "./runtime/binary.js",
|
||||
"import": "./runtime/binary.mjs",
|
||||
"default": "./runtime/binary.mjs"
|
||||
},
|
||||
"./runtime/wasm-engine-edge": {
|
||||
"types": "./runtime/wasm-engine-edge.d.ts",
|
||||
"require": "./runtime/wasm-engine-edge.js",
|
||||
"import": "./runtime/wasm-engine-edge.mjs",
|
||||
"default": "./runtime/wasm-engine-edge.mjs"
|
||||
},
|
||||
"./runtime/wasm-compiler-edge": {
|
||||
"types": "./runtime/wasm-compiler-edge.d.ts",
|
||||
"require": "./runtime/wasm-compiler-edge.js",
|
||||
"import": "./runtime/wasm-compiler-edge.mjs",
|
||||
"default": "./runtime/wasm-compiler-edge.mjs"
|
||||
},
|
||||
"./runtime/edge": {
|
||||
"types": "./runtime/edge.d.ts",
|
||||
"require": "./runtime/edge.js",
|
||||
"import": "./runtime/edge-esm.js",
|
||||
"default": "./runtime/edge-esm.js"
|
||||
},
|
||||
"./runtime/react-native": {
|
||||
"types": "./runtime/react-native.d.ts",
|
||||
"require": "./runtime/react-native.js",
|
||||
"import": "./runtime/react-native.js",
|
||||
"default": "./runtime/react-native.js"
|
||||
},
|
||||
"./runtime/index-browser": {
|
||||
"types": "./runtime/index-browser.d.ts",
|
||||
"require": "./runtime/index-browser.js",
|
||||
"import": "./runtime/index-browser.mjs",
|
||||
"default": "./runtime/index-browser.mjs"
|
||||
},
|
||||
"./generator-build": {
|
||||
"require": "./generator-build/index.js",
|
||||
"import": "./generator-build/index.js",
|
||||
"default": "./generator-build/index.js"
|
||||
},
|
||||
"./sql": {
|
||||
"require": {
|
||||
"types": "./sql.d.ts",
|
||||
"node": "./sql.js",
|
||||
"default": "./sql.js"
|
||||
},
|
||||
"import": {
|
||||
"types": "./sql.d.ts",
|
||||
"node": "./sql.mjs",
|
||||
"default": "./sql.mjs"
|
||||
},
|
||||
"default": "./sql.js"
|
||||
},
|
||||
"./*": "./*"
|
||||
},
|
||||
"version": "6.18.0",
|
||||
"sideEffects": false,
|
||||
"imports": {
|
||||
"#wasm-engine-loader": {
|
||||
"edge-light": "./wasm-edge-light-loader.mjs",
|
||||
"workerd": "./wasm-worker-loader.mjs",
|
||||
"worker": "./wasm-worker-loader.mjs",
|
||||
"default": "./wasm-worker-loader.mjs"
|
||||
},
|
||||
"#main-entry-point": {
|
||||
"require": {
|
||||
"node": "./index.js",
|
||||
"edge-light": "./wasm.js",
|
||||
"workerd": "./wasm.js",
|
||||
"worker": "./wasm.js",
|
||||
"browser": "./index-browser.js",
|
||||
"default": "./index.js"
|
||||
},
|
||||
"import": {
|
||||
"node": "./index.js",
|
||||
"edge-light": "./wasm.js",
|
||||
"workerd": "./wasm.js",
|
||||
"worker": "./wasm.js",
|
||||
"browser": "./index-browser.js",
|
||||
"default": "./index.js"
|
||||
},
|
||||
"default": "./index.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
src/generated/prisma/query_engine-windows.dll.node
Normal file
BIN
src/generated/prisma/query_engine-windows.dll.node
Normal file
Binary file not shown.
BIN
src/generated/prisma/query_engine-windows.dll.node.tmp12336
Normal file
BIN
src/generated/prisma/query_engine-windows.dll.node.tmp12336
Normal file
Binary file not shown.
BIN
src/generated/prisma/query_engine-windows.dll.node.tmp22464
Normal file
BIN
src/generated/prisma/query_engine-windows.dll.node.tmp22464
Normal file
Binary file not shown.
BIN
src/generated/prisma/query_engine-windows.dll.node.tmp3292
Normal file
BIN
src/generated/prisma/query_engine-windows.dll.node.tmp3292
Normal file
Binary file not shown.
BIN
src/generated/prisma/query_engine-windows.dll.node.tmp396
Normal file
BIN
src/generated/prisma/query_engine-windows.dll.node.tmp396
Normal file
Binary file not shown.
2
src/generated/prisma/query_engine_bg.js
Normal file
2
src/generated/prisma/query_engine_bg.js
Normal file
File diff suppressed because one or more lines are too long
BIN
src/generated/prisma/query_engine_bg.wasm
Normal file
BIN
src/generated/prisma/query_engine_bg.wasm
Normal file
Binary file not shown.
34
src/generated/prisma/runtime/edge-esm.js
Normal file
34
src/generated/prisma/runtime/edge-esm.js
Normal file
File diff suppressed because one or more lines are too long
34
src/generated/prisma/runtime/edge.js
Normal file
34
src/generated/prisma/runtime/edge.js
Normal file
File diff suppressed because one or more lines are too long
370
src/generated/prisma/runtime/index-browser.d.ts
vendored
Normal file
370
src/generated/prisma/runtime/index-browser.d.ts
vendored
Normal file
|
|
@ -0,0 +1,370 @@
|
|||
declare class AnyNull extends NullTypesEnumValue {
|
||||
#private;
|
||||
}
|
||||
|
||||
declare type Args<T, F extends Operation> = T extends {
|
||||
[K: symbol]: {
|
||||
types: {
|
||||
operations: {
|
||||
[K in F]: {
|
||||
args: any;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
} ? T[symbol]['types']['operations'][F]['args'] : any;
|
||||
|
||||
declare class DbNull extends NullTypesEnumValue {
|
||||
#private;
|
||||
}
|
||||
|
||||
export declare function Decimal(n: Decimal.Value): Decimal;
|
||||
|
||||
export declare namespace Decimal {
|
||||
export type Constructor = typeof Decimal;
|
||||
export type Instance = Decimal;
|
||||
export type Rounding = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
|
||||
export type Modulo = Rounding | 9;
|
||||
export type Value = string | number | Decimal;
|
||||
|
||||
// http://mikemcl.github.io/decimal.js/#constructor-properties
|
||||
export interface Config {
|
||||
precision?: number;
|
||||
rounding?: Rounding;
|
||||
toExpNeg?: number;
|
||||
toExpPos?: number;
|
||||
minE?: number;
|
||||
maxE?: number;
|
||||
crypto?: boolean;
|
||||
modulo?: Modulo;
|
||||
defaults?: boolean;
|
||||
}
|
||||
}
|
||||
|
||||
export declare class Decimal {
|
||||
readonly d: number[];
|
||||
readonly e: number;
|
||||
readonly s: number;
|
||||
|
||||
constructor(n: Decimal.Value);
|
||||
|
||||
absoluteValue(): Decimal;
|
||||
abs(): Decimal;
|
||||
|
||||
ceil(): Decimal;
|
||||
|
||||
clampedTo(min: Decimal.Value, max: Decimal.Value): Decimal;
|
||||
clamp(min: Decimal.Value, max: Decimal.Value): Decimal;
|
||||
|
||||
comparedTo(n: Decimal.Value): number;
|
||||
cmp(n: Decimal.Value): number;
|
||||
|
||||
cosine(): Decimal;
|
||||
cos(): Decimal;
|
||||
|
||||
cubeRoot(): Decimal;
|
||||
cbrt(): Decimal;
|
||||
|
||||
decimalPlaces(): number;
|
||||
dp(): number;
|
||||
|
||||
dividedBy(n: Decimal.Value): Decimal;
|
||||
div(n: Decimal.Value): Decimal;
|
||||
|
||||
dividedToIntegerBy(n: Decimal.Value): Decimal;
|
||||
divToInt(n: Decimal.Value): Decimal;
|
||||
|
||||
equals(n: Decimal.Value): boolean;
|
||||
eq(n: Decimal.Value): boolean;
|
||||
|
||||
floor(): Decimal;
|
||||
|
||||
greaterThan(n: Decimal.Value): boolean;
|
||||
gt(n: Decimal.Value): boolean;
|
||||
|
||||
greaterThanOrEqualTo(n: Decimal.Value): boolean;
|
||||
gte(n: Decimal.Value): boolean;
|
||||
|
||||
hyperbolicCosine(): Decimal;
|
||||
cosh(): Decimal;
|
||||
|
||||
hyperbolicSine(): Decimal;
|
||||
sinh(): Decimal;
|
||||
|
||||
hyperbolicTangent(): Decimal;
|
||||
tanh(): Decimal;
|
||||
|
||||
inverseCosine(): Decimal;
|
||||
acos(): Decimal;
|
||||
|
||||
inverseHyperbolicCosine(): Decimal;
|
||||
acosh(): Decimal;
|
||||
|
||||
inverseHyperbolicSine(): Decimal;
|
||||
asinh(): Decimal;
|
||||
|
||||
inverseHyperbolicTangent(): Decimal;
|
||||
atanh(): Decimal;
|
||||
|
||||
inverseSine(): Decimal;
|
||||
asin(): Decimal;
|
||||
|
||||
inverseTangent(): Decimal;
|
||||
atan(): Decimal;
|
||||
|
||||
isFinite(): boolean;
|
||||
|
||||
isInteger(): boolean;
|
||||
isInt(): boolean;
|
||||
|
||||
isNaN(): boolean;
|
||||
|
||||
isNegative(): boolean;
|
||||
isNeg(): boolean;
|
||||
|
||||
isPositive(): boolean;
|
||||
isPos(): boolean;
|
||||
|
||||
isZero(): boolean;
|
||||
|
||||
lessThan(n: Decimal.Value): boolean;
|
||||
lt(n: Decimal.Value): boolean;
|
||||
|
||||
lessThanOrEqualTo(n: Decimal.Value): boolean;
|
||||
lte(n: Decimal.Value): boolean;
|
||||
|
||||
logarithm(n?: Decimal.Value): Decimal;
|
||||
log(n?: Decimal.Value): Decimal;
|
||||
|
||||
minus(n: Decimal.Value): Decimal;
|
||||
sub(n: Decimal.Value): Decimal;
|
||||
|
||||
modulo(n: Decimal.Value): Decimal;
|
||||
mod(n: Decimal.Value): Decimal;
|
||||
|
||||
naturalExponential(): Decimal;
|
||||
exp(): Decimal;
|
||||
|
||||
naturalLogarithm(): Decimal;
|
||||
ln(): Decimal;
|
||||
|
||||
negated(): Decimal;
|
||||
neg(): Decimal;
|
||||
|
||||
plus(n: Decimal.Value): Decimal;
|
||||
add(n: Decimal.Value): Decimal;
|
||||
|
||||
precision(includeZeros?: boolean): number;
|
||||
sd(includeZeros?: boolean): number;
|
||||
|
||||
round(): Decimal;
|
||||
|
||||
sine() : Decimal;
|
||||
sin() : Decimal;
|
||||
|
||||
squareRoot(): Decimal;
|
||||
sqrt(): Decimal;
|
||||
|
||||
tangent() : Decimal;
|
||||
tan() : Decimal;
|
||||
|
||||
times(n: Decimal.Value): Decimal;
|
||||
mul(n: Decimal.Value) : Decimal;
|
||||
|
||||
toBinary(significantDigits?: number): string;
|
||||
toBinary(significantDigits: number, rounding: Decimal.Rounding): string;
|
||||
|
||||
toDecimalPlaces(decimalPlaces?: number): Decimal;
|
||||
toDecimalPlaces(decimalPlaces: number, rounding: Decimal.Rounding): Decimal;
|
||||
toDP(decimalPlaces?: number): Decimal;
|
||||
toDP(decimalPlaces: number, rounding: Decimal.Rounding): Decimal;
|
||||
|
||||
toExponential(decimalPlaces?: number): string;
|
||||
toExponential(decimalPlaces: number, rounding: Decimal.Rounding): string;
|
||||
|
||||
toFixed(decimalPlaces?: number): string;
|
||||
toFixed(decimalPlaces: number, rounding: Decimal.Rounding): string;
|
||||
|
||||
toFraction(max_denominator?: Decimal.Value): Decimal[];
|
||||
|
||||
toHexadecimal(significantDigits?: number): string;
|
||||
toHexadecimal(significantDigits: number, rounding: Decimal.Rounding): string;
|
||||
toHex(significantDigits?: number): string;
|
||||
toHex(significantDigits: number, rounding?: Decimal.Rounding): string;
|
||||
|
||||
toJSON(): string;
|
||||
|
||||
toNearest(n: Decimal.Value, rounding?: Decimal.Rounding): Decimal;
|
||||
|
||||
toNumber(): number;
|
||||
|
||||
toOctal(significantDigits?: number): string;
|
||||
toOctal(significantDigits: number, rounding: Decimal.Rounding): string;
|
||||
|
||||
toPower(n: Decimal.Value): Decimal;
|
||||
pow(n: Decimal.Value): Decimal;
|
||||
|
||||
toPrecision(significantDigits?: number): string;
|
||||
toPrecision(significantDigits: number, rounding: Decimal.Rounding): string;
|
||||
|
||||
toSignificantDigits(significantDigits?: number): Decimal;
|
||||
toSignificantDigits(significantDigits: number, rounding: Decimal.Rounding): Decimal;
|
||||
toSD(significantDigits?: number): Decimal;
|
||||
toSD(significantDigits: number, rounding: Decimal.Rounding): Decimal;
|
||||
|
||||
toString(): string;
|
||||
|
||||
truncated(): Decimal;
|
||||
trunc(): Decimal;
|
||||
|
||||
valueOf(): string;
|
||||
|
||||
static abs(n: Decimal.Value): Decimal;
|
||||
static acos(n: Decimal.Value): Decimal;
|
||||
static acosh(n: Decimal.Value): Decimal;
|
||||
static add(x: Decimal.Value, y: Decimal.Value): Decimal;
|
||||
static asin(n: Decimal.Value): Decimal;
|
||||
static asinh(n: Decimal.Value): Decimal;
|
||||
static atan(n: Decimal.Value): Decimal;
|
||||
static atanh(n: Decimal.Value): Decimal;
|
||||
static atan2(y: Decimal.Value, x: Decimal.Value): Decimal;
|
||||
static cbrt(n: Decimal.Value): Decimal;
|
||||
static ceil(n: Decimal.Value): Decimal;
|
||||
static clamp(n: Decimal.Value, min: Decimal.Value, max: Decimal.Value): Decimal;
|
||||
static clone(object?: Decimal.Config): Decimal.Constructor;
|
||||
static config(object: Decimal.Config): Decimal.Constructor;
|
||||
static cos(n: Decimal.Value): Decimal;
|
||||
static cosh(n: Decimal.Value): Decimal;
|
||||
static div(x: Decimal.Value, y: Decimal.Value): Decimal;
|
||||
static exp(n: Decimal.Value): Decimal;
|
||||
static floor(n: Decimal.Value): Decimal;
|
||||
static hypot(...n: Decimal.Value[]): Decimal;
|
||||
static isDecimal(object: any): object is Decimal;
|
||||
static ln(n: Decimal.Value): Decimal;
|
||||
static log(n: Decimal.Value, base?: Decimal.Value): Decimal;
|
||||
static log2(n: Decimal.Value): Decimal;
|
||||
static log10(n: Decimal.Value): Decimal;
|
||||
static max(...n: Decimal.Value[]): Decimal;
|
||||
static min(...n: Decimal.Value[]): Decimal;
|
||||
static mod(x: Decimal.Value, y: Decimal.Value): Decimal;
|
||||
static mul(x: Decimal.Value, y: Decimal.Value): Decimal;
|
||||
static noConflict(): Decimal.Constructor; // Browser only
|
||||
static pow(base: Decimal.Value, exponent: Decimal.Value): Decimal;
|
||||
static random(significantDigits?: number): Decimal;
|
||||
static round(n: Decimal.Value): Decimal;
|
||||
static set(object: Decimal.Config): Decimal.Constructor;
|
||||
static sign(n: Decimal.Value): number;
|
||||
static sin(n: Decimal.Value): Decimal;
|
||||
static sinh(n: Decimal.Value): Decimal;
|
||||
static sqrt(n: Decimal.Value): Decimal;
|
||||
static sub(x: Decimal.Value, y: Decimal.Value): Decimal;
|
||||
static sum(...n: Decimal.Value[]): Decimal;
|
||||
static tan(n: Decimal.Value): Decimal;
|
||||
static tanh(n: Decimal.Value): Decimal;
|
||||
static trunc(n: Decimal.Value): Decimal;
|
||||
|
||||
static readonly default?: Decimal.Constructor;
|
||||
static readonly Decimal?: Decimal.Constructor;
|
||||
|
||||
static readonly precision: number;
|
||||
static readonly rounding: Decimal.Rounding;
|
||||
static readonly toExpNeg: number;
|
||||
static readonly toExpPos: number;
|
||||
static readonly minE: number;
|
||||
static readonly maxE: number;
|
||||
static readonly crypto: boolean;
|
||||
static readonly modulo: Decimal.Modulo;
|
||||
|
||||
static readonly ROUND_UP: 0;
|
||||
static readonly ROUND_DOWN: 1;
|
||||
static readonly ROUND_CEIL: 2;
|
||||
static readonly ROUND_FLOOR: 3;
|
||||
static readonly ROUND_HALF_UP: 4;
|
||||
static readonly ROUND_HALF_DOWN: 5;
|
||||
static readonly ROUND_HALF_EVEN: 6;
|
||||
static readonly ROUND_HALF_CEIL: 7;
|
||||
static readonly ROUND_HALF_FLOOR: 8;
|
||||
static readonly EUCLID: 9;
|
||||
}
|
||||
|
||||
declare type Exact<A, W> = (A extends unknown ? (W extends A ? {
|
||||
[K in keyof A]: Exact<A[K], W[K]>;
|
||||
} : W) : never) | (A extends Narrowable ? A : never);
|
||||
|
||||
export declare function getRuntime(): GetRuntimeOutput;
|
||||
|
||||
declare type GetRuntimeOutput = {
|
||||
id: RuntimeName;
|
||||
prettyName: string;
|
||||
isEdge: boolean;
|
||||
};
|
||||
|
||||
declare class JsonNull extends NullTypesEnumValue {
|
||||
#private;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates more strict variant of an enum which, unlike regular enum,
|
||||
* throws on non-existing property access. This can be useful in following situations:
|
||||
* - we have an API, that accepts both `undefined` and `SomeEnumType` as an input
|
||||
* - enum values are generated dynamically from DMMF.
|
||||
*
|
||||
* In that case, if using normal enums and no compile-time typechecking, using non-existing property
|
||||
* will result in `undefined` value being used, which will be accepted. Using strict enum
|
||||
* in this case will help to have a runtime exception, telling you that you are probably doing something wrong.
|
||||
*
|
||||
* Note: if you need to check for existence of a value in the enum you can still use either
|
||||
* `in` operator or `hasOwnProperty` function.
|
||||
*
|
||||
* @param definition
|
||||
* @returns
|
||||
*/
|
||||
export declare function makeStrictEnum<T extends Record<PropertyKey, string | number>>(definition: T): T;
|
||||
|
||||
declare type Narrowable = string | number | bigint | boolean | [];
|
||||
|
||||
declare class NullTypesEnumValue extends ObjectEnumValue {
|
||||
_getNamespace(): string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for unique values of object-valued enums.
|
||||
*/
|
||||
declare abstract class ObjectEnumValue {
|
||||
constructor(arg?: symbol);
|
||||
abstract _getNamespace(): string;
|
||||
_getName(): string;
|
||||
toString(): string;
|
||||
}
|
||||
|
||||
export declare const objectEnumValues: {
|
||||
classes: {
|
||||
DbNull: typeof DbNull;
|
||||
JsonNull: typeof JsonNull;
|
||||
AnyNull: typeof AnyNull;
|
||||
};
|
||||
instances: {
|
||||
DbNull: DbNull;
|
||||
JsonNull: JsonNull;
|
||||
AnyNull: AnyNull;
|
||||
};
|
||||
};
|
||||
|
||||
declare type Operation = 'findFirst' | 'findFirstOrThrow' | 'findUnique' | 'findUniqueOrThrow' | 'findMany' | 'create' | 'createMany' | 'createManyAndReturn' | 'update' | 'updateMany' | 'updateManyAndReturn' | 'upsert' | 'delete' | 'deleteMany' | 'aggregate' | 'count' | 'groupBy' | '$queryRaw' | '$executeRaw' | '$queryRawUnsafe' | '$executeRawUnsafe' | 'findRaw' | 'aggregateRaw' | '$runCommandRaw';
|
||||
|
||||
declare namespace Public {
|
||||
export {
|
||||
validator
|
||||
}
|
||||
}
|
||||
export { Public }
|
||||
|
||||
declare type RuntimeName = 'workerd' | 'deno' | 'netlify' | 'node' | 'bun' | 'edge-light' | '';
|
||||
|
||||
declare function validator<V>(): <S>(select: Exact<S, V>) => S;
|
||||
|
||||
declare function validator<C, M extends Exclude<keyof C, `$${string}`>, O extends keyof C[M] & Operation>(client: C, model: M, operation: O): <S>(select: Exact<S, Args<C[M], O>>) => S;
|
||||
|
||||
declare function validator<C, M extends Exclude<keyof C, `$${string}`>, O extends keyof C[M] & Operation, P extends keyof Args<C[M], O>>(client: C, model: M, operation: O, prop: P): <S>(select: Exact<S, Args<C[M], O>[P]>) => S;
|
||||
|
||||
export { }
|
||||
16
src/generated/prisma/runtime/index-browser.js
Normal file
16
src/generated/prisma/runtime/index-browser.js
Normal file
File diff suppressed because one or more lines are too long
3982
src/generated/prisma/runtime/library.d.ts
vendored
Normal file
3982
src/generated/prisma/runtime/library.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load diff
146
src/generated/prisma/runtime/library.js
Normal file
146
src/generated/prisma/runtime/library.js
Normal file
File diff suppressed because one or more lines are too long
83
src/generated/prisma/runtime/react-native.js
vendored
Normal file
83
src/generated/prisma/runtime/react-native.js
vendored
Normal file
File diff suppressed because one or more lines are too long
84
src/generated/prisma/runtime/wasm-compiler-edge.js
Normal file
84
src/generated/prisma/runtime/wasm-compiler-edge.js
Normal file
File diff suppressed because one or more lines are too long
36
src/generated/prisma/runtime/wasm-engine-edge.js
Normal file
36
src/generated/prisma/runtime/wasm-engine-edge.js
Normal file
File diff suppressed because one or more lines are too long
48
src/generated/prisma/schema.prisma
Normal file
48
src/generated/prisma/schema.prisma
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
output = "../src/generated/prisma"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
enum Modello {
|
||||
FORM100
|
||||
FORM200
|
||||
FORM200PLUS
|
||||
FORM500
|
||||
}
|
||||
|
||||
model Intervento {
|
||||
id Int @id @default(autoincrement())
|
||||
id_registratore String
|
||||
data DateTime @db.Date
|
||||
lavoro String @db.Text
|
||||
fattura Boolean @db.Boolean
|
||||
registratore Registratore @relation(fields: [id_registratore], references: [id])
|
||||
}
|
||||
|
||||
model Registratore {
|
||||
id String @id
|
||||
id_cliente Int
|
||||
modello Modello?
|
||||
data_acquisto DateTime? @db.Date
|
||||
ultima_verifica DateTime? @db.Date
|
||||
prossima_verifica DateTime? @db.Date
|
||||
cliente Cliente @relation(fields: [id_cliente], references: [id])
|
||||
interventi Intervento[]
|
||||
}
|
||||
|
||||
model Cliente {
|
||||
id Int @id @default(autoincrement())
|
||||
ragione_sociale String @unique @db.VarChar(255)
|
||||
email String @db.VarChar(255)
|
||||
partita_iva String @db.VarChar(255)
|
||||
telefono String @db.VarChar(255)
|
||||
sede String @db.VarChar(255)
|
||||
sede_url String @db.VarChar(255)
|
||||
contratto String @db.VarChar(255)
|
||||
registratori Registratore[]
|
||||
}
|
||||
4
src/generated/prisma/wasm-edge-light-loader.mjs
Normal file
4
src/generated/prisma/wasm-edge-light-loader.mjs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
/* !!! This is code generated by Prisma. Do not edit directly. !!!
|
||||
/* eslint-disable */
|
||||
export default import('./query_engine_bg.wasm?module')
|
||||
4
src/generated/prisma/wasm-worker-loader.mjs
Normal file
4
src/generated/prisma/wasm-worker-loader.mjs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
/* !!! This is code generated by Prisma. Do not edit directly. !!!
|
||||
/* eslint-disable */
|
||||
export default import('./query_engine_bg.wasm')
|
||||
1
src/generated/prisma/wasm.d.ts
vendored
Normal file
1
src/generated/prisma/wasm.d.ts
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from "./default"
|
||||
229
src/generated/prisma/wasm.js
Normal file
229
src/generated/prisma/wasm.js
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
|
||||
/* !!! This is code generated by Prisma. Do not edit directly. !!!
|
||||
/* eslint-disable */
|
||||
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
|
||||
const {
|
||||
PrismaClientKnownRequestError,
|
||||
PrismaClientUnknownRequestError,
|
||||
PrismaClientRustPanicError,
|
||||
PrismaClientInitializationError,
|
||||
PrismaClientValidationError,
|
||||
getPrismaClient,
|
||||
sqltag,
|
||||
empty,
|
||||
join,
|
||||
raw,
|
||||
skip,
|
||||
Decimal,
|
||||
Debug,
|
||||
objectEnumValues,
|
||||
makeStrictEnum,
|
||||
Extensions,
|
||||
warnOnce,
|
||||
defineDmmfProperty,
|
||||
Public,
|
||||
getRuntime,
|
||||
createParam,
|
||||
} = require('./runtime/wasm-engine-edge.js')
|
||||
|
||||
|
||||
const Prisma = {}
|
||||
|
||||
exports.Prisma = Prisma
|
||||
exports.$Enums = {}
|
||||
|
||||
/**
|
||||
* Prisma Client JS version: 6.18.0
|
||||
* Query Engine version: 34b5a692b7bd79939a9a2c3ef97d816e749cda2f
|
||||
*/
|
||||
Prisma.prismaVersion = {
|
||||
client: "6.18.0",
|
||||
engine: "34b5a692b7bd79939a9a2c3ef97d816e749cda2f"
|
||||
}
|
||||
|
||||
Prisma.PrismaClientKnownRequestError = PrismaClientKnownRequestError;
|
||||
Prisma.PrismaClientUnknownRequestError = PrismaClientUnknownRequestError
|
||||
Prisma.PrismaClientRustPanicError = PrismaClientRustPanicError
|
||||
Prisma.PrismaClientInitializationError = PrismaClientInitializationError
|
||||
Prisma.PrismaClientValidationError = PrismaClientValidationError
|
||||
Prisma.Decimal = Decimal
|
||||
|
||||
/**
|
||||
* Re-export of sql-template-tag
|
||||
*/
|
||||
Prisma.sql = sqltag
|
||||
Prisma.empty = empty
|
||||
Prisma.join = join
|
||||
Prisma.raw = raw
|
||||
Prisma.validator = Public.validator
|
||||
|
||||
/**
|
||||
* Extensions
|
||||
*/
|
||||
Prisma.getExtensionContext = Extensions.getExtensionContext
|
||||
Prisma.defineExtension = Extensions.defineExtension
|
||||
|
||||
/**
|
||||
* Shorthand utilities for JSON filtering
|
||||
*/
|
||||
Prisma.DbNull = objectEnumValues.instances.DbNull
|
||||
Prisma.JsonNull = objectEnumValues.instances.JsonNull
|
||||
Prisma.AnyNull = objectEnumValues.instances.AnyNull
|
||||
|
||||
Prisma.NullTypes = {
|
||||
DbNull: objectEnumValues.classes.DbNull,
|
||||
JsonNull: objectEnumValues.classes.JsonNull,
|
||||
AnyNull: objectEnumValues.classes.AnyNull
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Enums
|
||||
*/
|
||||
exports.Prisma.TransactionIsolationLevel = makeStrictEnum({
|
||||
ReadUncommitted: 'ReadUncommitted',
|
||||
ReadCommitted: 'ReadCommitted',
|
||||
RepeatableRead: 'RepeatableRead',
|
||||
Serializable: 'Serializable'
|
||||
});
|
||||
|
||||
exports.Prisma.InterventoScalarFieldEnum = {
|
||||
id: 'id',
|
||||
id_registratore: 'id_registratore',
|
||||
data: 'data',
|
||||
lavoro: 'lavoro',
|
||||
fattura: 'fattura'
|
||||
};
|
||||
|
||||
exports.Prisma.RegistratoreScalarFieldEnum = {
|
||||
id: 'id',
|
||||
id_cliente: 'id_cliente',
|
||||
modello: 'modello',
|
||||
data_acquisto: 'data_acquisto',
|
||||
ultima_verifica: 'ultima_verifica',
|
||||
prossima_verifica: 'prossima_verifica'
|
||||
};
|
||||
|
||||
exports.Prisma.ClienteScalarFieldEnum = {
|
||||
id: 'id',
|
||||
ragione_sociale: 'ragione_sociale',
|
||||
email: 'email',
|
||||
partita_iva: 'partita_iva',
|
||||
telefono: 'telefono',
|
||||
sede: 'sede',
|
||||
sede_url: 'sede_url',
|
||||
contratto: 'contratto',
|
||||
lat: 'lat',
|
||||
lon: 'lon'
|
||||
};
|
||||
|
||||
exports.Prisma.SortOrder = {
|
||||
asc: 'asc',
|
||||
desc: 'desc'
|
||||
};
|
||||
|
||||
exports.Prisma.QueryMode = {
|
||||
default: 'default',
|
||||
insensitive: 'insensitive'
|
||||
};
|
||||
|
||||
exports.Prisma.NullsOrder = {
|
||||
first: 'first',
|
||||
last: 'last'
|
||||
};
|
||||
exports.Modello = exports.$Enums.Modello = {
|
||||
FORM100: 'FORM100',
|
||||
FORM200: 'FORM200',
|
||||
FORM200PLUS: 'FORM200PLUS',
|
||||
FORM500: 'FORM500'
|
||||
};
|
||||
|
||||
exports.Prisma.ModelName = {
|
||||
Intervento: 'Intervento',
|
||||
Registratore: 'Registratore',
|
||||
Cliente: 'Cliente'
|
||||
};
|
||||
/**
|
||||
* Create the Client
|
||||
*/
|
||||
const config = {
|
||||
"generator": {
|
||||
"name": "client",
|
||||
"provider": {
|
||||
"fromEnvVar": null,
|
||||
"value": "prisma-client-js"
|
||||
},
|
||||
"output": {
|
||||
"value": "C:\\Users\\nicola\\Documents\\dev\\dash-registratori\\src\\generated\\prisma",
|
||||
"fromEnvVar": null
|
||||
},
|
||||
"config": {
|
||||
"engineType": "library"
|
||||
},
|
||||
"binaryTargets": [
|
||||
{
|
||||
"fromEnvVar": null,
|
||||
"value": "windows",
|
||||
"native": true
|
||||
}
|
||||
],
|
||||
"previewFeatures": [],
|
||||
"sourceFilePath": "C:\\Users\\nicola\\Documents\\dev\\dash-registratori\\prisma\\schema.prisma",
|
||||
"isCustomOutput": true
|
||||
},
|
||||
"relativeEnvPaths": {
|
||||
"rootEnvPath": null,
|
||||
"schemaEnvPath": "../../../.env"
|
||||
},
|
||||
"relativePath": "../../../prisma",
|
||||
"clientVersion": "6.18.0",
|
||||
"engineVersion": "34b5a692b7bd79939a9a2c3ef97d816e749cda2f",
|
||||
"datasourceNames": [
|
||||
"db"
|
||||
],
|
||||
"activeProvider": "postgresql",
|
||||
"inlineDatasources": {
|
||||
"db": {
|
||||
"url": {
|
||||
"fromEnvVar": "DATABASE_URL",
|
||||
"value": null
|
||||
}
|
||||
}
|
||||
},
|
||||
"inlineSchema": "generator client {\n provider = \"prisma-client-js\"\n output = \"../src/generated/prisma\"\n}\n\ndatasource db {\n provider = \"postgresql\"\n url = env(\"DATABASE_URL\")\n}\n\nenum Modello {\n FORM100\n FORM200\n FORM200PLUS\n FORM500\n}\n\nmodel Intervento {\n id Int @id @default(autoincrement())\n id_registratore String\n data DateTime @db.Date\n lavoro String @db.Text\n fattura Boolean @db.Boolean\n registratore Registratore @relation(fields: [id_registratore], references: [id])\n}\n\nmodel Registratore {\n id String @id\n id_cliente Int\n modello Modello?\n data_acquisto DateTime? @db.Date\n ultima_verifica DateTime? @db.Date\n prossima_verifica DateTime? @db.Date\n cliente Cliente @relation(fields: [id_cliente], references: [id])\n interventi Intervento[]\n}\n\nmodel Cliente {\n id Int @id @default(autoincrement())\n ragione_sociale String @unique @db.VarChar(255)\n email String @db.VarChar(255)\n partita_iva String @db.VarChar(255)\n telefono String @db.VarChar(255)\n sede String @db.VarChar(255)\n sede_url String\n contratto String @db.VarChar(255)\n lat Float\n lon Float\n registratori Registratore[]\n}\n",
|
||||
"inlineSchemaHash": "9bd9d1485d1021de6ddd08a2040ad878357151b96b361e965ef2ca00c0bca296",
|
||||
"copyEngine": true
|
||||
}
|
||||
config.dirname = '/'
|
||||
|
||||
config.runtimeDataModel = JSON.parse("{\"models\":{\"Intervento\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"id_registratore\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"data\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"lavoro\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"fattura\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"registratore\",\"kind\":\"object\",\"type\":\"Registratore\",\"relationName\":\"InterventoToRegistratore\"}],\"dbName\":null},\"Registratore\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"id_cliente\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"modello\",\"kind\":\"enum\",\"type\":\"Modello\"},{\"name\":\"data_acquisto\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"ultima_verifica\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"prossima_verifica\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"cliente\",\"kind\":\"object\",\"type\":\"Cliente\",\"relationName\":\"ClienteToRegistratore\"},{\"name\":\"interventi\",\"kind\":\"object\",\"type\":\"Intervento\",\"relationName\":\"InterventoToRegistratore\"}],\"dbName\":null},\"Cliente\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"ragione_sociale\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"partita_iva\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"telefono\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"sede\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"sede_url\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"contratto\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"lat\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"lon\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"registratori\",\"kind\":\"object\",\"type\":\"Registratore\",\"relationName\":\"ClienteToRegistratore\"}],\"dbName\":null}},\"enums\":{},\"types\":{}}")
|
||||
defineDmmfProperty(exports.Prisma, config.runtimeDataModel)
|
||||
config.engineWasm = {
|
||||
getRuntime: async () => require('./query_engine_bg.js'),
|
||||
getQueryEngineWasmModule: async () => {
|
||||
const loader = (await import('#wasm-engine-loader')).default
|
||||
const engine = (await loader).default
|
||||
return engine
|
||||
}
|
||||
}
|
||||
config.compilerWasm = undefined
|
||||
|
||||
config.injectableEdgeEnv = () => ({
|
||||
parsed: {
|
||||
DATABASE_URL: typeof globalThis !== 'undefined' && globalThis['DATABASE_URL'] || typeof process !== 'undefined' && process.env && process.env.DATABASE_URL || undefined
|
||||
}
|
||||
})
|
||||
|
||||
if (typeof globalThis !== 'undefined' && globalThis['DEBUG'] || typeof process !== 'undefined' && process.env && process.env.DEBUG || undefined) {
|
||||
Debug.enable(typeof globalThis !== 'undefined' && globalThis['DEBUG'] || typeof process !== 'undefined' && process.env && process.env.DEBUG || undefined)
|
||||
}
|
||||
|
||||
const PrismaClient = getPrismaClient(config)
|
||||
exports.PrismaClient = PrismaClient
|
||||
Object.assign(exports, Prisma)
|
||||
|
||||
Loading…
Reference in a new issue