Compare commits
No commits in common. "main" and "refactor" have entirely different histories.
75 changed files with 855 additions and 15710 deletions
|
|
@ -1,7 +0,0 @@
|
||||||
Dockerfile
|
|
||||||
.dockerignore
|
|
||||||
node_modules
|
|
||||||
npm-debug.log
|
|
||||||
README.md
|
|
||||||
.next
|
|
||||||
.git
|
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -39,5 +39,3 @@ yarn-error.log*
|
||||||
# typescript
|
# typescript
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
next-env.d.ts
|
next-env.d.ts
|
||||||
|
|
||||||
/src/generated/prisma
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"tabWidth": 2,
|
|
||||||
"useTabs": false
|
|
||||||
}
|
|
||||||
50
Dockerfile
50
Dockerfile
|
|
@ -1,44 +1,38 @@
|
||||||
FROM node:22-alpine AS base
|
# Fase 1: Build
|
||||||
|
FROM node:18-alpine AS builder
|
||||||
RUN apk add --no-cache libc6-compat openssl
|
|
||||||
|
|
||||||
|
# Imposta la directory di lavoro
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# --- STAGE 1 ---
|
# Copia i file di configurazione e dipendenze
|
||||||
FROM base AS deps
|
COPY package.json pnpm-lock.yaml* ./
|
||||||
COPY package.json ./
|
|
||||||
RUN npm install
|
|
||||||
|
|
||||||
# --- STAGE 2 ---
|
# Installa le dipendenze
|
||||||
FROM base AS builder
|
RUN npm install --force
|
||||||
COPY --from=deps /app/node_modules ./node_modules
|
|
||||||
|
# Copia il resto dei file dell'app
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
RUN npx prisma generate
|
# Build dell'app Next.js
|
||||||
|
|
||||||
ENV NEXT_TELEMETRY_DISABLED=1
|
|
||||||
|
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
# --- STAGE 3 ---
|
# Fase 2: Runtime (immagine più leggera)
|
||||||
FROM base AS runner
|
FROM node:18-alpine AS runner
|
||||||
|
|
||||||
|
# Imposta la directory di lavoro
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Imposta variabile d'ambiente per produzione
|
||||||
ENV NODE_ENV=production
|
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/public ./public
|
||||||
|
COPY --from=builder /app/.next ./.next
|
||||||
|
COPY --from=builder /app/node_modules ./node_modules
|
||||||
|
COPY --from=builder /app/package.json ./package.json
|
||||||
|
|
||||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
# Porta esposta (3000 di default per Next.js)
|
||||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
|
||||||
|
|
||||||
USER nextjs
|
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
CMD ["node", "server.js"]
|
# Comando di avvio
|
||||||
|
CMD ["npm", "start"]
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,11 @@
|
||||||
services:
|
services:
|
||||||
webapp:
|
app:
|
||||||
build: .
|
container_name: dashregistratori
|
||||||
container_name: dash-registratori
|
build:
|
||||||
|
context: .
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- "3000:3000"
|
- 3001:3000
|
||||||
|
dns: 1.1.1.1
|
||||||
environment:
|
environment:
|
||||||
DATABASE_URL: "postgresql://postgres:postgres@db:5432/db?schema=public"
|
NODE_ENV: development
|
||||||
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,14 +2,6 @@ import type { NextConfig } from "next";
|
||||||
|
|
||||||
const nextConfig: NextConfig = {
|
const nextConfig: NextConfig = {
|
||||||
output: "standalone",
|
output: "standalone",
|
||||||
|
|
||||||
typescript: {
|
|
||||||
ignoreBuildErrors: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
eslint: {
|
|
||||||
ignoreDuringBuilds: true,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default nextConfig;
|
export default nextConfig;
|
||||||
|
|
|
||||||
1994
package-lock.json
generated
1994
package-lock.json
generated
File diff suppressed because it is too large
Load diff
11
package.json
11
package.json
|
|
@ -8,29 +8,23 @@
|
||||||
"start": "next start"
|
"start": "next start"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/client": "^6.18.0",
|
|
||||||
"@radix-ui/react-avatar": "^1.1.10",
|
"@radix-ui/react-avatar": "^1.1.10",
|
||||||
"@radix-ui/react-checkbox": "^1.3.3",
|
"@radix-ui/react-checkbox": "^1.3.3",
|
||||||
"@radix-ui/react-collapsible": "^1.1.12",
|
"@radix-ui/react-collapsible": "^1.1.12",
|
||||||
"@radix-ui/react-dialog": "^1.1.15",
|
"@radix-ui/react-dialog": "^1.1.15",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
||||||
"@radix-ui/react-label": "^2.1.7",
|
"@radix-ui/react-label": "^2.1.7",
|
||||||
"@radix-ui/react-popover": "^1.1.15",
|
|
||||||
"@radix-ui/react-separator": "^1.1.7",
|
"@radix-ui/react-separator": "^1.1.7",
|
||||||
"@radix-ui/react-slot": "^1.2.4",
|
"@radix-ui/react-slot": "^1.2.3",
|
||||||
"@radix-ui/react-switch": "^1.2.6",
|
"@radix-ui/react-switch": "^1.2.6",
|
||||||
"@radix-ui/react-tooltip": "^1.2.8",
|
"@radix-ui/react-tooltip": "^1.2.8",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"cmdk": "^1.1.1",
|
|
||||||
"date-fns": "^4.1.0",
|
|
||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
"leaflet-defaulticon-compatibility": "^0.1.2",
|
"leaflet-defaulticon-compatibility": "^0.1.2",
|
||||||
"lucide-react": "^0.546.0",
|
"lucide-react": "^0.546.0",
|
||||||
"next": "15.5.5",
|
"next": "15.5.5",
|
||||||
"prisma": "^6.17.1",
|
|
||||||
"react": "19.1.0",
|
"react": "19.1.0",
|
||||||
"react-day-picker": "^9.11.1",
|
|
||||||
"react-dom": "19.1.0",
|
"react-dom": "19.1.0",
|
||||||
"react-leaflet": "^5.0.0",
|
"react-leaflet": "^5.0.0",
|
||||||
"tailwind-merge": "^3.3.1"
|
"tailwind-merge": "^3.3.1"
|
||||||
|
|
@ -39,9 +33,8 @@
|
||||||
"@tailwindcss/postcss": "^4",
|
"@tailwindcss/postcss": "^4",
|
||||||
"@types/leaflet": "^1.9.21",
|
"@types/leaflet": "^1.9.21",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "^19.2.6",
|
"@types/react": "^19",
|
||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
"prisma": "^6.18.0",
|
|
||||||
"tailwindcss": "^4",
|
"tailwindcss": "^4",
|
||||||
"tw-animate-css": "^1.4.0",
|
"tw-animate-css": "^1.4.0",
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
|
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
-- 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;
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE "Registratore" ADD COLUMN "data_acquisto" DATE,
|
|
||||||
ADD COLUMN "prossima_verifica" DATE,
|
|
||||||
ADD COLUMN "seriale" VARCHAR(255),
|
|
||||||
ADD COLUMN "ultima_verifica" DATE;
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
/*
|
|
||||||
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;
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
/*
|
|
||||||
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";
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
-- CreateEnum
|
|
||||||
CREATE TYPE "Modello" AS ENUM ('FORM100', 'FORM200', 'FORM500');
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE "Registratore" ADD COLUMN "modello" "Modello";
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
-- AlterEnum
|
|
||||||
ALTER TYPE "Modello" ADD VALUE 'FORM200PLUS';
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE "Cliente" ADD COLUMN "coordinate" DOUBLE PRECISION[];
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
/*
|
|
||||||
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;
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
/*
|
|
||||||
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;
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE "Cliente" ALTER COLUMN "sede_url" SET DATA TYPE TEXT;
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
# Please do not edit this file manually
|
|
||||||
# It should be added in your version-control system (e.g., Git)
|
|
||||||
provider = "postgresql"
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
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[]
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
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 });
|
|
||||||
}
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
import { Cliente, Modello, PrismaClient, Prisma } 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);
|
|
||||||
|
|
||||||
const cliente = {
|
|
||||||
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,
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
await prisma.cliente.create({
|
|
||||||
data: cliente,
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
if (e instanceof Prisma.PrismaClientKnownRequestError) {
|
|
||||||
if (e.code == "P2002") {
|
|
||||||
return Response.json(
|
|
||||||
{ message: "Il cliente esista già" },
|
|
||||||
{ status: 400 },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Response.json({ message: "Cliente creato" });
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
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" });
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
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 });
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
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" });
|
|
||||||
}
|
|
||||||
112
src/app/client/[client]/page.tsx
Normal file
112
src/app/client/[client]/page.tsx
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { AppSidebar } from "@/components/app-sidebar";
|
||||||
|
import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar";
|
||||||
|
import ClientCard from "@/components/client-card";
|
||||||
|
import DeviceCard from "@/components/device-card";
|
||||||
|
import { useSearchParams, useParams } from "next/navigation";
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
const { client } = useParams();
|
||||||
|
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SidebarProvider
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
"--sidebar-width": "350px",
|
||||||
|
} as React.CSSProperties
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<AppSidebar />
|
||||||
|
<SidebarInset>
|
||||||
|
|
||||||
|
<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} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</SidebarInset>
|
||||||
|
</SidebarProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
"use client";
|
|
||||||
|
|
||||||
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";
|
|
||||||
|
|
||||||
function ClientComponent() {
|
|
||||||
const searchParams = useSearchParams();
|
|
||||||
const id = searchParams.get("client");
|
|
||||||
const [cliente, setCliente] = useState<Cliente>();
|
|
||||||
const [registratori, setRegistratori] = useState<Array<Registratore>>();
|
|
||||||
|
|
||||||
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">
|
|
||||||
{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,13 +28,25 @@ import {
|
||||||
} from "@/components/ui/table";
|
} from "@/components/ui/table";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
import { useSearchParams } from "next/navigation";
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
return (
|
return (
|
||||||
|
<SidebarProvider
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
"--sidebar-width": "350px",
|
||||||
|
} as React.CSSProperties
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<AppSidebar />
|
||||||
|
<SidebarInset>
|
||||||
<div className="flex flex-1 flex-col gap-4 p-4">
|
<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">
|
<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">
|
||||||
THIS IS A DASHBOARD, AND I DON'T KNOW WHAT TO PUT IN IT
|
THIS IS A DASHBOARD, AND I DON'T KNOW WHAT TO PUT IN IT
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</SidebarInset>
|
||||||
|
</SidebarProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { Geist, Geist_Mono } from "next/font/google";
|
import { Geist, Geist_Mono } from "next/font/google";
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar";
|
|
||||||
import { AppSidebar } from "@/components/app-sidebar";
|
|
||||||
|
|
||||||
const geistSans = Geist({
|
const geistSans = Geist({
|
||||||
variable: "--font-geist-sans",
|
variable: "--font-geist-sans",
|
||||||
|
|
@ -29,18 +27,7 @@ export default function RootLayout({
|
||||||
<body
|
<body
|
||||||
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
||||||
>
|
>
|
||||||
<SidebarProvider
|
|
||||||
style={
|
|
||||||
{
|
|
||||||
"--sidebar-width": "350px",
|
|
||||||
} as React.CSSProperties
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<AppSidebar />
|
|
||||||
<SidebarInset>
|
|
||||||
{children}
|
{children}
|
||||||
</SidebarInset>
|
|
||||||
</SidebarProvider>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,27 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import { AppSidebar } from "@/components/app-sidebar";
|
||||||
|
import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar";
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import { useSearchParams } from "next/navigation";
|
|
||||||
import { useEffect, useState, Suspense } from "react";
|
|
||||||
import { Cliente } from "@/generated/prisma";
|
|
||||||
|
|
||||||
function MapContent() {
|
export default function Page() {
|
||||||
const MapWithNoSSR = dynamic(() => import("../../components/map"), {
|
const MapWithNoSSR = dynamic(() => import("../../components/map"), {
|
||||||
ssr: false,
|
ssr: false,
|
||||||
});
|
});
|
||||||
const [clienti, setClienti] = useState<Array<Cliente>>();
|
return (
|
||||||
const searchParams = useSearchParams();
|
<SidebarProvider
|
||||||
const client = searchParams.get("client");
|
style={
|
||||||
|
{
|
||||||
useEffect(() => {
|
"--sidebar-width": "350px",
|
||||||
async function getClienti() {
|
} as React.CSSProperties
|
||||||
const req = await fetch(`/api/clienti`);
|
|
||||||
const data = await req.json();
|
|
||||||
setClienti(data.clients);
|
|
||||||
}
|
}
|
||||||
|
>
|
||||||
getClienti();
|
<AppSidebar />
|
||||||
}, []);
|
<SidebarInset>
|
||||||
|
|
||||||
return (
|
|
||||||
<div id="map" className="w-full h-full border rounded-md m-0 p-0">
|
<div id="map" className="w-full h-full border rounded-md m-0 p-0">
|
||||||
<MapWithNoSSR
|
<MapWithNoSSR />
|
||||||
highlight={clienti?.find((cliente) => cliente.id == +(client || -1))}
|
|
||||||
clienti={clienti || undefined}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
</SidebarInset>
|
||||||
}
|
</SidebarProvider>
|
||||||
|
|
||||||
export default function Page() {
|
|
||||||
return (
|
|
||||||
<Suspense fallback={<div>Caricamento mappa...</div>}>
|
|
||||||
<MapContent />
|
|
||||||
</Suspense>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,161 +0,0 @@
|
||||||
"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 { Spinner } from "@/components/ui/spinner";
|
|
||||||
import { useState } from "react";
|
|
||||||
|
|
||||||
const AddClientDialog = () => {
|
|
||||||
const [wait, setWait] = useState(false);
|
|
||||||
const [open, setOpen] = useState(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 () => {
|
|
||||||
setWait(true);
|
|
||||||
|
|
||||||
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,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
setWait(false);
|
|
||||||
|
|
||||||
if (res.status == 200) {
|
|
||||||
setOpen(false);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
type="submit"
|
|
||||||
disabled={wait}
|
|
||||||
>
|
|
||||||
{wait ? <Spinner /> : <></>}
|
|
||||||
Aggiungi
|
|
||||||
</Button>
|
|
||||||
</DialogFooter>
|
|
||||||
</DialogContent>
|
|
||||||
</form>
|
|
||||||
</Dialog>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AddClientDialog;
|
|
||||||
|
|
@ -1,121 +0,0 @@
|
||||||
"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 [openDialog, setOpenDialog] = useState(false);
|
|
||||||
const [openDatePicker, setOpenDatePicker] = useState(false);
|
|
||||||
const [data, setData] = useState<Date | undefined>(new Date());
|
|
||||||
const [lavoro, setLavoro] = useState<string>("");
|
|
||||||
const [fattura, setFattura] = useState<Boolean>(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Dialog open={openDialog} onOpenChange={setOpenDialog}>
|
|
||||||
<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={openDatePicker}
|
|
||||||
setOpen={setOpenDatePicker}
|
|
||||||
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 () => {
|
|
||||||
const res = await fetch("/api/interventi", {
|
|
||||||
method: "POST",
|
|
||||||
body: JSON.stringify({
|
|
||||||
id: id,
|
|
||||||
data: data,
|
|
||||||
fattura: fattura,
|
|
||||||
lavoro: lavoro,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
if (res.status == 200) {
|
|
||||||
setOpenDialog(false);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
type="submit"
|
|
||||||
>
|
|
||||||
Aggiungi
|
|
||||||
</Button>
|
|
||||||
</DialogFooter>
|
|
||||||
</DialogContent>
|
|
||||||
</form>
|
|
||||||
</Dialog>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AddInterventoDialog;
|
|
||||||
|
|
@ -1,137 +0,0 @@
|
||||||
"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 [openDialog, setOpenDialog] = useState(false);
|
|
||||||
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 open={openDialog} onOpenChange={setOpenDialog}>
|
|
||||||
<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 () => {
|
|
||||||
const res = await fetch("/api/registratori", {
|
|
||||||
method: "POST",
|
|
||||||
body: JSON.stringify({
|
|
||||||
id: id,
|
|
||||||
seriale: seriale,
|
|
||||||
data: data,
|
|
||||||
modello: modello,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (res.status == 200) {
|
|
||||||
setOpenDialog(false);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
type="submit"
|
|
||||||
>
|
|
||||||
Aggiungi
|
|
||||||
</Button>
|
|
||||||
</DialogFooter>
|
|
||||||
</DialogContent>
|
|
||||||
</form>
|
|
||||||
</Dialog>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AddRegistratoreDialog;
|
|
||||||
|
|
@ -2,10 +2,9 @@
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { Home, Map } from "lucide-react";
|
import { Home, Map } from "lucide-react";
|
||||||
|
|
||||||
import { NavUser } from "@/components/nav-user";
|
import { NavUser } from "@/components/nav-user";
|
||||||
import { Avatar, AvatarImage } from "./ui/avatar";
|
import { Label } from "@/components/ui/label";
|
||||||
import { useState, useEffect } from "react";
|
|
||||||
import { usePathname, useRouter } from "next/navigation";
|
|
||||||
import {
|
import {
|
||||||
Sidebar,
|
Sidebar,
|
||||||
SidebarContent,
|
SidebarContent,
|
||||||
|
|
@ -19,15 +18,11 @@ import {
|
||||||
SidebarMenuItem,
|
SidebarMenuItem,
|
||||||
useSidebar,
|
useSidebar,
|
||||||
} from "@/components/ui/sidebar";
|
} from "@/components/ui/sidebar";
|
||||||
import {
|
import { Switch } from "@/components/ui/switch";
|
||||||
Tooltip,
|
import { Avatar, AvatarImage } from "./ui/avatar";
|
||||||
TooltipContent,
|
|
||||||
TooltipTrigger,
|
import { useState, useEffect } from "react";
|
||||||
} from "@/components/ui/tooltip";
|
import { usePathname, useRouter } from "next/navigation";
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { XIcon } from "lucide-react";
|
|
||||||
import AddClientDialog from "./add-client";
|
|
||||||
import { Cliente } from "@/generated/prisma";
|
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
user: {
|
user: {
|
||||||
|
|
@ -38,28 +33,17 @@ const data = {
|
||||||
navMain: [
|
navMain: [
|
||||||
{
|
{
|
||||||
title: "Dashboard",
|
title: "Dashboard",
|
||||||
page: "dashboard",
|
|
||||||
url: "/dashboard",
|
url: "/dashboard",
|
||||||
icon: Home,
|
icon: Home,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
isVisible: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Map",
|
title: "Map",
|
||||||
page: "map",
|
|
||||||
url: "/map",
|
url: "/map",
|
||||||
icon: Map,
|
icon: Map,
|
||||||
isActive: false,
|
isActive: false,
|
||||||
isVisible: true,
|
|
||||||
},
|
},
|
||||||
{
|
],
|
||||||
title: "Dettaglio cliente",
|
|
||||||
page: "client",
|
|
||||||
url: "/client",
|
|
||||||
icon: Home,
|
|
||||||
isVisible: false,
|
|
||||||
},
|
|
||||||
] /*
|
|
||||||
clienti: [
|
clienti: [
|
||||||
{
|
{
|
||||||
name: "Savoldi Ettore",
|
name: "Savoldi Ettore",
|
||||||
|
|
@ -131,26 +115,16 @@ const data = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],*/,
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [clientPathname, setClientPathname] = useState("");
|
const [clientPathname, setClientPathname] = useState("");
|
||||||
const [clienti, setClienti] = useState<Array<Cliente>>();
|
const [clienti, setClienti] = React.useState(data.clienti);
|
||||||
const { setOpen } = useSidebar();
|
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(() => {
|
useEffect(() => {
|
||||||
setClientPathname(pathname);
|
setClientPathname(pathname);
|
||||||
}, [pathname]);
|
}, [pathname]);
|
||||||
|
|
@ -162,6 +136,9 @@ export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
||||||
variant="inset"
|
variant="inset"
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
|
{/* This is the first sidebar */}
|
||||||
|
{/* We disable collapsible and adjust width to icon. */}
|
||||||
|
{/* This will make the sidebar appear as icons. */}
|
||||||
<Sidebar
|
<Sidebar
|
||||||
collapsible="none"
|
collapsible="none"
|
||||||
className="w-[calc(var(--sidebar-width-icon)+1px)]! border-r"
|
className="w-[calc(var(--sidebar-width-icon)+1px)]! border-r"
|
||||||
|
|
@ -198,11 +175,7 @@ export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
||||||
<SidebarGroup>
|
<SidebarGroup>
|
||||||
<SidebarGroupContent className="px-1.5 md:px-0">
|
<SidebarGroupContent className="px-1.5 md:px-0">
|
||||||
<SidebarMenu>
|
<SidebarMenu>
|
||||||
{data.navMain.map((item) => {
|
{data.navMain.map((item) => (
|
||||||
if (!item.isVisible) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<SidebarMenuItem key={item.title}>
|
<SidebarMenuItem key={item.title}>
|
||||||
<SidebarMenuButton
|
<SidebarMenuButton
|
||||||
tooltip={{
|
tooltip={{
|
||||||
|
|
@ -210,6 +183,15 @@ export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
||||||
hidden: false,
|
hidden: false,
|
||||||
}}
|
}}
|
||||||
onClick={() => {
|
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);
|
setOpen(true);
|
||||||
if (clientPathname != item.url) {
|
if (clientPathname != item.url) {
|
||||||
router.push(item.url);
|
router.push(item.url);
|
||||||
|
|
@ -222,8 +204,7 @@ export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
||||||
<span>{item.title}</span>
|
<span>{item.title}</span>
|
||||||
</SidebarMenuButton>
|
</SidebarMenuButton>
|
||||||
</SidebarMenuItem>
|
</SidebarMenuItem>
|
||||||
);
|
))}
|
||||||
})}
|
|
||||||
</SidebarMenu>
|
</SidebarMenu>
|
||||||
</SidebarGroupContent>
|
</SidebarGroupContent>
|
||||||
</SidebarGroup>
|
</SidebarGroup>
|
||||||
|
|
@ -233,6 +214,8 @@ export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
||||||
</SidebarFooter>
|
</SidebarFooter>
|
||||||
</Sidebar>
|
</Sidebar>
|
||||||
|
|
||||||
|
{/* This is the second sidebar */}
|
||||||
|
{/* We disable collapsible and let it fill remaining space */}
|
||||||
<Sidebar collapsible="none" className="hidden flex-1 md:flex">
|
<Sidebar collapsible="none" className="hidden flex-1 md:flex">
|
||||||
<SidebarHeader className="gap-3.5 border-b p-4">
|
<SidebarHeader className="gap-3.5 border-b p-4">
|
||||||
<div className="flex w-full items-center justify-between">
|
<div className="flex w-full items-center justify-between">
|
||||||
|
|
@ -242,56 +225,31 @@ export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
||||||
: data.navMain.find((entry) => entry.url == clientPathname)
|
: data.navMain.find((entry) => entry.url == clientPathname)
|
||||||
?.title}
|
?.title}
|
||||||
</div>
|
</div>
|
||||||
|
{/*<Label className="flex items-center gap-2 text-sm">
|
||||||
|
<span>Unreads</span>
|
||||||
|
<Switch className="shadow-none" />
|
||||||
|
</Label>*/}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row max-h-max gap-2">
|
<SidebarInput placeholder="Type to search..." />
|
||||||
<SidebarInput
|
|
||||||
placeholder="Digita per cercare..."
|
|
||||||
className="h-full"
|
|
||||||
/>
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger asChild>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
onClick={() => {
|
|
||||||
if (clientPathname.split("/")[1] == "map") {
|
|
||||||
router.replace("/map", undefined);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<XIcon className="size-4" />
|
|
||||||
</Button>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent>
|
|
||||||
<p>Resetta ricerca</p>
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
<AddClientDialog />
|
|
||||||
</SidebarHeader>
|
</SidebarHeader>
|
||||||
<SidebarContent>
|
<SidebarContent>
|
||||||
<SidebarGroup className="px-0">
|
<SidebarGroup className="px-0">
|
||||||
<SidebarGroupContent className="">
|
<SidebarGroupContent className="">
|
||||||
{clienti?.map((cliente) => (
|
{clienti.map((cliente) => (
|
||||||
<span
|
<a
|
||||||
onClick={() => {
|
href="#"
|
||||||
let path = clientPathname.split("/")[1];
|
onClick={() => router.push(`/client/${cliente.name}`)}
|
||||||
if (path == "dashboard" || path == "") {
|
key={cliente.name}
|
||||||
path = "client";
|
className="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"
|
||||||
}
|
|
||||||
router.push(`/${path}?client=${cliente.id}`);
|
|
||||||
}}
|
|
||||||
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.ragione_sociale}</span>
|
<span className="font-medium">{cliente.name}</span>
|
||||||
<div className="flex w-full items-center gap-2">
|
<div className="flex w-full items-center gap-2">
|
||||||
<span className="text-xs">
|
<span className="text-xs">{cliente.sede}</span>
|
||||||
{cliente.sede.length > 35
|
|
||||||
? cliente.sede.substring(0, 35) + "..."
|
|
||||||
: cliente.sede}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
<span className="line-clamp-2 w-[260px] text-xs whitespace-break-spaces">
|
||||||
|
{cliente.registratori[0].prossima_verifica}
|
||||||
</span>
|
</span>
|
||||||
|
</a>
|
||||||
))}
|
))}
|
||||||
</SidebarGroupContent>
|
</SidebarGroupContent>
|
||||||
</SidebarGroup>
|
</SidebarGroup>
|
||||||
|
|
|
||||||
|
|
@ -12,15 +12,13 @@ import {
|
||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Edit, Plus } from "lucide-react";
|
import { Edit, Plus } from "lucide-react";
|
||||||
import { Cliente } from "@/generated/prisma";
|
|
||||||
import AddRegistratoreDialog from "./add-registratore";
|
|
||||||
|
|
||||||
const ClientCard = ({ cliente }: { cliente: Cliente }) => {
|
const ClientCard = ({client}: {client: any}) => {
|
||||||
return (
|
return (
|
||||||
<Card className="@container/card">
|
<Card className="@container/card">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="text-xl font-semibold tabular-nums @[250px]/card:text-2xl">
|
<CardTitle className="text-xl font-semibold tabular-nums @[250px]/card:text-2xl">
|
||||||
{cliente.ragione_sociale}
|
{client}
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<CardAction className="flex items-center gap-4">
|
<CardAction className="flex items-center gap-4">
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
|
|
@ -33,20 +31,37 @@ const ClientCard = ({ cliente }: { cliente: Cliente }) => {
|
||||||
<p>Modifica dettagli</p>
|
<p>Modifica dettagli</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<AddRegistratoreDialog id={cliente.id} />
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<Button variant="outline">
|
||||||
|
<Plus className="size-4" />
|
||||||
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
<p>Aggiungi registratore</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
</CardAction>
|
</CardAction>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="flex items-start gap-20 text-md">
|
<CardContent className="flex items-start gap-20 text-md">
|
||||||
<div className="flex-col items-start gap-1.5 text-md">
|
<div className="flex-col items-start gap-1.5 text-md">
|
||||||
<div className="text-muted-foreground">Partita IVA</div>
|
<div className="text-muted-foreground">Ragione Sociale</div>
|
||||||
<div className="line-clamp-1 flex gap-2 font-medium">
|
<div className="line-clamp-1 flex gap-2 font-medium">
|
||||||
{cliente.partita_iva}
|
Acconciature Uomo
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-col items-start gap-1.5 text-md">
|
<div className="flex-col items-start gap-1.5 text-md">
|
||||||
<div className="text-muted-foreground">Numero di Telefono</div>
|
<div className="text-muted-foreground">Partita IVA</div>
|
||||||
<div className="line-clamp-1 flex gap-2 font-medium">
|
<div className="line-clamp-1 flex gap-2 font-medium">
|
||||||
{cliente.telefono}
|
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>
|
</div>
|
||||||
<div className="flex-col items-start gap-1.5 text-md">
|
<div className="flex-col items-start gap-1.5 text-md">
|
||||||
|
|
@ -55,9 +70,9 @@ const ClientCard = ({ cliente }: { cliente: Cliente }) => {
|
||||||
<a
|
<a
|
||||||
className="text-blue-700 italic underline"
|
className="text-blue-700 italic underline"
|
||||||
target="blank"
|
target="blank"
|
||||||
href={cliente.sede_url}
|
href="https://maps.app.goo.gl/9uNbw2a62ZCCjkQc7"
|
||||||
>
|
>
|
||||||
{cliente.sede}
|
Via Umberto I 60/T, Flero (BS)
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -67,7 +82,7 @@ const ClientCard = ({ cliente }: { cliente: Cliente }) => {
|
||||||
<a
|
<a
|
||||||
className="text-blue-700 italic underline"
|
className="text-blue-700 italic underline"
|
||||||
target="blank"
|
target="blank"
|
||||||
href={cliente.contratto}
|
href="https://google.com"
|
||||||
>
|
>
|
||||||
LINK
|
LINK
|
||||||
</a>
|
</a>
|
||||||
|
|
@ -75,7 +90,7 @@ const ClientCard = ({ cliente }: { cliente: Cliente }) => {
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default ClientCard;
|
export default ClientCard;
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
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,5 +1,3 @@
|
||||||
"use client";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CardAction,
|
CardAction,
|
||||||
|
|
@ -26,15 +24,43 @@ import { Button } from "@/components/ui/button";
|
||||||
import { Edit, Plus } from "lucide-react";
|
import { Edit, Plus } from "lucide-react";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { Cliente, Registratore } from "@/generated/prisma";
|
import { useParams } from "next/navigation";
|
||||||
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 { client } = useParams();
|
||||||
|
|
||||||
const DeviceCard = ({ registratore }: { registratore: Registratore }) => {
|
|
||||||
return (
|
return (
|
||||||
<Card className="@container/card">
|
<Card className="@container/card">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="text-xl font-semibold tabular-nums @[250px]/card:text-2xl">
|
<CardTitle className="text-xl font-semibold tabular-nums @[250px]/card:text-2xl">
|
||||||
{registratore.modello}
|
FORM 100
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<CardAction className="flex items-center gap-4">
|
<CardAction className="flex items-center gap-4">
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
|
|
@ -47,7 +73,16 @@ const DeviceCard = ({ registratore }: { registratore: Registratore }) => {
|
||||||
<p>Modifica dettagli</p>
|
<p>Modifica dettagli</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<AddInterventoDialog id={registratore.id} />
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<Button variant="outline">
|
||||||
|
<Plus className="size-4" />
|
||||||
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
<p>Aggiungi intervento</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
</CardAction>
|
</CardAction>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="flex flex-col gap-5 text-md">
|
<CardContent className="flex flex-col gap-5 text-md">
|
||||||
|
|
@ -55,37 +90,27 @@ const DeviceCard = ({ registratore }: { registratore: Registratore }) => {
|
||||||
<div className="flex-col items-start gap-1.5 text-md">
|
<div className="flex-col items-start gap-1.5 text-md">
|
||||||
<div className="text-muted-foreground">Seriale</div>
|
<div className="text-muted-foreground">Seriale</div>
|
||||||
<div className="line-clamp-1 flex gap-2 font-medium">
|
<div className="line-clamp-1 flex gap-2 font-medium">
|
||||||
{registratore.id}
|
80E100548745
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-col items-start gap-1.5 text-md">
|
<div className="flex-col items-start gap-1.5 text-md">
|
||||||
<div className="text-muted-foreground">Data acquisto</div>
|
<div className="text-muted-foreground">Data acquisto</div>
|
||||||
<div className="line-clamp-1 flex gap-2 font-medium">
|
<div className="line-clamp-1 flex gap-2 font-medium">
|
||||||
{registratore.data_acquisto
|
15/10/2019
|
||||||
? new Date(registratore.data_acquisto).toLocaleDateString(
|
|
||||||
"it-IT",
|
|
||||||
)
|
|
||||||
: "--"}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-col items-start gap-1.5 text-md">
|
<div className="flex-col items-start gap-1.5 text-md">
|
||||||
<div className="text-muted-foreground">Ultima verifica</div>
|
<div className="text-muted-foreground">Ultima verifica</div>
|
||||||
<div className="line-clamp-1 flex gap-2 font-medium">
|
<div className="line-clamp-1 flex gap-2 font-medium">
|
||||||
{registratore.ultima_verifica
|
15/10/2025
|
||||||
? new Date(registratore.ultima_verifica).toLocaleDateString(
|
|
||||||
"it-IT",
|
|
||||||
)
|
|
||||||
: "--"}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-col items-start gap-1.5 text-md">
|
<div className="flex-col items-start gap-1.5 text-md">
|
||||||
<div className="text-muted-foreground">Prossima verifica</div>
|
<div className="text-muted-foreground">
|
||||||
|
Prossima verifica
|
||||||
|
</div>
|
||||||
<div className="line-clamp-1 flex gap-2 font-medium">
|
<div className="line-clamp-1 flex gap-2 font-medium">
|
||||||
{registratore.prossima_verifica
|
15/10/2026
|
||||||
? new Date(registratore.prossima_verifica).toLocaleDateString(
|
|
||||||
"it-IT",
|
|
||||||
)
|
|
||||||
: "--"}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -102,10 +127,15 @@ const DeviceCard = ({ registratore }: { registratore: Registratore }) => {
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{registratore.interventi.map((intervento) => (
|
{clienti
|
||||||
|
.find(
|
||||||
|
(cliente) =>
|
||||||
|
cliente.name == decodeURIComponent(client?.toString() || ""),
|
||||||
|
)
|
||||||
|
?.registratori[0].interventi.map((intervento) => (
|
||||||
<TableRow key={intervento.id}>
|
<TableRow key={intervento.id}>
|
||||||
<TableCell className="font-medium">
|
<TableCell className="font-medium">
|
||||||
{new Date(intervento.data).toLocaleDateString("it-IT")}
|
{intervento.data}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>{intervento.lavoro}</TableCell>
|
<TableCell>{intervento.lavoro}</TableCell>
|
||||||
<TableCell className="text-right">
|
<TableCell className="text-right">
|
||||||
|
|
@ -132,7 +162,7 @@ const DeviceCard = ({ registratore }: { registratore: Registratore }) => {
|
||||||
</Button>
|
</Button>
|
||||||
</CardFooter>
|
</CardFooter>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default DeviceCard;
|
export default DeviceCard;
|
||||||
|
|
@ -1,47 +1,24 @@
|
||||||
import { MapContainer, Marker, Popup, TileLayer } from "react-leaflet";
|
import { MapContainer, Marker, Popup, TileLayer } from "react-leaflet";
|
||||||
import { Icon } from "leaflet";
|
import { Icon } from "leaflet";
|
||||||
import "leaflet/dist/leaflet.css";
|
import "leaflet/dist/leaflet.css";
|
||||||
import {
|
|
||||||
Tooltip,
|
|
||||||
TooltipContent,
|
|
||||||
TooltipTrigger,
|
|
||||||
} from "@/components/ui/tooltip";
|
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { Map as MapIcon } from "lucide-react";
|
|
||||||
import { Cliente } from "@/generated/prisma";
|
|
||||||
|
|
||||||
const Map = ({
|
const Map = () => {
|
||||||
highlight,
|
|
||||||
clienti,
|
|
||||||
}: {
|
|
||||||
highlight?: Cliente;
|
|
||||||
clienti?: Array<Cliente>;
|
|
||||||
}) => {
|
|
||||||
const positions = [
|
const positions = [
|
||||||
{
|
{
|
||||||
name: "Autogeneral",
|
name: "Autogeneral",
|
||||||
position: [45.49285083101236, 10.15951437254693],
|
position: [45.49285083101236, 10.15951437254693],
|
||||||
sede_url: "https://maps.app.goo.gl/9uNbw2a62ZCCjkQc7",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Delizie e Sapori (Cuor di gelato)",
|
name: "Delizie e Sapori (Cuor di gelato)",
|
||||||
position: [45.55425938252774, 10.227818585851844],
|
position: [45.55425938252774, 10.227818585851844],
|
||||||
sede_url: "https://maps.app.goo.gl/9uNbw2a62ZCCjkQc7",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Casa dell'Ottica di Zanotti Giulio",
|
name: "Casa dell'Ottica di Zanotti Giulio",
|
||||||
position: [45.53644055688526, 10.222584658771389],
|
position: [45.53644055688526, 10.222584658771389],
|
||||||
sede_url: "https://maps.app.goo.gl/9uNbw2a62ZCCjkQc7",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Nuova Ottica",
|
name: "Nuova Ottica",
|
||||||
position: [45.48257540298808, 10.23957216093029],
|
position: [45.48257540298808, 10.23957216093029],
|
||||||
sede_url: "https://maps.app.goo.gl/9uNbw2a62ZCCjkQc7",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Savoldi Ettore",
|
|
||||||
position: [45.486316837251415, 10.1737522099259],
|
|
||||||
sede_url: "https://maps.app.goo.gl/9uNbw2a62ZCCjkQc7",
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -53,95 +30,31 @@ const Map = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MapContainer
|
<MapContainer
|
||||||
center={
|
center={positions[0].position}
|
||||||
highlight
|
zoom={10}
|
||||||
? [highlight.lat, highlight.lon]
|
|
||||||
: [45.54157745559809, 10.211896906975962]
|
|
||||||
}
|
|
||||||
zoom={13}
|
|
||||||
scrollWheelZoom={true}
|
scrollWheelZoom={true}
|
||||||
className="m-0 p-0 h-[99%] w-[99%] mx-[0.5%] my-[0.5%] rounded-md z-0"
|
className="m-0 p-0 h-[99%] w-[99%] mx-[0.5%] my-[0.5%] rounded-md"
|
||||||
>
|
>
|
||||||
<TileLayer
|
<TileLayer
|
||||||
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||||
url={`https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png`}
|
url={`https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png`}
|
||||||
/>
|
/>
|
||||||
{highlight == null ? (
|
{positions.map((client) => (
|
||||||
clienti ? (
|
|
||||||
clienti.map((client) => (
|
|
||||||
<Marker
|
<Marker
|
||||||
position={[client.lat, client.lon]}
|
position={client.position}
|
||||||
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={[highlight.lat, highlight.lon]}
|
|
||||||
draggable={false}
|
draggable={false}
|
||||||
animate={false}
|
animate={false}
|
||||||
icon={customMarker}
|
icon={customMarker}
|
||||||
>
|
>
|
||||||
<Popup className="">
|
<Popup>
|
||||||
<div className="flex flex-row gap-5">
|
<span className="block text-sm font-bold">{client.name}</span>
|
||||||
<div>
|
|
||||||
<span className="block text-sm font-bold">
|
|
||||||
{highlight.ragione_sociale}
|
|
||||||
</span>
|
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<span className="text-xs font-semibold">P.IVA</span>
|
<span className="text-xs font-semibold">P.IVA</span>
|
||||||
<span className="text-xs">03417520172</span>
|
<span className="text-xs">03417520172</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger asChild>
|
|
||||||
<a href={highlight.sede_url} target="blank">
|
|
||||||
<Button variant="outline">
|
|
||||||
<MapIcon className="size-4" />
|
|
||||||
</Button>
|
|
||||||
</a>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent>
|
|
||||||
<p>Resetta ricerca</p>
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
</Popup>
|
</Popup>
|
||||||
</Marker>
|
</Marker>
|
||||||
)}
|
))}
|
||||||
</MapContainer>
|
</MapContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,79 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
@ -1,216 +0,0 @@
|
||||||
"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 }
|
|
||||||
|
|
@ -1,184 +0,0 @@
|
||||||
"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,
|
|
||||||
}
|
|
||||||
|
|
@ -1,143 +0,0 @@
|
||||||
"use client"
|
|
||||||
|
|
||||||
import * as React from "react"
|
|
||||||
import * as DialogPrimitive from "@radix-ui/react-dialog"
|
|
||||||
import { XIcon } from "lucide-react"
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
|
||||||
|
|
||||||
function Dialog({
|
|
||||||
...props
|
|
||||||
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
|
||||||
return <DialogPrimitive.Root data-slot="dialog" {...props} />
|
|
||||||
}
|
|
||||||
|
|
||||||
function DialogTrigger({
|
|
||||||
...props
|
|
||||||
}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
|
||||||
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />
|
|
||||||
}
|
|
||||||
|
|
||||||
function DialogPortal({
|
|
||||||
...props
|
|
||||||
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
|
||||||
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
|
|
||||||
}
|
|
||||||
|
|
||||||
function DialogClose({
|
|
||||||
...props
|
|
||||||
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
|
||||||
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />
|
|
||||||
}
|
|
||||||
|
|
||||||
function DialogOverlay({
|
|
||||||
className,
|
|
||||||
...props
|
|
||||||
}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
|
|
||||||
return (
|
|
||||||
<DialogPrimitive.Overlay
|
|
||||||
data-slot="dialog-overlay"
|
|
||||||
className={cn(
|
|
||||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function DialogContent({
|
|
||||||
className,
|
|
||||||
children,
|
|
||||||
showCloseButton = true,
|
|
||||||
...props
|
|
||||||
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
|
|
||||||
showCloseButton?: boolean
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<DialogPortal data-slot="dialog-portal">
|
|
||||||
<DialogOverlay />
|
|
||||||
<DialogPrimitive.Content
|
|
||||||
data-slot="dialog-content"
|
|
||||||
className={cn(
|
|
||||||
"bg-background 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 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
{showCloseButton && (
|
|
||||||
<DialogPrimitive.Close
|
|
||||||
data-slot="dialog-close"
|
|
||||||
className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
|
|
||||||
>
|
|
||||||
<XIcon />
|
|
||||||
<span className="sr-only">Close</span>
|
|
||||||
</DialogPrimitive.Close>
|
|
||||||
)}
|
|
||||||
</DialogPrimitive.Content>
|
|
||||||
</DialogPortal>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
data-slot="dialog-header"
|
|
||||||
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
data-slot="dialog-footer"
|
|
||||||
className={cn(
|
|
||||||
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function DialogTitle({
|
|
||||||
className,
|
|
||||||
...props
|
|
||||||
}: React.ComponentProps<typeof DialogPrimitive.Title>) {
|
|
||||||
return (
|
|
||||||
<DialogPrimitive.Title
|
|
||||||
data-slot="dialog-title"
|
|
||||||
className={cn("text-lg leading-none font-semibold", className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function DialogDescription({
|
|
||||||
className,
|
|
||||||
...props
|
|
||||||
}: React.ComponentProps<typeof DialogPrimitive.Description>) {
|
|
||||||
return (
|
|
||||||
<DialogPrimitive.Description
|
|
||||||
data-slot="dialog-description"
|
|
||||||
className={cn("text-muted-foreground text-sm", className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export {
|
|
||||||
Dialog,
|
|
||||||
DialogClose,
|
|
||||||
DialogContent,
|
|
||||||
DialogDescription,
|
|
||||||
DialogFooter,
|
|
||||||
DialogHeader,
|
|
||||||
DialogOverlay,
|
|
||||||
DialogPortal,
|
|
||||||
DialogTitle,
|
|
||||||
DialogTrigger,
|
|
||||||
}
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
"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,16 +0,0 @@
|
||||||
import { Loader2Icon } from "lucide-react"
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
|
||||||
|
|
||||||
function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
|
|
||||||
return (
|
|
||||||
<Loader2Icon
|
|
||||||
role="status"
|
|
||||||
aria-label="Loading"
|
|
||||||
className={cn("size-4 animate-spin", className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export { Spinner }
|
|
||||||
1
src/generated/prisma/client.d.ts
vendored
1
src/generated/prisma/client.d.ts
vendored
|
|
@ -1 +0,0 @@
|
||||||
export * from "./index"
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
|
|
||||||
/* !!! This is code generated by Prisma. Do not edit directly. !!!
|
|
||||||
/* eslint-disable */
|
|
||||||
module.exports = { ...require('.') }
|
|
||||||
1
src/generated/prisma/default.d.ts
vendored
1
src/generated/prisma/default.d.ts
vendored
|
|
@ -1 +0,0 @@
|
||||||
export * from "./index"
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
|
|
||||||
/* !!! 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
1
src/generated/prisma/edge.d.ts
vendored
|
|
@ -1 +0,0 @@
|
||||||
export * from "./default"
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,209 +0,0 @@
|
||||||
|
|
||||||
/* !!! 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
6049
src/generated/prisma/index.d.ts
vendored
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
|
@ -1,183 +0,0 @@
|
||||||
{
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
370
src/generated/prisma/runtime/index-browser.d.ts
vendored
370
src/generated/prisma/runtime/index-browser.d.ts
vendored
|
|
@ -1,370 +0,0 @@
|
||||||
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 { }
|
|
||||||
File diff suppressed because one or more lines are too long
3982
src/generated/prisma/runtime/library.d.ts
vendored
3982
src/generated/prisma/runtime/library.d.ts
vendored
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
83
src/generated/prisma/runtime/react-native.js
vendored
83
src/generated/prisma/runtime/react-native.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,48 +0,0 @@
|
||||||
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[]
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
|
|
||||||
/* !!! This is code generated by Prisma. Do not edit directly. !!!
|
|
||||||
/* eslint-disable */
|
|
||||||
export default import('./query_engine_bg.wasm?module')
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
|
|
||||||
/* !!! 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
1
src/generated/prisma/wasm.d.ts
vendored
|
|
@ -1 +0,0 @@
|
||||||
export * from "./default"
|
|
||||||
|
|
@ -1,229 +0,0 @@
|
||||||
|
|
||||||
/* !!! 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