Refactor service document handling and contact modal
- Removed temp_tokens data from SQL initialization. - Updated AllegatiComp to invalidate additional service announcements on file removal. - Simplified imports in interactions.tsx and removed unused components. - Enhanced ServizioContent layout for better display of announcements. - Adjusted button styles in servizio_annunci_accordions for responsiveness. - Streamlined ricerca-table by removing unnecessary ServizioProvider wrapping. - Modified upload modal to support new upload callback structure. - Added new document reference fields to Servizio schema. - Introduced UsersStorageUserStorageId type for better type safety. - Updated servizio.controller to include document references in service announcements. - Changed storage.controller to return user_storage_id on conflict. - Updated docker-compose to streamline storage service configuration. - Created migration script for new foreign key constraints on document references. - Implemented ContattiProprietarioModal to manage document uploads and contact unlocking.
This commit is contained in:
parent
f3c4f231a9
commit
bd5a35a172
15 changed files with 582 additions and 403 deletions
|
|
@ -146,17 +146,16 @@ CREATE TABLE public.annunci (
|
||||||
stato text,
|
stato text,
|
||||||
web boolean,
|
web boolean,
|
||||||
caratteristiche json,
|
caratteristiche json,
|
||||||
url_immagini text[],
|
|
||||||
homepage boolean,
|
homepage boolean,
|
||||||
url_video text[],
|
url_video text[],
|
||||||
email text,
|
email text,
|
||||||
creato_il timestamp without time zone,
|
creato_il timestamp without time zone,
|
||||||
modificato_il timestamp without time zone,
|
modificato_il timestamp without time zone,
|
||||||
consegna integer,
|
consegna integer,
|
||||||
og_url text,
|
|
||||||
disponibile_da date,
|
disponibile_da date,
|
||||||
permanenza integer[],
|
permanenza integer[],
|
||||||
persone text[]
|
persone text[],
|
||||||
|
updated_at timestamp without time zone
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -394,6 +393,21 @@ CREATE TABLE public.flags (
|
||||||
|
|
||||||
ALTER TABLE public.flags OWNER TO postgres;
|
ALTER TABLE public.flags OWNER TO postgres;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: images_refs; Type: TABLE; Schema: public; Owner: postgres
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE public.images_refs (
|
||||||
|
codice text NOT NULL,
|
||||||
|
ordine integer NOT NULL,
|
||||||
|
img text NOT NULL,
|
||||||
|
thumb text NOT NULL,
|
||||||
|
og_url text NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
ALTER TABLE public.images_refs OWNER TO postgres;
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: messages; Type: TABLE; Schema: public; Owner: postgres
|
-- Name: messages; Type: TABLE; Schema: public; Owner: postgres
|
||||||
--
|
--
|
||||||
|
|
@ -410,18 +424,6 @@ CREATE TABLE public.messages (
|
||||||
|
|
||||||
ALTER TABLE public.messages OWNER TO postgres;
|
ALTER TABLE public.messages OWNER TO postgres;
|
||||||
|
|
||||||
--
|
|
||||||
-- Name: miogest_images_ref; Type: TABLE; Schema: public; Owner: postgres
|
|
||||||
--
|
|
||||||
|
|
||||||
CREATE TABLE public.miogest_images_ref (
|
|
||||||
codice text NOT NULL,
|
|
||||||
foto text[]
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
ALTER TABLE public.miogest_images_ref OWNER TO postgres;
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: ordini; Type: TABLE; Schema: public; Owner: postgres
|
-- Name: ordini; Type: TABLE; Schema: public; Owner: postgres
|
||||||
--
|
--
|
||||||
|
|
@ -526,7 +528,10 @@ CREATE TABLE public.servizio (
|
||||||
permanenza integer,
|
permanenza integer,
|
||||||
"isOkAcconto" boolean DEFAULT false NOT NULL,
|
"isOkAcconto" boolean DEFAULT false NOT NULL,
|
||||||
"isOkSaldo" boolean DEFAULT false NOT NULL,
|
"isOkSaldo" boolean DEFAULT false NOT NULL,
|
||||||
"isOkConsulenza" boolean DEFAULT false NOT NULL
|
"isOkConsulenza" boolean DEFAULT false NOT NULL,
|
||||||
|
doc_personale_fronte_ref uuid,
|
||||||
|
doc_personale_retro_ref uuid,
|
||||||
|
doc_motivazione_ref uuid
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -541,7 +546,7 @@ CREATE TABLE public.servizio_annunci (
|
||||||
annunci_id integer NOT NULL,
|
annunci_id integer NOT NULL,
|
||||||
created_at timestamp without time zone DEFAULT now() NOT NULL,
|
created_at timestamp without time zone DEFAULT now() NOT NULL,
|
||||||
open_contatti_at timestamp without time zone,
|
open_contatti_at timestamp without time zone,
|
||||||
doc_conferma_ref uuid,
|
doc_conferma_ref text,
|
||||||
user_confirmed_at timestamp without time zone,
|
user_confirmed_at timestamp without time zone,
|
||||||
accettato_conferma_at timestamp without time zone,
|
accettato_conferma_at timestamp without time zone,
|
||||||
caparra_causale text,
|
caparra_causale text,
|
||||||
|
|
@ -549,12 +554,12 @@ CREATE TABLE public.servizio_annunci (
|
||||||
caparra_importo text,
|
caparra_importo text,
|
||||||
caparra_intestazione text,
|
caparra_intestazione text,
|
||||||
"hasConfermaAdmin" boolean DEFAULT false NOT NULL,
|
"hasConfermaAdmin" boolean DEFAULT false NOT NULL,
|
||||||
doc_contratto_ref uuid,
|
doc_contratto_ref text,
|
||||||
gestionale_id integer,
|
gestionale_id integer,
|
||||||
contratto_decorrenza date,
|
contratto_decorrenza date,
|
||||||
contratto_scadenza date,
|
contratto_scadenza date,
|
||||||
contratto_tipo text,
|
contratto_tipo text,
|
||||||
doc_registrazione_ref uuid,
|
doc_registrazione_ref text,
|
||||||
doc_conferma_added boolean DEFAULT false NOT NULL,
|
doc_conferma_added boolean DEFAULT false NOT NULL,
|
||||||
doc_contratto_added boolean DEFAULT false NOT NULL,
|
doc_contratto_added boolean DEFAULT false NOT NULL,
|
||||||
doc_registrazione_added boolean DEFAULT false NOT NULL
|
doc_registrazione_added boolean DEFAULT false NOT NULL
|
||||||
|
|
@ -575,34 +580,6 @@ CREATE TABLE public.servizio_interessi (
|
||||||
|
|
||||||
ALTER TABLE public.servizio_interessi OWNER TO postgres;
|
ALTER TABLE public.servizio_interessi OWNER TO postgres;
|
||||||
|
|
||||||
--
|
|
||||||
-- Name: storageindex; Type: TABLE; Schema: public; Owner: postgres
|
|
||||||
--
|
|
||||||
|
|
||||||
CREATE TABLE public.storageindex (
|
|
||||||
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
||||||
created_at timestamp without time zone DEFAULT now() NOT NULL,
|
|
||||||
filename text,
|
|
||||||
ext text,
|
|
||||||
from_admin boolean DEFAULT false NOT NULL,
|
|
||||||
expires_at timestamp without time zone
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
ALTER TABLE public.storageindex OWNER TO postgres;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Name: temp_tokens; Type: TABLE; Schema: public; Owner: postgres
|
|
||||||
--
|
|
||||||
|
|
||||||
CREATE TABLE public.temp_tokens (
|
|
||||||
token uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
||||||
elapse timestamp without time zone DEFAULT (now() + '00:00:30'::interval) NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
ALTER TABLE public.temp_tokens OWNER TO postgres;
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: testi_e_stringhe; Type: TABLE; Schema: public; Owner: postgres
|
-- Name: testi_e_stringhe; Type: TABLE; Schema: public; Owner: postgres
|
||||||
--
|
--
|
||||||
|
|
@ -677,8 +654,10 @@ ALTER TABLE public.users_anagrafica OWNER TO postgres;
|
||||||
--
|
--
|
||||||
|
|
||||||
CREATE TABLE public.users_storage (
|
CREATE TABLE public.users_storage (
|
||||||
userid uuid NOT NULL,
|
"userId" uuid NOT NULL,
|
||||||
storageid uuid NOT NULL
|
"storageId" text NOT NULL,
|
||||||
|
from_admin boolean DEFAULT false NOT NULL,
|
||||||
|
user_storage_id uuid DEFAULT gen_random_uuid() NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -791,6 +770,14 @@ ALTER TABLE ONLY public.event_queue
|
||||||
ADD CONSTRAINT event_queue_pkey PRIMARY KEY (event_id);
|
ADD CONSTRAINT event_queue_pkey PRIMARY KEY (event_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: images_refs img_cod_order; Type: CONSTRAINT; Schema: public; Owner: postgres
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.images_refs
|
||||||
|
ADD CONSTRAINT img_cod_order UNIQUE (codice, ordine);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: messages messages_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
|
-- Name: messages messages_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
|
||||||
--
|
--
|
||||||
|
|
@ -799,14 +786,6 @@ ALTER TABLE ONLY public.messages
|
||||||
ADD CONSTRAINT messages_pkey PRIMARY KEY (messageid);
|
ADD CONSTRAINT messages_pkey PRIMARY KEY (messageid);
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Name: miogest_images_ref miogest_images_ref_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
|
|
||||||
--
|
|
||||||
|
|
||||||
ALTER TABLE ONLY public.miogest_images_ref
|
|
||||||
ADD CONSTRAINT miogest_images_ref_pkey PRIMARY KEY (codice);
|
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: ordini ordini2_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
|
-- Name: ordini ordini2_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
|
||||||
--
|
--
|
||||||
|
|
@ -847,30 +826,6 @@ ALTER TABLE ONLY public.flags
|
||||||
ADD CONSTRAINT sitesettings_pkey PRIMARY KEY (id);
|
ADD CONSTRAINT sitesettings_pkey PRIMARY KEY (id);
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Name: users_storage sotrageuser; Type: CONSTRAINT; Schema: public; Owner: postgres
|
|
||||||
--
|
|
||||||
|
|
||||||
ALTER TABLE ONLY public.users_storage
|
|
||||||
ADD CONSTRAINT sotrageuser UNIQUE (userid, storageid);
|
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Name: storageindex storageindex_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
|
|
||||||
--
|
|
||||||
|
|
||||||
ALTER TABLE ONLY public.storageindex
|
|
||||||
ADD CONSTRAINT storageindex_pkey PRIMARY KEY (id);
|
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Name: temp_tokens temp_tokens_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
|
|
||||||
--
|
|
||||||
|
|
||||||
ALTER TABLE ONLY public.temp_tokens
|
|
||||||
ADD CONSTRAINT temp_tokens_pkey PRIMARY KEY (token);
|
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: testi_e_stringhe testi_e_stringhe_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
|
-- Name: testi_e_stringhe testi_e_stringhe_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
|
||||||
--
|
--
|
||||||
|
|
@ -895,6 +850,14 @@ ALTER TABLE ONLY public.servizio_annunci
|
||||||
ADD CONSTRAINT uniq_annuncio_servizio UNIQUE (annunci_id, servizio_id);
|
ADD CONSTRAINT uniq_annuncio_servizio UNIQUE (annunci_id, servizio_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: users_storage unique_user_storage; Type: CONSTRAINT; Schema: public; Owner: postgres
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.users_storage
|
||||||
|
ADD CONSTRAINT unique_user_storage UNIQUE ("userId", "storageId");
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: servizio_interessi uniqui_interest; Type: CONSTRAINT; Schema: public; Owner: postgres
|
-- Name: servizio_interessi uniqui_interest; Type: CONSTRAINT; Schema: public; Owner: postgres
|
||||||
--
|
--
|
||||||
|
|
@ -919,6 +882,14 @@ ALTER TABLE ONLY public.users
|
||||||
ADD CONSTRAINT users_pkey PRIMARY KEY (id);
|
ADD CONSTRAINT users_pkey PRIMARY KEY (id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: users_storage users_storage_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.users_storage
|
||||||
|
ADD CONSTRAINT users_storage_pkey PRIMARY KEY (user_storage_id);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: users_anagrafica usersanagrafica2_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
|
-- Name: users_anagrafica usersanagrafica2_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
|
||||||
--
|
--
|
||||||
|
|
@ -935,13 +906,6 @@ ALTER TABLE ONLY public.users_anagrafica
|
||||||
ADD CONSTRAINT usserunique2 UNIQUE (userid);
|
ADD CONSTRAINT usserunique2 UNIQUE (userid);
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Name: annunci_immagini_index; Type: INDEX; Schema: public; Owner: postgres
|
|
||||||
--
|
|
||||||
|
|
||||||
CREATE INDEX annunci_immagini_index ON public.annunci USING gin (url_immagini);
|
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: ratelimiter_key_index; Type: INDEX; Schema: public; Owner: postgres
|
-- Name: ratelimiter_key_index; Type: INDEX; Schema: public; Owner: postgres
|
||||||
--
|
--
|
||||||
|
|
@ -957,6 +921,14 @@ ALTER TABLE ONLY public.chats_etichette
|
||||||
ADD CONSTRAINT chat_etichetta_fkey FOREIGN KEY (chatid) REFERENCES public.chats(chatid) ON UPDATE CASCADE ON DELETE CASCADE;
|
ADD CONSTRAINT chat_etichetta_fkey FOREIGN KEY (chatid) REFERENCES public.chats(chatid) ON UPDATE CASCADE ON DELETE CASCADE;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: images_refs cod_image; Type: FK CONSTRAINT; Schema: public; Owner: postgres
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.images_refs
|
||||||
|
ADD CONSTRAINT cod_image FOREIGN KEY (codice) REFERENCES public.annunci(codice);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: emails email_user; Type: FK CONSTRAINT; Schema: public; Owner: postgres
|
-- Name: emails email_user; Type: FK CONSTRAINT; Schema: public; Owner: postgres
|
||||||
--
|
--
|
||||||
|
|
@ -1070,27 +1042,27 @@ ALTER TABLE ONLY public.servizio_annunci
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: servizio_annunci servizio_annuncio_conferma_doc; Type: FK CONSTRAINT; Schema: public; Owner: postgres
|
-- Name: servizio servizio_doc_fronte; Type: FK CONSTRAINT; Schema: public; Owner: postgres
|
||||||
--
|
--
|
||||||
|
|
||||||
ALTER TABLE ONLY public.servizio_annunci
|
ALTER TABLE ONLY public.servizio
|
||||||
ADD CONSTRAINT servizio_annuncio_conferma_doc FOREIGN KEY (doc_conferma_ref) REFERENCES public.storageindex(id) ON UPDATE CASCADE ON DELETE SET NULL NOT VALID;
|
ADD CONSTRAINT servizio_doc_fronte FOREIGN KEY (doc_personale_fronte_ref) REFERENCES public.users_storage(user_storage_id) ON UPDATE CASCADE ON DELETE SET NULL NOT VALID;
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: servizio_annunci servizio_annuncio_contratto_doc; Type: FK CONSTRAINT; Schema: public; Owner: postgres
|
-- Name: servizio servizio_doc_motivazione; Type: FK CONSTRAINT; Schema: public; Owner: postgres
|
||||||
--
|
--
|
||||||
|
|
||||||
ALTER TABLE ONLY public.servizio_annunci
|
ALTER TABLE ONLY public.servizio
|
||||||
ADD CONSTRAINT servizio_annuncio_contratto_doc FOREIGN KEY (doc_contratto_ref) REFERENCES public.storageindex(id) ON UPDATE CASCADE ON DELETE SET NULL NOT VALID;
|
ADD CONSTRAINT servizio_doc_motivazione FOREIGN KEY (doc_motivazione_ref) REFERENCES public.users_storage(user_storage_id) ON UPDATE CASCADE ON DELETE SET NULL NOT VALID;
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: servizio_annunci servizio_annuncio_registraz_doc; Type: FK CONSTRAINT; Schema: public; Owner: postgres
|
-- Name: servizio servizio_doc_retro; Type: FK CONSTRAINT; Schema: public; Owner: postgres
|
||||||
--
|
--
|
||||||
|
|
||||||
ALTER TABLE ONLY public.servizio_annunci
|
ALTER TABLE ONLY public.servizio
|
||||||
ADD CONSTRAINT servizio_annuncio_registraz_doc FOREIGN KEY (doc_registrazione_ref) REFERENCES public.storageindex(id) ON UPDATE CASCADE ON DELETE SET NULL NOT VALID;
|
ADD CONSTRAINT servizio_doc_retro FOREIGN KEY (doc_personale_retro_ref) REFERENCES public.users_storage(user_storage_id) ON UPDATE CASCADE ON DELETE SET NULL NOT VALID;
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
|
|
@ -1117,20 +1089,12 @@ ALTER TABLE ONLY public.users_anagrafica
|
||||||
ADD CONSTRAINT useridfkeyanagrafica2 FOREIGN KEY (userid) REFERENCES public.users(id) ON UPDATE CASCADE ON DELETE CASCADE NOT VALID;
|
ADD CONSTRAINT useridfkeyanagrafica2 FOREIGN KEY (userid) REFERENCES public.users(id) ON UPDATE CASCADE ON DELETE CASCADE NOT VALID;
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Name: users_storage users_storage_storageid_fkey; Type: FK CONSTRAINT; Schema: public; Owner: postgres
|
|
||||||
--
|
|
||||||
|
|
||||||
ALTER TABLE ONLY public.users_storage
|
|
||||||
ADD CONSTRAINT users_storage_storageid_fkey FOREIGN KEY (storageid) REFERENCES public.storageindex(id) ON UPDATE CASCADE ON DELETE CASCADE NOT VALID;
|
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: users_storage userstorage; Type: FK CONSTRAINT; Schema: public; Owner: postgres
|
-- Name: users_storage userstorage; Type: FK CONSTRAINT; Schema: public; Owner: postgres
|
||||||
--
|
--
|
||||||
|
|
||||||
ALTER TABLE ONLY public.users_storage
|
ALTER TABLE ONLY public.users_storage
|
||||||
ADD CONSTRAINT userstorage FOREIGN KEY (userid) REFERENCES public.users(id) ON UPDATE CASCADE ON DELETE CASCADE;
|
ADD CONSTRAINT userstorage FOREIGN KEY ("userId") REFERENCES public.users(id) ON UPDATE CASCADE ON DELETE CASCADE;
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
|
|
|
||||||
|
|
@ -87,17 +87,6 @@ SALDOCA500+ 38700 CONDIZIONI_CERCHI t Saldo Cerco Stabile (500+) Stable 500+ Sal
|
||||||
\.
|
\.
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Data for Name: temp_tokens; Type: TABLE DATA; Schema: public; Owner: postgres
|
|
||||||
--
|
|
||||||
|
|
||||||
COPY public.temp_tokens (token, elapse) FROM stdin;
|
|
||||||
c256c17d-3299-47a4-b3ef-640aa9688b38 2025-08-22 13:01:41.20164
|
|
||||||
4bd62a5f-aa6d-403b-a1bb-c0e11e382adc 2025-08-22 13:01:48.897271
|
|
||||||
5d069230-9572-4b26-aa06-2964f3ca79a2 2030-02-19 10:25:33.046587
|
|
||||||
\.
|
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Data for Name: testi_e_stringhe; Type: TABLE DATA; Schema: public; Owner: postgres
|
-- Data for Name: testi_e_stringhe; Type: TABLE DATA; Schema: public; Owner: postgres
|
||||||
--
|
--
|
||||||
|
|
|
||||||
20
apps/infoalloggi/migration.sql
Normal file
20
apps/infoalloggi/migration.sql
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
ALTER TABLE
|
||||||
|
IF EXISTS public.servizio
|
||||||
|
ADD
|
||||||
|
CONSTRAINT servizio_doc_fronte FOREIGN KEY (doc_personale_fronte_ref) REFERENCES public.users_storage ("storageId") MATCH SIMPLE ON UPDATE CASCADE ON DELETE
|
||||||
|
SET
|
||||||
|
NULL NOT VALID;
|
||||||
|
|
||||||
|
ALTER TABLE
|
||||||
|
IF EXISTS public.servizio
|
||||||
|
ADD
|
||||||
|
CONSTRAINT servizio_doc_retro FOREIGN KEY (doc_personale_retro_ref) REFERENCES public.users_storage ("storageId") MATCH SIMPLE ON UPDATE CASCADE ON DELETE
|
||||||
|
SET
|
||||||
|
NULL NOT VALID;
|
||||||
|
|
||||||
|
ALTER TABLE
|
||||||
|
IF EXISTS public.servizio
|
||||||
|
ADD
|
||||||
|
CONSTRAINT servizio_doc_motivazione FOREIGN KEY (doc_motivazione_ref) REFERENCES public.users_storage ("storageId") MATCH SIMPLE ON UPDATE CASCADE ON DELETE
|
||||||
|
SET
|
||||||
|
NULL NOT VALID;
|
||||||
|
|
@ -66,6 +66,8 @@ export const AllegatiComp = ({
|
||||||
await utils.storage.retrieveUserFileData.invalidate({
|
await utils.storage.retrieveUserFileData.invalidate({
|
||||||
userId: userId,
|
userId: userId,
|
||||||
});
|
});
|
||||||
|
await utils.servizio.getAllServizioAnnunci.invalidate({ userId });
|
||||||
|
|
||||||
toast.success(t.allegati.allegato_rimosso, {
|
toast.success(t.allegati.allegato_rimosso, {
|
||||||
icon: "🗑️",
|
icon: "🗑️",
|
||||||
id: context?.toastId,
|
id: context?.toastId,
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,14 @@
|
||||||
import {
|
import {
|
||||||
CircleCheck,
|
CircleCheck,
|
||||||
CircleUser,
|
|
||||||
FileBadge,
|
FileBadge,
|
||||||
FileText,
|
FileText,
|
||||||
Handshake,
|
Handshake,
|
||||||
Navigation,
|
|
||||||
PackageCheck,
|
PackageCheck,
|
||||||
Phone,
|
|
||||||
Pointer,
|
Pointer,
|
||||||
TriangleAlert,
|
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { useEffect, useState } from "react";
|
import { useState } from "react";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import {
|
import {
|
||||||
Credenza,
|
Credenza,
|
||||||
|
|
@ -26,7 +22,6 @@ import {
|
||||||
CredenzaTrigger,
|
CredenzaTrigger,
|
||||||
} from "~/components/custom_ui/credenza";
|
} from "~/components/custom_ui/credenza";
|
||||||
import LoadingButton from "~/components/custom_ui/loading-button";
|
import LoadingButton from "~/components/custom_ui/loading-button";
|
||||||
import { LoadingPage } from "~/components/loading";
|
|
||||||
import { Button, type ButtonConfigs } from "~/components/ui/button";
|
import { Button, type ButtonConfigs } from "~/components/ui/button";
|
||||||
import {
|
import {
|
||||||
Tooltip,
|
Tooltip,
|
||||||
|
|
@ -39,7 +34,7 @@ import { useTranslation } from "~/providers/I18nProvider";
|
||||||
import { useServizio, useServizioAnnuncio } from "~/providers/ServizioProvider";
|
import { useServizio, useServizioAnnuncio } from "~/providers/ServizioProvider";
|
||||||
import type { AnnunciId } from "~/schemas/public/Annunci";
|
import type { AnnunciId } from "~/schemas/public/Annunci";
|
||||||
import { api } from "~/utils/api";
|
import { api } from "~/utils/api";
|
||||||
import { WhatsAppIcon2 } from "../svgs";
|
import { ContattiProprietarioModal } from "./modale_contatti";
|
||||||
|
|
||||||
export const Interactions = () => {
|
export const Interactions = () => {
|
||||||
const { servizio, servizioId } = useServizio();
|
const { servizio, servizioId } = useServizio();
|
||||||
|
|
@ -406,225 +401,3 @@ const ConfermaLavorazioneModal = () => {
|
||||||
</Credenza>
|
</Credenza>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ContattiProprietarioModal = () => {
|
|
||||||
const { servizioId, userId } = useServizio();
|
|
||||||
const { data, annuncioId } = useServizioAnnuncio();
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const [showContacts, setShowContacts] = useState<boolean>(
|
|
||||||
data.open_contatti_at != null,
|
|
||||||
);
|
|
||||||
const utils = api.useUtils();
|
|
||||||
|
|
||||||
const { mutate } = api.servizio.unlockServizioContatti.useMutation({
|
|
||||||
onError: (err) => {
|
|
||||||
toast.error(err.message, {
|
|
||||||
id: "unlock-contacts",
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onMutate: () => {
|
|
||||||
toast.loading("Caricamento ...", {
|
|
||||||
id: "unlock-contacts",
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onSuccess: async (data) => {
|
|
||||||
if (!data) {
|
|
||||||
toast.error("Limite di sblocchi raggiunto", {
|
|
||||||
id: "unlock-contacts",
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
toast.success("Successo", {
|
|
||||||
id: "unlock-contacts",
|
|
||||||
});
|
|
||||||
await utils.servizio.getAllServizioAnnunci.invalidate({
|
|
||||||
userId,
|
|
||||||
});
|
|
||||||
setShowContacts(true);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const d = new Date();
|
|
||||||
const tooEarly = d.getHours() < 9;
|
|
||||||
const tooLate = d.getHours() >= 20;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Credenza>
|
|
||||||
<CredenzaTrigger asChild>
|
|
||||||
{showContacts ? (
|
|
||||||
<Button
|
|
||||||
aria-label="Vedi contatti proprietario"
|
|
||||||
className="flex w-fit items-center gap-2"
|
|
||||||
variant="success"
|
|
||||||
>
|
|
||||||
<CircleUser className="size-7" />
|
|
||||||
Vedi i contatti
|
|
||||||
</Button>
|
|
||||||
) : (
|
|
||||||
<Button
|
|
||||||
aria-label="Contatta proprietario"
|
|
||||||
className="flex w-fit items-center gap-2"
|
|
||||||
variant="warning"
|
|
||||||
>
|
|
||||||
<CircleUser className="size-7" />
|
|
||||||
Ottieni i contatti
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</CredenzaTrigger>
|
|
||||||
<CredenzaContent className="max-h-[90vh]">
|
|
||||||
<CredenzaHeader>
|
|
||||||
<CredenzaTitle>{t.contatto.title}</CredenzaTitle>
|
|
||||||
<CredenzaDescription className="sr-only">
|
|
||||||
{t.contatto.descrizione}
|
|
||||||
</CredenzaDescription>
|
|
||||||
</CredenzaHeader>
|
|
||||||
<CredenzaBody className="max-h-[80vh] overflow-auto pb-5">
|
|
||||||
{showContacts ? (
|
|
||||||
<ContattiProprietarioData />
|
|
||||||
) : (
|
|
||||||
<div className="space-y-5">
|
|
||||||
<p>{t.contatto.disclaimer}</p>
|
|
||||||
<p>{t.contatto.disclaimer2}</p>
|
|
||||||
<p className="text-muted-foreground text-xs">
|
|
||||||
{t.contatto.disclaimer3}
|
|
||||||
</p>
|
|
||||||
{(tooEarly || tooLate) && (
|
|
||||||
<div className="flex items-center gap-2 rounded-md bg-yellow-200 p-2">
|
|
||||||
<TriangleAlert className="size-8" />
|
|
||||||
{/*TODO testare */}
|
|
||||||
<p>
|
|
||||||
Il proprietario riceverà la notifica alle ore 9.00{" "}
|
|
||||||
{tooLate && "di domani"}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</CredenzaBody>
|
|
||||||
<CredenzaFooter>
|
|
||||||
{!showContacts && (
|
|
||||||
<Button
|
|
||||||
aria-label="Contatta proprietario"
|
|
||||||
onClick={() =>
|
|
||||||
mutate({
|
|
||||||
annuncioId,
|
|
||||||
servizioId,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
variant="success"
|
|
||||||
>
|
|
||||||
{t.accetta}
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
<CredenzaClose asChild>
|
|
||||||
<Button aria-label="Chiudi modal credenza" variant="outline">
|
|
||||||
{t.chiudi}
|
|
||||||
</Button>
|
|
||||||
</CredenzaClose>
|
|
||||||
</CredenzaFooter>
|
|
||||||
</CredenzaContent>
|
|
||||||
</Credenza>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const ContattiProprietarioData = () => {
|
|
||||||
const { servizioId } = useServizio();
|
|
||||||
const { annuncioId } = useServizioAnnuncio();
|
|
||||||
const { data, isLoading } = api.annunci.getProprietarioData.useQuery({
|
|
||||||
annuncioId,
|
|
||||||
servizioId,
|
|
||||||
});
|
|
||||||
const [navigationUrl, setNavigationUrl] = useState<string | undefined>(
|
|
||||||
undefined,
|
|
||||||
);
|
|
||||||
const { t } = useTranslation();
|
|
||||||
useEffect(() => {
|
|
||||||
if (!data || !data.propData) return;
|
|
||||||
if (typeof window === "undefined") return;
|
|
||||||
if (
|
|
||||||
navigator.userAgent.toUpperCase().includes("MAC") ||
|
|
||||||
navigator.userAgent.toUpperCase().includes("IPAD") ||
|
|
||||||
navigator.userAgent.toUpperCase().includes("IPHONE") ||
|
|
||||||
navigator.userAgent.toUpperCase().includes("IOS") ||
|
|
||||||
navigator.userAgent.toUpperCase().includes("IPOD")
|
|
||||||
) {
|
|
||||||
setNavigationUrl(
|
|
||||||
`maps://www.google.com/maps/dir/?api=1&travelmode=driving&layer=traffic&destination=${data.propData.lat},${data.propData.lon}`,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
setNavigationUrl(
|
|
||||||
`https://www.google.com/maps/dir/?api=1&travelmode=driving&layer=traffic&destination=${data.propData.lat},${data.propData.lon}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}, [data]);
|
|
||||||
|
|
||||||
if (isLoading) {
|
|
||||||
return (
|
|
||||||
<div className="flex justify-center">
|
|
||||||
<LoadingPage />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (!data || !data.propData) {
|
|
||||||
return <p>{t.contatto.error}</p>;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col gap-2">
|
|
||||||
<h3 className="font-semibold">{t.contatto.propietario}:</h3>
|
|
||||||
<p>
|
|
||||||
{t.contatto.nome}: {data.propData.locatore}
|
|
||||||
</p>
|
|
||||||
<a
|
|
||||||
className="flex items-center gap-2"
|
|
||||||
href={`tel:${data.propData.numero}`}
|
|
||||||
>
|
|
||||||
<Phone />:
|
|
||||||
<span className="text-blue-600 underline">{data.propData.numero}</span>
|
|
||||||
<Link href={`https://wa.me/${data.propData.numero}`} target="_blank">
|
|
||||||
<Button
|
|
||||||
className="flex items-center gap-2"
|
|
||||||
size="sm"
|
|
||||||
variant="success"
|
|
||||||
>
|
|
||||||
<WhatsAppIcon2 className="size-4 fill-white" />
|
|
||||||
WhatsApp
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
</a>
|
|
||||||
<br />
|
|
||||||
<h3 className="font-semibold">{t.contatto.immobile}:</h3>
|
|
||||||
<p>
|
|
||||||
{t.contatto.indirizzo}: {data.propData.indirizzo},{" "}
|
|
||||||
{data.propData.civico} {data.propData.comune} ({data.propData.provincia}
|
|
||||||
)
|
|
||||||
</p>
|
|
||||||
<a
|
|
||||||
className="flex w-fit items-center gap-2 rounded-md border border-border px-3 py-2"
|
|
||||||
href={navigationUrl}
|
|
||||||
rel="noreferrer"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
<Navigation /> <span>{t.contatto.apri_nav}</span>
|
|
||||||
</a>
|
|
||||||
<br />
|
|
||||||
<p>
|
|
||||||
{t.contatto.sbloccato_il}:{" "}
|
|
||||||
{data.opened_at.toLocaleString("it", {
|
|
||||||
day: "2-digit",
|
|
||||||
hour: "2-digit",
|
|
||||||
minute: "2-digit",
|
|
||||||
month: "2-digit",
|
|
||||||
year: "numeric",
|
|
||||||
})}
|
|
||||||
</p>
|
|
||||||
<div className="flex items-center gap-2 rounded-md bg-red-500 p-2 text-white">
|
|
||||||
<TriangleAlert className="size-8" />
|
|
||||||
<div>
|
|
||||||
<p>{t.contatto.contatta}</p>
|
|
||||||
<p className="font-semibold">{t.contatto.orari}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ import {
|
||||||
import { api } from "~/utils/api";
|
import { api } from "~/utils/api";
|
||||||
import {
|
import {
|
||||||
AnnunciCompatibili,
|
AnnunciCompatibili,
|
||||||
AnnunciInConferma,
|
|
||||||
AnnunciSelezionati,
|
AnnunciSelezionati,
|
||||||
} from "./servizio_annunci_accordions";
|
} from "./servizio_annunci_accordions";
|
||||||
|
|
||||||
|
|
@ -255,12 +254,22 @@ export const ServizioContent = () => {
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<div className="flex flex-col gap-2 overflow-y-auto">
|
||||||
|
{annunciInConferma.map((data) => {
|
||||||
|
return (
|
||||||
|
<ServizioAnnuncioProvider data={data} key={data.id}>
|
||||||
|
<AnnuncioCard className="border-2 border-green-500" />
|
||||||
|
</ServizioAnnuncioProvider>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex flex-col items-center gap-4 sm:flex-row">
|
||||||
<AnnunciInConferma annunci={annunciInConferma} />
|
|
||||||
<AnnunciSelezionati annunci={annunciNotInConferma} />
|
<AnnunciSelezionati annunci={annunciNotInConferma} />
|
||||||
<AnnunciCompatibili />
|
<AnnunciCompatibili />
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
header={
|
header={
|
||||||
|
|
|
||||||
378
apps/infoalloggi/src/components/servizio/modale_contatti.tsx
Normal file
378
apps/infoalloggi/src/components/servizio/modale_contatti.tsx
Normal file
|
|
@ -0,0 +1,378 @@
|
||||||
|
import {
|
||||||
|
CircleCheck,
|
||||||
|
CircleUser,
|
||||||
|
Navigation,
|
||||||
|
Phone,
|
||||||
|
TriangleAlert,
|
||||||
|
} from "lucide-react";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { useMemo } from "react";
|
||||||
|
import toast from "react-hot-toast";
|
||||||
|
import { useTranslation } from "~/providers/I18nProvider";
|
||||||
|
import { useServizio, useServizioAnnuncio } from "~/providers/ServizioProvider";
|
||||||
|
import type { UsersStorageUserStorageId } from "~/schemas/public/UsersStorage";
|
||||||
|
import { api } from "~/utils/api";
|
||||||
|
import {
|
||||||
|
Credenza,
|
||||||
|
CredenzaBody,
|
||||||
|
CredenzaClose,
|
||||||
|
CredenzaContent,
|
||||||
|
CredenzaDescription,
|
||||||
|
CredenzaFooter,
|
||||||
|
CredenzaHeader,
|
||||||
|
CredenzaTitle,
|
||||||
|
CredenzaTrigger,
|
||||||
|
} from "../custom_ui/credenza";
|
||||||
|
import { LoadingPage } from "../loading";
|
||||||
|
import { WhatsAppIcon2 } from "../svgs";
|
||||||
|
import { Button } from "../ui/button";
|
||||||
|
import { type UploadCallback, UploadModal } from "../upload_modal";
|
||||||
|
|
||||||
|
export const ContattiProprietarioModal = () => {
|
||||||
|
const { servizio } = useServizio();
|
||||||
|
const { data } = useServizioAnnuncio();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
return (
|
||||||
|
<Credenza>
|
||||||
|
<CredenzaTrigger asChild>
|
||||||
|
{data.open_contatti_at != null ? (
|
||||||
|
<Button
|
||||||
|
aria-label="Vedi contatti proprietario"
|
||||||
|
className="flex w-fit items-center gap-2"
|
||||||
|
variant="success"
|
||||||
|
>
|
||||||
|
<CircleUser className="size-7" />
|
||||||
|
Vedi i contatti
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
|
<Button
|
||||||
|
aria-label="Contatta proprietario"
|
||||||
|
className="flex w-fit items-center gap-2"
|
||||||
|
variant="warning"
|
||||||
|
>
|
||||||
|
<CircleUser className="size-7" />
|
||||||
|
Ottieni i contatti
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</CredenzaTrigger>
|
||||||
|
<CredenzaContent className="max-h-[90vh]">
|
||||||
|
<CredenzaHeader>
|
||||||
|
<CredenzaTitle>{t.contatto.title}</CredenzaTitle>
|
||||||
|
<CredenzaDescription className="sr-only">
|
||||||
|
{t.contatto.descrizione}
|
||||||
|
</CredenzaDescription>
|
||||||
|
</CredenzaHeader>
|
||||||
|
{servizio.doc_personale_fronte == null ||
|
||||||
|
servizio.doc_personale_retro == null ? (
|
||||||
|
<DocCheckpoint />
|
||||||
|
// biome-ignore lint/style/noNestedTernary: <this is fine>
|
||||||
|
) : data.open_contatti_at == null ? (
|
||||||
|
<PreUnlock />
|
||||||
|
) : (
|
||||||
|
<PostUnlock />
|
||||||
|
)}
|
||||||
|
</CredenzaContent>
|
||||||
|
</Credenza>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const DocComponent = ({
|
||||||
|
docInfo,
|
||||||
|
cb,
|
||||||
|
}: {
|
||||||
|
docInfo: {
|
||||||
|
storageId: string;
|
||||||
|
ref: UsersStorageUserStorageId | null;
|
||||||
|
} | null;
|
||||||
|
cb: UploadCallback;
|
||||||
|
}) => {
|
||||||
|
const { isAdmin, userId } = useServizio();
|
||||||
|
|
||||||
|
if (!docInfo?.storageId) {
|
||||||
|
return <UploadModal cb_onUpload={cb} isAdmin={isAdmin} userId={userId} />;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className="flex items-center gap-2 text-green-500">
|
||||||
|
<CircleCheck className="size-5" />
|
||||||
|
<span>Documento caricato</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const DocCheckpoint = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { userId, servizio } = useServizio();
|
||||||
|
const utils = api.useUtils();
|
||||||
|
const { mutate } = api.servizio.updateServizio.useMutation({
|
||||||
|
onSuccess: async () => {
|
||||||
|
await utils.servizio.getAllServizioAnnunci.invalidate({
|
||||||
|
userId,
|
||||||
|
});
|
||||||
|
await utils.storage.retrieveUserFileData.invalidate({ userId });
|
||||||
|
await utils.servizio.getServizio.invalidate({
|
||||||
|
servizioId: servizio.servizio_id,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onError: (err) => {
|
||||||
|
toast.error(`Errore aggiornamento servizio: ${err.message}`);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<CredenzaBody className="max-h-[80vh] overflow-auto pb-5">
|
||||||
|
<div className="space-y-5">
|
||||||
|
<p>Devi ancora caricare un tuo documento</p>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
Fronte documento:{" "}
|
||||||
|
<DocComponent
|
||||||
|
cb={({ userStorageIds }) =>
|
||||||
|
userStorageIds.length > 0 &&
|
||||||
|
mutate({
|
||||||
|
servizioId: servizio.servizio_id,
|
||||||
|
data: {
|
||||||
|
doc_personale_fronte_ref: userStorageIds[0],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
docInfo={servizio.doc_personale_fronte}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
Retro documento:{" "}
|
||||||
|
<DocComponent
|
||||||
|
cb={({ userStorageIds }) =>
|
||||||
|
userStorageIds.length > 0 &&
|
||||||
|
mutate({
|
||||||
|
servizioId: servizio.servizio_id,
|
||||||
|
data: {
|
||||||
|
doc_personale_retro_ref: userStorageIds[0],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
docInfo={servizio.doc_personale_retro}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<p className="text-muted-foreground text-sm">
|
||||||
|
I tuoi dati saranno conservati solamente per la durata del servizio,
|
||||||
|
in conformità con la nostra{" "}
|
||||||
|
<Link className="underline" href="/privacy-policy" target="_blank">
|
||||||
|
Informativa sulla Privacy
|
||||||
|
</Link>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</CredenzaBody>
|
||||||
|
<CredenzaFooter>
|
||||||
|
<CredenzaClose asChild>
|
||||||
|
<Button aria-label="Chiudi modal credenza" variant="outline">
|
||||||
|
{t.chiudi}
|
||||||
|
</Button>
|
||||||
|
</CredenzaClose>
|
||||||
|
</CredenzaFooter>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const PreUnlock = () => {
|
||||||
|
const { userId, servizioId } = useServizio();
|
||||||
|
const { annuncioId } = useServizioAnnuncio();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const utils = api.useUtils();
|
||||||
|
|
||||||
|
const { mutate } = api.servizio.unlockServizioContatti.useMutation({
|
||||||
|
onError: (err) => {
|
||||||
|
toast.error(err.message, {
|
||||||
|
id: "unlock-contacts",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onMutate: () => {
|
||||||
|
toast.loading("Caricamento ...", {
|
||||||
|
id: "unlock-contacts",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onSuccess: async (data) => {
|
||||||
|
if (!data) {
|
||||||
|
toast.error("Limite di sblocchi raggiunto", {
|
||||||
|
id: "unlock-contacts",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
toast.success("Successo", {
|
||||||
|
id: "unlock-contacts",
|
||||||
|
});
|
||||||
|
await utils.servizio.getAllServizioAnnunci.invalidate({
|
||||||
|
userId,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const d = new Date();
|
||||||
|
const tooEarly = d.getHours() < 9;
|
||||||
|
const tooLate = d.getHours() >= 20;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<CredenzaBody className="max-h-[80vh] overflow-auto pb-5">
|
||||||
|
<div className="space-y-5">
|
||||||
|
<p>{t.contatto.disclaimer}</p>
|
||||||
|
<p>{t.contatto.disclaimer2}</p>
|
||||||
|
<p className="text-muted-foreground text-xs">
|
||||||
|
{t.contatto.disclaimer3}
|
||||||
|
</p>
|
||||||
|
{(tooEarly || tooLate) && (
|
||||||
|
<div className="flex items-center gap-2 rounded-md bg-yellow-200 p-2">
|
||||||
|
<TriangleAlert className="size-8" />
|
||||||
|
{/*TODO testare */}
|
||||||
|
<p>
|
||||||
|
Il proprietario riceverà la notifica alle ore 9.00{" "}
|
||||||
|
{tooLate && "di domani"}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</CredenzaBody>
|
||||||
|
<CredenzaFooter>
|
||||||
|
<Button
|
||||||
|
aria-label="Contatta proprietario"
|
||||||
|
onClick={() =>
|
||||||
|
mutate({
|
||||||
|
annuncioId,
|
||||||
|
servizioId,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
variant="success"
|
||||||
|
>
|
||||||
|
{t.accetta}
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<CredenzaClose asChild>
|
||||||
|
<Button aria-label="Chiudi modal credenza" variant="outline">
|
||||||
|
{t.chiudi}
|
||||||
|
</Button>
|
||||||
|
</CredenzaClose>
|
||||||
|
</CredenzaFooter>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
function getNavigationUrl(lat: string, lon: string): string {
|
||||||
|
if (typeof window !== "undefined") {
|
||||||
|
const isIOS =
|
||||||
|
navigator.userAgent.toUpperCase().includes("MAC") ||
|
||||||
|
navigator.userAgent.toUpperCase().includes("IPAD") ||
|
||||||
|
navigator.userAgent.toUpperCase().includes("IPHONE") ||
|
||||||
|
navigator.userAgent.toUpperCase().includes("IOS") ||
|
||||||
|
navigator.userAgent.toUpperCase().includes("IPOD");
|
||||||
|
|
||||||
|
return `${isIOS ? "maps" : "https"}://www.google.com/maps/dir/?api=1&travelmode=driving&layer=traffic&destination=${lat},${lon}`;
|
||||||
|
}
|
||||||
|
return `https://www.google.com/maps/dir/?api=1&travelmode=driving&layer=traffic&destination=${lat},${lon}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PostUnlock = () => {
|
||||||
|
const { servizioId } = useServizio();
|
||||||
|
const { annuncioId } = useServizioAnnuncio();
|
||||||
|
const { data, isLoading } = api.annunci.getProprietarioData.useQuery({
|
||||||
|
annuncioId,
|
||||||
|
servizioId,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
// Memoize navigation URL
|
||||||
|
const navigationUrl = useMemo(() => {
|
||||||
|
if (!data?.propData || !data.propData.lat || !data.propData.lon)
|
||||||
|
return undefined;
|
||||||
|
return getNavigationUrl(data.propData.lat, data.propData.lon);
|
||||||
|
}, [data?.propData]);
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return (
|
||||||
|
<div className="flex justify-center">
|
||||||
|
<LoadingPage />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!data || !data.propData) {
|
||||||
|
return <p>{t.contatto.error}</p>;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<CredenzaBody className="max-h-[80vh] overflow-auto pb-5">
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<h3 className="font-semibold">{t.contatto.propietario}:</h3>
|
||||||
|
<p>
|
||||||
|
{t.contatto.nome}: {data.propData.locatore}
|
||||||
|
</p>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<a
|
||||||
|
className="flex items-center gap-2"
|
||||||
|
href={`tel:${data.propData.numero}`}
|
||||||
|
>
|
||||||
|
<Phone />:
|
||||||
|
<span className="text-blue-600 underline">
|
||||||
|
{data.propData.numero}
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
<Link
|
||||||
|
href={`https://wa.me/${data.propData.numero}`}
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
className="flex items-center gap-2"
|
||||||
|
size="sm"
|
||||||
|
variant="success"
|
||||||
|
>
|
||||||
|
<WhatsAppIcon2 className="size-4 fill-white" />
|
||||||
|
WhatsApp
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<h3 className="font-semibold">{t.contatto.immobile}:</h3>
|
||||||
|
<p>
|
||||||
|
{t.contatto.indirizzo}: {data.propData.indirizzo},{" "}
|
||||||
|
{data.propData.civico} {data.propData.comune} (
|
||||||
|
{data.propData.provincia})
|
||||||
|
</p>
|
||||||
|
<a
|
||||||
|
className="flex w-fit items-center gap-2 rounded-md border border-border px-3 py-2"
|
||||||
|
href={navigationUrl}
|
||||||
|
rel="noreferrer"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
<Navigation /> <span>{t.contatto.apri_nav}</span>
|
||||||
|
</a>
|
||||||
|
<br />
|
||||||
|
<p>
|
||||||
|
{t.contatto.sbloccato_il}:{" "}
|
||||||
|
{data.opened_at.toLocaleString("it", {
|
||||||
|
day: "2-digit",
|
||||||
|
hour: "2-digit",
|
||||||
|
minute: "2-digit",
|
||||||
|
month: "2-digit",
|
||||||
|
year: "numeric",
|
||||||
|
})}
|
||||||
|
</p>
|
||||||
|
<div className="flex items-center gap-2 rounded-md bg-red-500 p-2 text-white">
|
||||||
|
<TriangleAlert className="size-8" />
|
||||||
|
<div>
|
||||||
|
<p>{t.contatto.contatta}</p>
|
||||||
|
<p className="font-semibold">{t.contatto.orari}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CredenzaBody>
|
||||||
|
<CredenzaFooter>
|
||||||
|
<CredenzaClose asChild>
|
||||||
|
<Button aria-label="Chiudi modal credenza" variant="outline">
|
||||||
|
{t.chiudi}
|
||||||
|
</Button>
|
||||||
|
</CredenzaClose>
|
||||||
|
</CredenzaFooter>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -104,8 +104,12 @@ export const AnnunciSelezionati = ({
|
||||||
<DialogServizio
|
<DialogServizio
|
||||||
title="Annunci selezionati"
|
title="Annunci selezionati"
|
||||||
trigger={
|
trigger={
|
||||||
<div className="relative">
|
<div className="relative flex w-full sm:w-fit">
|
||||||
<Button className="text-lg" size="xl" variant="orange">
|
<Button
|
||||||
|
className="w-full text-lg sm:w-fit"
|
||||||
|
size="xl"
|
||||||
|
variant="orange"
|
||||||
|
>
|
||||||
Annunci selezionati
|
Annunci selezionati
|
||||||
</Button>
|
</Button>
|
||||||
{annunci.length > 0 && (
|
{annunci.length > 0 && (
|
||||||
|
|
@ -159,8 +163,8 @@ export const AnnunciCompatibili = () => {
|
||||||
<DialogServizio
|
<DialogServizio
|
||||||
title="Annunci compatibili"
|
title="Annunci compatibili"
|
||||||
trigger={
|
trigger={
|
||||||
<div className="relative">
|
<div className="relative flex w-full sm:w-fit">
|
||||||
<Button className="bg-purple-500 text-lg" size="xl">
|
<Button className="w-full bg-purple-500 text-lg sm:w-fit" size="xl">
|
||||||
Annunci compatibili
|
Annunci compatibili
|
||||||
</Button>
|
</Button>
|
||||||
{data && data.length > 0 && (
|
{data && data.length > 0 && (
|
||||||
|
|
|
||||||
|
|
@ -108,14 +108,7 @@ const Row = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CollapsibleContent className="mt-2 overflow-hidden transition-all duration-300 ease-in-out data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down">
|
<CollapsibleContent className="mt-2 overflow-hidden transition-all duration-300 ease-in-out data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down">
|
||||||
<ServizioProvider
|
|
||||||
isAdmin={isAdmin}
|
|
||||||
servizio={servizio}
|
|
||||||
servizioId={servizio.servizio_id}
|
|
||||||
userId={userId}
|
|
||||||
>
|
|
||||||
<ServizioContent />
|
<ServizioContent />
|
||||||
</ServizioProvider>
|
|
||||||
</CollapsibleContent>
|
</CollapsibleContent>
|
||||||
</Collapsible>
|
</Collapsible>
|
||||||
</ServizioProvider>
|
</ServizioProvider>
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,16 @@ import { Button } from "~/components/ui/button";
|
||||||
import { uploadHandler } from "~/hooks/storageClienSideHooks";
|
import { uploadHandler } from "~/hooks/storageClienSideHooks";
|
||||||
import { useTranslation } from "~/providers/I18nProvider";
|
import { useTranslation } from "~/providers/I18nProvider";
|
||||||
import type { UsersId } from "~/schemas/public/Users";
|
import type { UsersId } from "~/schemas/public/Users";
|
||||||
|
import type { UsersStorageUserStorageId } from "~/schemas/public/UsersStorage";
|
||||||
import { api } from "~/utils/api";
|
import { api } from "~/utils/api";
|
||||||
|
|
||||||
|
export type UploadCallback = (args: {
|
||||||
|
storageIds: string[];
|
||||||
|
userStorageIds: UsersStorageUserStorageId[];
|
||||||
|
}) => void;
|
||||||
|
|
||||||
type UploadModalProps = {
|
type UploadModalProps = {
|
||||||
cb_onUpload?: () => void;
|
cb_onUpload?: UploadCallback;
|
||||||
isAdmin?: boolean;
|
isAdmin?: boolean;
|
||||||
userId?: UsersId;
|
userId?: UsersId;
|
||||||
};
|
};
|
||||||
|
|
@ -69,7 +75,7 @@ export const UploadModal = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
type UploadComponentProps = {
|
type UploadComponentProps = {
|
||||||
cb_onUpload?: () => void;
|
cb_onUpload?: UploadCallback;
|
||||||
isAdmin?: boolean;
|
isAdmin?: boolean;
|
||||||
userId?: UsersId;
|
userId?: UsersId;
|
||||||
maxMB?: number;
|
maxMB?: number;
|
||||||
|
|
@ -90,7 +96,10 @@ export const UploadComponent = ({
|
||||||
const { mutateAsync: setUserStorage } =
|
const { mutateAsync: setUserStorage } =
|
||||||
api.storage.addUserStorageEntry.useMutation({
|
api.storage.addUserStorageEntry.useMutation({
|
||||||
onMutate: () => {
|
onMutate: () => {
|
||||||
toast(t.allegati.allegato_caricato, { icon: "📤" });
|
toast(t.allegati.allegato_caricato, {
|
||||||
|
icon: "📤",
|
||||||
|
toasterId: "uploading-toast",
|
||||||
|
});
|
||||||
},
|
},
|
||||||
onSettled: async () => {
|
onSettled: async () => {
|
||||||
await utils.storage.getAll.invalidate();
|
await utils.storage.getAll.invalidate();
|
||||||
|
|
@ -160,6 +169,8 @@ export const UploadComponent = ({
|
||||||
if (files.length === 0) {
|
if (files.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
let storageIds: string[] = [];
|
||||||
|
const userStorageIds: UsersStorageUserStorageId[] = [];
|
||||||
try {
|
try {
|
||||||
const from_admin = isAdmin ?? true;
|
const from_admin = isAdmin ?? true;
|
||||||
setIsUploading(true);
|
setIsUploading(true);
|
||||||
|
|
@ -168,14 +179,24 @@ export const UploadComponent = ({
|
||||||
files,
|
files,
|
||||||
from_admin,
|
from_admin,
|
||||||
});
|
});
|
||||||
|
if (!status) {
|
||||||
|
toast.error(t.allegati.errore_caricamento, {
|
||||||
|
icon: "❌",
|
||||||
|
toasterId: "uploading-toast",
|
||||||
|
});
|
||||||
|
setIsUploading(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
storageIds = attachments;
|
||||||
|
|
||||||
if (userId) {
|
if (userId) {
|
||||||
for (const storageId of attachments) {
|
for (const storageId of attachments) {
|
||||||
await setUserStorage({
|
const res = await setUserStorage({
|
||||||
storageId,
|
storageId,
|
||||||
userId,
|
userId,
|
||||||
from_admin,
|
from_admin,
|
||||||
});
|
});
|
||||||
|
userStorageIds.push(res.user_storage_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -193,16 +214,9 @@ export const UploadComponent = ({
|
||||||
}, randomDelay / 1); // Adjust interval based on random delay
|
}, randomDelay / 1); // Adjust interval based on random delay
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!status) {
|
|
||||||
toast.error(t.allegati.errore_caricamento, {
|
|
||||||
icon: "❌",
|
|
||||||
});
|
|
||||||
setIsUploading(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
toast.success(t.allegati.success_caricamento, {
|
toast.success(t.allegati.success_caricamento, {
|
||||||
icon: "✅",
|
icon: "✅",
|
||||||
|
toasterId: "uploading-toast",
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setIsUploading(false);
|
setIsUploading(false);
|
||||||
|
|
@ -211,11 +225,12 @@ export const UploadComponent = ({
|
||||||
error instanceof Error
|
error instanceof Error
|
||||||
? error.message
|
? error.message
|
||||||
: t.allegati.errore_sconosciuto,
|
: t.allegati.errore_sconosciuto,
|
||||||
|
{ icon: "❌", toasterId: "uploading-toast" },
|
||||||
);
|
);
|
||||||
} finally {
|
} finally {
|
||||||
setIsUploading(false);
|
setIsUploading(false);
|
||||||
setFiles([]);
|
setFiles([]);
|
||||||
cb_onUpload?.();
|
cb_onUpload?.({ storageIds, userStorageIds });
|
||||||
await utils.storage.getAll.invalidate();
|
await utils.storage.getAll.invalidate();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
import type { UsersId } from './Users';
|
import type { UsersId } from './Users';
|
||||||
import type { default as TipologiaPosizioneEnum } from './TipologiaPosizioneEnum';
|
import type { default as TipologiaPosizioneEnum } from './TipologiaPosizioneEnum';
|
||||||
|
import type { UsersStorageUserStorageId } from './UsersStorage';
|
||||||
import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
|
import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
|
||||||
|
|
||||||
/** Identifier type for public.servizio */
|
/** Identifier type for public.servizio */
|
||||||
|
|
@ -59,6 +60,12 @@ export default interface ServizioTable {
|
||||||
isOkSaldo: ColumnType<boolean, boolean | undefined, boolean>;
|
isOkSaldo: ColumnType<boolean, boolean | undefined, boolean>;
|
||||||
|
|
||||||
isOkConsulenza: ColumnType<boolean, boolean | undefined, boolean>;
|
isOkConsulenza: ColumnType<boolean, boolean | undefined, boolean>;
|
||||||
|
|
||||||
|
doc_personale_fronte_ref: ColumnType<UsersStorageUserStorageId | null, UsersStorageUserStorageId | null, UsersStorageUserStorageId | null>;
|
||||||
|
|
||||||
|
doc_personale_retro_ref: ColumnType<UsersStorageUserStorageId | null, UsersStorageUserStorageId | null, UsersStorageUserStorageId | null>;
|
||||||
|
|
||||||
|
doc_motivazione_ref: ColumnType<UsersStorageUserStorageId | null, UsersStorageUserStorageId | null, UsersStorageUserStorageId | null>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Servizio = Selectable<ServizioTable>;
|
export type Servizio = Selectable<ServizioTable>;
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,13 @@
|
||||||
import type { UsersId } from './Users';
|
import type { UsersId } from './Users';
|
||||||
import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
|
import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
|
||||||
|
|
||||||
|
/** Identifier type for public.users_storage */
|
||||||
|
export type UsersStorageUserStorageId = string & { __brand: 'public.users_storage' };
|
||||||
|
|
||||||
/** Represents the table public.users_storage */
|
/** Represents the table public.users_storage */
|
||||||
export default interface UsersStorageTable {
|
export default interface UsersStorageTable {
|
||||||
|
user_storage_id: ColumnType<UsersStorageUserStorageId, UsersStorageUserStorageId | undefined, UsersStorageUserStorageId>;
|
||||||
|
|
||||||
userId: ColumnType<UsersId, UsersId, UsersId>;
|
userId: ColumnType<UsersId, UsersId, UsersId>;
|
||||||
|
|
||||||
storageId: ColumnType<string, string, string>;
|
storageId: ColumnType<string, string, string>;
|
||||||
|
|
|
||||||
|
|
@ -627,6 +627,45 @@ export const getAllServizioAnnunci = async (userId: UsersId) => {
|
||||||
"servizio.isOkAcconto",
|
"servizio.isOkAcconto",
|
||||||
"servizio.isOkSaldo",
|
"servizio.isOkSaldo",
|
||||||
"servizio.isOkConsulenza",
|
"servizio.isOkConsulenza",
|
||||||
|
jsonObjectFrom(
|
||||||
|
eb
|
||||||
|
.selectFrom("users_storage")
|
||||||
|
.select([
|
||||||
|
"users_storage.storageId as storageId",
|
||||||
|
"servizio.doc_personale_fronte_ref as ref",
|
||||||
|
])
|
||||||
|
.whereRef(
|
||||||
|
"users_storage.user_storage_id",
|
||||||
|
"=",
|
||||||
|
"servizio.doc_personale_fronte_ref",
|
||||||
|
),
|
||||||
|
).as("doc_personale_fronte"),
|
||||||
|
jsonObjectFrom(
|
||||||
|
eb
|
||||||
|
.selectFrom("users_storage")
|
||||||
|
.select([
|
||||||
|
"users_storage.storageId as storageId",
|
||||||
|
"servizio.doc_personale_retro_ref as ref",
|
||||||
|
])
|
||||||
|
.whereRef(
|
||||||
|
"users_storage.user_storage_id",
|
||||||
|
"=",
|
||||||
|
"servizio.doc_personale_retro_ref",
|
||||||
|
),
|
||||||
|
).as("doc_personale_retro"),
|
||||||
|
jsonObjectFrom(
|
||||||
|
eb
|
||||||
|
.selectFrom("users_storage")
|
||||||
|
.select([
|
||||||
|
"users_storage.storageId as storageId",
|
||||||
|
"servizio.doc_motivazione_ref as ref",
|
||||||
|
])
|
||||||
|
.whereRef(
|
||||||
|
"users_storage.user_storage_id",
|
||||||
|
"=",
|
||||||
|
"servizio.doc_motivazione_ref",
|
||||||
|
),
|
||||||
|
).as("doc_motivazione"),
|
||||||
jsonArrayFrom(
|
jsonArrayFrom(
|
||||||
eb
|
eb
|
||||||
.selectFrom("servizio_annunci")
|
.selectFrom("servizio_annunci")
|
||||||
|
|
|
||||||
|
|
@ -114,8 +114,8 @@ export const addUserStorage = async (data: NewUsersStorage) => {
|
||||||
.insertInto("users_storage")
|
.insertInto("users_storage")
|
||||||
.values(data)
|
.values(data)
|
||||||
.onConflict((oc) => oc.columns(["userId", "storageId"]).doNothing())
|
.onConflict((oc) => oc.columns(["userId", "storageId"]).doNothing())
|
||||||
.returningAll()
|
.returning("user_storage_id")
|
||||||
.execute();
|
.executeTakeFirstOrThrow();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "INTERNAL_SERVER_ERROR",
|
code: "INTERNAL_SERVER_ERROR",
|
||||||
|
|
|
||||||
|
|
@ -18,29 +18,12 @@ services:
|
||||||
interval: 1s
|
interval: 1s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 10
|
retries: 10
|
||||||
|
|
||||||
# minio:
|
|
||||||
# image: minio/minio
|
|
||||||
# expose:
|
|
||||||
# - "9000"
|
|
||||||
# - "9001"
|
|
||||||
# volumes:
|
|
||||||
# - minio_storage:/data
|
|
||||||
# networks:
|
|
||||||
# - dokploy-network
|
|
||||||
# environment:
|
|
||||||
# MINIO_ROOT_USER: ${MINIO_ROOT_USER}
|
|
||||||
# MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
|
|
||||||
# command: server --console-address ":9001" /data
|
|
||||||
# healthcheck:
|
|
||||||
# test: [ "CMD", "curl", "-f", "http://minio:9000/minio/health/live" ]
|
|
||||||
# interval: 10s
|
|
||||||
# timeout: 10s
|
|
||||||
# retries: 5
|
|
||||||
storage:
|
storage:
|
||||||
image: "ghcr.io/marcopedone/go_fs:latest"
|
image: "ghcr.io/marcopedone/go_fs:latest"
|
||||||
ports:
|
expose:
|
||||||
- "8080:8080"
|
- "8080"
|
||||||
|
restart: unless-stopped
|
||||||
|
pull_policy: "always"
|
||||||
environment:
|
environment:
|
||||||
PORT: 8080
|
PORT: 8080
|
||||||
AUTH_TOKEN: ${STORAGE_TOKEN}
|
AUTH_TOKEN: ${STORAGE_TOKEN}
|
||||||
|
|
@ -106,10 +89,8 @@ services:
|
||||||
- images_volume:/app/images
|
- images_volume:/app/images
|
||||||
- storage_volume:/app/storage
|
- storage_volume:/app/storage
|
||||||
environment:
|
environment:
|
||||||
STORAGE_STRATEGY: "s3"
|
STORAGE_URL: http://storage:8080
|
||||||
MINIO_URL: minio:9000
|
STORAGE_TOKEN: ${STORAGE_TOKEN}
|
||||||
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
|
|
||||||
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
|
|
||||||
POSTGRES_USER: ${POSTGRES_USER}
|
POSTGRES_USER: ${POSTGRES_USER}
|
||||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||||
POSTGRES_DB: ${POSTGRES_DB}
|
POSTGRES_DB: ${POSTGRES_DB}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue