eslint migration biome

This commit is contained in:
Marco Pedone 2025-08-28 18:27:07 +02:00
parent 9185d8ddec
commit 3f82763168
348 changed files with 64918 additions and 67612 deletions

View file

@ -17,6 +17,4 @@ knip.json
check-env-vars.js
headers
.kanelrc.js
eslint.config.mjs
prettier.config.cjs
kyselyRules

View file

@ -13,9 +13,4 @@
}
],
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.fixAll.biome": "explicit",
"source.organizeImports.biome": "explicit"
}
}

View file

@ -44,7 +44,11 @@
"!*compose.yml",
"!.kanelrc.js",
"!TODO",
"!*.d.ts"
"!*.d.ts",
"!src/i18n/comuni.ts",
"!src/i18n/nazioni.ts",
"!src/i18n/provincie.ts",
"!src/styles/globals.css"
],
"ignoreUnknown": true
},
@ -54,6 +58,7 @@
},
"linter": {
"enabled": true,
"domains": {
"next": "recommended",
"react": "recommended"
@ -61,14 +66,29 @@
"rules": {
"recommended": true,
"a11y": {
"noNoninteractiveElementInteractions": "error"
"noNoninteractiveElementInteractions": "error",
"useSemanticElements": "off",
"noAutofocus": "off"
},
"suspicious": {
"noArrayIndexKey": "off"
"useIterableCallbackReturn": "off",
"noArrayIndexKey": "off",
"noUnknownAtRules": "off"
},
"complexity": {
"noUselessFragments": "off"
},
"correctness": {
"useExhaustiveDependencies": "off"
"useHookAtTopLevel": "off",
"useExhaustiveDependencies": "off",
"useParseIntRadix": "off"
},
"performance": {
"noImgElement": "off"
},
"security": {
"noDangerouslySetInnerHtml": "off"
}
}
},

View file

@ -2,13 +2,13 @@ import {
Body,
Container,
Head,
Hr,
Html,
Img,
Preview,
Section,
Text,
Tailwind,
Img,
Hr,
Text,
} from "@react-email/components";
import type { JSX } from "react";

View file

@ -20,7 +20,7 @@ const EmailContattoInteressato = ({
sesso,
}: EmailContattoInteressatoProps) => {
const sig = sesso
? sesso == "M"
? sesso === "M"
? "Il Sig."
: "La Sig.ra"
: "Il/La Sig./Sig.ra";
@ -37,7 +37,7 @@ const EmailContattoInteressato = ({
la contatterà {sig} {nome_cognome_utente} (tel: {telefono}),
cliente Arca abbonato tramite il nostro servizio online
Infoalloggi.it interessato a vedere il Suo immobile{" "}
{indirizzo ? "di " + indirizzo : ""}.
{indirizzo ? `di ${indirizzo}` : ""}.
</Text>
<Text className="text-base">
Per ulteriori informazioni e chiarimenti non esiti a contattarci

View file

@ -1,4 +1,4 @@
import { Heading, Row, Section, Text, Button } from "@react-email/components";
import { Button, Heading, Row, Section, Text } from "@react-email/components";
import Base from "./base";
export type PwResetLink_NewMail = {
mailType: "pwResetLink";

View file

@ -1,152 +0,0 @@
import react from "eslint-plugin-react";
import typescriptEslint from "@typescript-eslint/eslint-plugin";
import pluginQuery from "@tanstack/eslint-plugin-query";
import kyselyRules from "./kyselyRules/plugin.js";
import tsParser from "@typescript-eslint/parser";
import path from "node:path";
import { fileURLToPath } from "node:url";
import js from "@eslint/js";
import noRelativeImportPaths from "eslint-plugin-no-relative-import-paths";
import { FlatCompat } from "@eslint/eslintrc";
import jsxA11y from "eslint-plugin-jsx-a11y";
import eslintPluginBetterTailwindcss from "eslint-plugin-better-tailwindcss";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all,
});
export default [
...pluginQuery.configs["flat/recommended"],
{
ignores: [
"**/.next",
"**/out",
"**/public",
"**/node_modules/",
"**/check-env-vars.js",
"**/headers/",
"**/schemas/",
"**/kyselyRules/",
"prettier.config.cjs",
"postcss.config.cjs",
".kanelrc.js",
],
},
...compat.extends(
"eslint:recommended",
"plugin:react/recommended",
"plugin:@next/next/recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-type-checked",
"plugin:@typescript-eslint/stylistic-type-checked",
"plugin:jsx-a11y/recommended",
),
{
plugins: {
react,
"@typescript-eslint": typescriptEslint,
"better-tailwindcss": eslintPluginBetterTailwindcss,
"jsx-a11y": jsxA11y,
kyselyRules: kyselyRules,
//"no-relative-import-paths": noRelativeImportPaths,
},
languageOptions: {
parser: tsParser,
ecmaVersion: 5,
sourceType: "script",
parserOptions: {
project: true,
tsconfigRootDir: "./",
},
},
linterOptions: {
reportUnusedDisableDirectives: true,
},
settings: {
react: {
version: "detect",
},
"import/resolver": {
typescript: {
alwaysTryTypes: true,
project: "./tsconfig.json",
},
},
"better-tailwindcss": {
entryPoint: "src/styles/globals.css",
},
},
rules: {
"react/react-in-jsx-scope": "off",
"react-hooks/exhaustive-deps": "off",
"react/prop-types": "off",
"@typescript-eslint/ban-types": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/array-type": "off",
"@typescript-eslint/no-redundant-type-constituents": "warn",
"@typescript-eslint/consistent-type-definitions": "off",
"@typescript-eslint/prefer-optional-chain": "off",
"@typescript-eslint/prefer-nullish-coalescing": "off",
"@typescript-eslint/no-empty-interface": "off",
"@typescript-eslint/unbound-method": "off",
"@typescript-eslint/consistent-type-imports": [
"warn",
{
prefer: "type-imports",
fixStyle: "inline-type-imports",
},
],
"@typescript-eslint/no-unused-vars": [
"warn",
{
argsIgnorePattern: "^_",
},
],
"@typescript-eslint/require-await": "off",
"@typescript-eslint/switch-exhaustiveness-check": "warn",
"@typescript-eslint/no-misused-promises": [
"error",
{
checksVoidReturn: {
attributes: false,
},
},
],
"@next/next/no-img-element": "warn",
"kyselyRules/enforce-select": "error",
"kyselyRules/enforce-where": "error",
"kyselyRules/enforce-null": "error",
...eslintPluginBetterTailwindcss.configs["recommended-warn"]?.rules,
...eslintPluginBetterTailwindcss.configs["recommended-error"]?.rules,
"better-tailwindcss/enforce-consistent-line-wrapping": "off",
"better-tailwindcss/enforce-consistent-class-order": "off",
},
},
{
//ignores: ["**/emails/**/*.tsx", "next.config.js"],
files: ["src/**/*.tsx", "src/**/*.ts"],
plugins: {
"no-relative-import-paths": noRelativeImportPaths,
},
rules: {
"no-relative-import-paths/no-relative-import-paths": [
"warn",
{ rootDir: "src", prefix: "~" },
],
},
},
];

View file

@ -1,14 +1,8 @@
{
"$schema": "https://unpkg.com/knip@5/schema.json",
"project": [
"src/**",
"**",
"!src/schemas/public/*.ts",
"!emails/**"
],
"project": ["src/**", "**", "!src/schemas/public/*.ts", "!emails/**"],
"ignore": [
".kanelrc.js",
".eslintrc.json",
"TypeHelpers.type.ts",
"src/utils/api.ts",
"src/server/api/trpc.ts",
@ -23,26 +17,15 @@
"src/utils/get-media-url.ts",
"src/utils/utils.ts"
],
"ignoreBinaries": [
"stripe"
],
"ignoreBinaries": ["stripe"],
"ignoreDependencies": [
"kysely-plugin-serialize",
"sharp",
"uuid",
"@react-email/components",
"@eslint/compat",
"@next/eslint-plugin-next",
"@prettier/sync",
"@types/eslint",
"@types/uuid",
"eslint-config-next",
"eslint-import-resolver-typescript",
"eslint-plugin-import",
"eslint-plugin-react-hooks",
"kanel-kysely",
"npm-run-all",
"typescript-eslint",
"@react-email/preview-server",
"@tailwindcss/forms",
"@tailwindcss/typography",

View file

@ -34,9 +34,7 @@ const nextConfig = {
typescript: {
ignoreBuildErrors: true,
},
eslint: {
ignoreDuringBuilds: true,
},
devIndicators: false,
rewrites: async () => {
return [
@ -46,11 +44,11 @@ const nextConfig = {
},
{
source: "/go-api/images/get/:slug*",
destination: env.BACKENDSERVER_URL + "/images/get/:slug*",
destination: `${env.BACKENDSERVER_URL}/images/get/:slug*`,
},
{
source: "/go-api/storage/get/:slug*",
destination: env.BACKENDSERVER_URL + "/storage/get/:slug*",
destination: `${env.BACKENDSERVER_URL}/storage/get/:slug*`,
has: [
{ type: "cookie", key: "access_token" },
{
@ -63,7 +61,7 @@ const nextConfig = {
},
{
source: "/go-api/storage/upload:slug*",
destination: env.BACKENDSERVER_URL + "/storage/upload:slug*",
destination: `${env.BACKENDSERVER_URL}/storage/upload:slug*`,
has: [
{ type: "cookie", key: "access_token" },
{

File diff suppressed because it is too large Load diff

View file

@ -101,17 +101,9 @@
},
"devDependencies": {
"@biomejs/biome": "2.2.2",
"@eslint/compat": "^1.3.1",
"@eslint/eslintrc": "^3.3.0",
"@eslint/js": "^9.32.0",
"@hookform/devtools": "^4.4.0",
"@next/eslint-plugin-next": "^15.4.5",
"@prettier/sync": "^0.6.1",
"@react-email/preview-server": "^4.2.8",
"@tanstack/eslint-plugin-query": "^5.83.1",
"@total-typescript/ts-reset": "^0.6.1",
"@types/eslint": "^9.6.1",
"@types/eslint-plugin-jsx-a11y": "^6.10.0",
"@types/js-cookie": "^3.0.6",
"@types/leaflet": "^1.9.20",
"@types/node": "^24.2.0",
@ -122,27 +114,13 @@
"@types/react-dom": "^19.1.7",
"@types/react-is": "^19.0.0",
"@types/uuid": "^10.0.0",
"@typescript-eslint/eslint-plugin": "^8.39.0",
"@typescript-eslint/parser": "^8.39.0",
"cross-env": "^10.0.0",
"eslint": "^9.32.0",
"eslint-config-next": "^15.4.5",
"eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-better-tailwindcss": "^3.7.4",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-no-relative-import-paths": "^1.6.1",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^5.2.0",
"jiti": "^2.5.1",
"kanel": "^3.14.2",
"kanel-kysely": "^0.7.1",
"knip": "^5.62.0",
"npm-run-all": "^4.1.5",
"prettier": "^3.6.2",
"prettier-plugin-classnames": "^0.8.2",
"prettier-plugin-tailwindcss": "^0.6.14",
"typescript": "^5.9.2",
"typescript-eslint": "^8.39.0"
"typescript": "^5.9.2"
},
"ct3aMetadata": {
"initVersion": "7.9.0"

View file

@ -1,4 +1,4 @@
/* eslint-env node */
const config = {
plugins: {

View file

@ -1,10 +0,0 @@
/* eslint-env node */
/** @type {import("prettier").Config & import('prettier-plugin-tailwindcss').PluginOptions} */
const config = {
printWidth: 80,
plugins: ["prettier-plugin-classnames", "prettier-plugin-tailwindcss"],
customAttributes: ["className"],
customFunctions: ["classNames"],
};
module.exports = config;

View file

@ -1,6 +1,6 @@
import { Suspense } from "react";
import Annunci from "~/_app/ui/annunci";
import { getDataFromDB } from "~/_app/lib/annunci";
import AnnunciList from "~/_app/ui/annunci";
import { LoadingPage } from "~/components/loading";
export default function TestAppPage() {
@ -14,7 +14,7 @@ export default function TestAppPage() {
<h2 className="mb-2 text-lg font-semibold">Data from Database:</h2>
<Suspense fallback={<LoadingPage />}>
<Annunci annunci={annunci} />
<AnnunciList annunci={annunci} />
</Suspense>
</div>
</div>

View file

@ -6,7 +6,7 @@ type AnnunciProps = {
annunci: Promise<Pick<Annunci, "codice">[]>;
};
export default function Annunci({ annunci }: AnnunciProps) {
export default function AnnunciList({ annunci }: AnnunciProps) {
const allAnnunci = use(annunci);
return (

View file

@ -23,6 +23,7 @@ import {
House,
Info,
LayoutDashboard,
type LucideProps,
Mail,
MessageSquareText,
MessagesSquare,
@ -42,20 +43,19 @@ import {
User,
Users,
Wifi,
type LucideProps,
} from "lucide-react";
import type {
ComponentPropsWithoutRef,
ForwardRefExoticComponent,
RefAttributes,
} from "react";
import toast from "react-hot-toast";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "~/components/ui/tooltip";
import toast from "react-hot-toast";
import type {
ComponentPropsWithoutRef,
ForwardRefExoticComponent,
RefAttributes,
} from "react";
const iconOptions = [
"heater",
@ -315,6 +315,7 @@ export const ShieldExclamationIcon = ({
fill="currentColor"
className={className}
>
<title>Shield</title>
<path
fillRule="evenodd"
d="M11.484 2.17a.75.75 0 0 1 1.032 0 11.209 11.209 0 0 0 7.877 3.08.75.75 0 0 1 .722.515 12.74 12.74 0 0 1 .635 3.985c0 5.942-4.064 10.933-9.563 12.348a.749.749 0 0 1-.374 0C6.314 20.683 2.25 15.692 2.25 9.75c0-1.39.223-2.73.635-3.985a.75.75 0 0 1 .722-.516l.143.001c2.996 0 5.718-1.17 7.734-3.08ZM12 8.25a.75.75 0 0 1 .75.75v3.75a.75.75 0 0 1-1.5 0V9a.75.75 0 0 1 .75-.75ZM12 15a.75.75 0 0 0-.75.75v.008c0 .414.336.75.75.75h.008a.75.75 0 0 0 .75-.75v-.008a.75.75 0 0 0-.75-.75H12Z"
@ -334,6 +335,7 @@ export const QuestionMarkCircleIcon = ({
fill="currentColor"
className={className}
>
<title>QuestionMark</title>
<path
fillRule="evenodd"
d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12Zm11.378-3.917c-.89-.777-2.366-.777-3.255 0a.75.75 0 0 1-.988-1.129c1.454-1.272 3.776-1.272 5.23 0 1.513 1.324 1.513 3.518 0 4.842a3.75 3.75 0 0 1-.837.552c-.676.328-1.028.774-1.028 1.152v.75a.75.75 0 0 1-1.5 0v-.75c0-1.279 1.06-2.107 1.875-2.502.182-.088.351-.199.503-.331.83-.727.83-1.857 0-2.584ZM12 18a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Z"
@ -351,6 +353,7 @@ export const HomeIcon = ({ className }: { className?: string }) => (
stroke="currentColor"
className={className}
>
<title>Home</title>
<path
strokeLinecap="round"
strokeLinejoin="round"
@ -365,6 +368,7 @@ const CheckCircleIcon = ({ className }: { className?: string }) => (
fill="currentColor"
className={className}
>
<title>CheckCircle</title>
<path
fillRule="evenodd"
d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12Zm13.36-1.814a.75.75 0 1 0-1.22-.872l-3.236 4.53L9.53 12.22a.75.75 0 0 0-1.06 1.06l2.25 2.25a.75.75 0 0 0 1.14-.094l3.75-5.25Z"

View file

@ -1,5 +1,5 @@
import Image from "next/image";
import { type ComponentProps } from "react";
import type { ComponentProps } from "react";
const fallbackImage = "/fallback-image.png";
export const ImageFlbk = (props: ComponentProps<typeof Image>) => {

View file

@ -1,14 +1,15 @@
import { cn } from "~/lib/utils";
import { ExternalLink } from "lucide-react";
import Link from "next/link";
import type { ReactNode } from "react";
import {
HybridTooltip,
HybridTooltipContent,
HybridTooltipTrigger,
} from "~/components/custom_ui/HybridTooltip";
import { TooltipProvider } from "~/components/ui/tooltip";
import { IconMatrix, type IconType } from "~/components/IconComponents";
import Link from "next/link";
import { ExternalLink } from "lucide-react";
import type { ReactNode } from "react";
import { TooltipProvider } from "~/components/ui/tooltip";
import { cn } from "~/lib/utils";
/*
<TouchProvider>
<div className="relative">

View file

@ -1,11 +1,3 @@
import { useContext, type ReactNode } from "react";
import { BannerFactory } from "~/components/banners";
import { Footer, MiniFooter } from "~/components/footer";
import { SiteHeader } from "~/components/navbar/site-header";
import { useTranslation } from "~/providers/I18nProvider";
import { UserViewContext, UserViewProvider } from "~/lib/userViewContext";
import Head from "next/head";
import Link from "next/link";
import {
ExternalLink,
Mail,
@ -16,21 +8,29 @@ import {
Tickets,
UserCog,
} from "lucide-react";
import Head from "next/head";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { useRouter } from "next/router";
import { type ReactNode, useContext } from "react";
import toast from "react-hot-toast";
import { Sidebar } from "~/components/area-riservata/sidebar";
import { BannerFactory } from "~/components/banners";
import { Footer, MiniFooter } from "~/components/footer";
import { LoadingPage } from "~/components/loading";
import { SiteHeader } from "~/components/navbar/site-header";
import { WhatsAppIcon } from "~/components/svgs";
import { Button } from "~/components/ui/button";
import { Separator } from "~/components/ui/separator";
import { usePathname } from "next/navigation";
import { api } from "~/utils/api";
import { Sidebar } from "~/components/area-riservata/sidebar";
import type { UsersId } from "~/schemas/public/Users";
import toast from "react-hot-toast";
import { useRouter } from "next/router";
import { UserViewContext, UserViewProvider } from "~/lib/userViewContext";
import { useTranslation } from "~/providers/I18nProvider";
import {
useSession,
EnforcedSessionContext,
useSession,
} from "~/providers/SessionProvider";
import { WhatsAppIcon } from "~/components/svgs";
import { LoadingPage } from "~/components/loading";
import type { UsersId } from "~/schemas/public/Users";
import type { ValidSession } from "~/server/api/trpc";
import { api } from "~/utils/api";
interface Props {
children: ReactNode;
@ -80,7 +80,7 @@ export const AreaRiservataLayout = ({
<main className="flex h-full flex-1 overflow-auto">
<div className="flex h-auto w-full flex-col md:flex-row">
<LoadingPage />;
<LoadingPage />
</div>
</main>
{!noFooter && <MiniFooter />}
@ -94,7 +94,7 @@ export const AreaRiservataLayout = ({
<main className="flex h-full flex-1 overflow-auto">
<div className="flex h-auto w-full flex-col md:flex-row">
<LoadingPage />;
<LoadingPage />
</div>
</main>
{!noFooter && <MiniFooter />}

View file

@ -1,8 +1,8 @@
"use client";
import dynamic from "next/dynamic";
import { Button } from "~/components/ui/button";
import { MapIcon } from "lucide-react";
import { useTranslation } from "~/providers/I18nProvider";
import dynamic from "next/dynamic";
import { useState } from "react";
import { Button } from "~/components/ui/button";
import {
Dialog,
DialogContent,
@ -11,9 +11,9 @@ import {
DialogTitle,
DialogTrigger,
} from "~/components/ui/dialog";
import { useState } from "react";
import { useTranslation } from "~/providers/I18nProvider";
const Map = dynamic(() => import("~/components/map/Map"), {
const MapComp = dynamic(() => import("~/components/map/Map"), {
ssr: false,
});
@ -41,7 +41,7 @@ export const MappaDialogFullscreen = ({
<div className="size-full">
{lat && long && (
<>
<Map
<MapComp
posix={{
pos: {
lat: Number.parseFloat(lat),

View file

@ -1,25 +1,25 @@
"use client";
import { api } from "~/utils/api";
import { useState, type FormEvent } from "react";
import {
Elements,
PaymentElement,
useElements,
useStripe,
} from "@stripe/react-stripe-js";
import type { Stripe } from "@stripe/stripe-js";
import { ArrowRight, ExternalLink } from "lucide-react";
import Link from "next/link";
import { type FormEvent, useState } from "react";
import LoadingButton from "~/components/custom_ui/loading-button";
import { LoadingPage } from "~/components/loading";
import { Status500 } from "~/components/status-page";
import LoadingButton from "~/components/custom_ui/loading-button";
import { useTranslation } from "~/providers/I18nProvider";
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
import type { Stripe } from "@stripe/stripe-js";
import { formatCurrency } from "~/lib/utils";
import { Button } from "~/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
import { env } from "~/env.mjs";
import { formatCurrency } from "~/lib/utils";
import { useTranslation } from "~/providers/I18nProvider";
import type { PaymentsId } from "~/schemas/public/Payments";
import type { PrezziarioIdprezziario } from "~/schemas/public/Prezziario";
import { ArrowRight, ExternalLink } from "lucide-react";
import { env } from "~/env.mjs";
import Link from "next/link";
import { api } from "~/utils/api";
type AcquistoProcessingProps = {
paymentId: PaymentsId;
@ -69,8 +69,7 @@ export const AcquistoProcessing = ({
) : isPending ? (
<LoadingPage />
) : (
stripeIntent &&
stripeIntent.clientSecret && (
stripeIntent?.clientSecret && (
<>
<Elements
options={{

View file

@ -1,14 +1,14 @@
"use client";
import { format } from "date-fns";
import { it } from "date-fns/locale";
import Image from "next/image";
import { useRef } from "react";
import { useReactToPrint } from "react-to-print";
import { Button } from "~/components/ui/button";
import { Card } from "~/components/ui/card";
import Image from "next/image";
import { format } from "date-fns";
import { useReactToPrint } from "react-to-print";
import { it } from "date-fns/locale";
import { formatCurrency } from "~/lib/utils";
import { useRef } from "react";
import { PaymentMethodToString, type PaymentType } from "~/i18n/stripe";
import { formatCurrency } from "~/lib/utils";
export function ReceiptGenerator({ data }: { data: PurchaseData }) {
const contentRef = useRef<HTMLDivElement>(null);

View file

@ -1,8 +1,8 @@
import { useEffect, useRef, useState } from "react";
import { LoadingPage } from "~/components/loading";
import { cn } from "~/lib/utils";
import type { TempTokensToken } from "~/schemas/public/TempTokens";
import { api } from "~/utils/api";
import { LoadingPage } from "~/components/loading";
import { useEffect, useRef, useState } from "react";
export const AllegatoIframe = ({
className,
@ -15,7 +15,7 @@ export const AllegatoIframe = ({
const { mutateAsync: getToken } = api.storage.getStorageToken.useMutation();
const [token, setToken] = useState<TempTokensToken | null>(null);
const handleIframeLoad = () => {
if (if_ref.current && if_ref.current.contentWindow) {
if (if_ref.current?.contentWindow) {
const img = if_ref.current.contentWindow.document.querySelector("img");
if (img) {
img.style.width = "100%";
@ -43,6 +43,7 @@ export const AllegatoIframe = ({
className,
)}
>
{/** biome-ignore lint/a11y/noNoninteractiveElementInteractions: <need interaction> */}
<iframe
title="Allegato"
ref={if_ref}

View file

@ -1,5 +1,5 @@
import { getTitoloTranslation } from "~/lib/annuncio_details";
import { CardAnnuncio } from "~/components/annuncio_card";
import { getTitoloTranslation } from "~/lib/annuncio_details";
import { useTranslation } from "~/providers/I18nProvider";
import type { AnnuncioRicerca } from "~/server/controllers/annunci.controller";

View file

@ -1,23 +1,23 @@
import dynamic from "next/dynamic";
import type { AnnuncioRicercaWPosition } from "~/server/controllers/annunci.controller";
import { api } from "~/utils/api";
import { LoadingPage } from "~/components/loading";
import { Status500 } from "~/components/status-page";
import { useTranslation } from "~/providers/I18nProvider";
import { AnimatePresence, motion } from "framer-motion";
import dynamic from "next/dynamic";
import Image from "next/image";
import { formatCurrency } from "~/lib/utils";
import { handleConsegna } from "~/lib/annuncio_details";
import {
type Dispatch,
Fragment,
memo,
useState,
type Dispatch,
type SetStateAction,
useState,
} from "react";
import { LoadingPage } from "~/components/loading";
import { Status500 } from "~/components/status-page";
import { handleConsegna } from "~/lib/annuncio_details";
import { formatCurrency } from "~/lib/utils";
import { useTranslation } from "~/providers/I18nProvider";
import { useRicerca } from "~/providers/RicercaProvider";
import type { AnnuncioRicercaWPosition } from "~/server/controllers/annunci.controller";
import { api } from "~/utils/api";
const Map = dynamic(() => import("~/components/map/Map"), {
const MapComp = dynamic(() => import("~/components/map/Map"), {
ssr: false,
});
@ -78,7 +78,7 @@ const MapDisplay = memo(
.filter((a) => a !== undefined);
return (
<Map
<MapComp
isGroup
groupData={posizioni}
posix={{ pos: { lat: 45.764718, lng: 11.73067 } }}
@ -118,7 +118,7 @@ const SelectedComp = memo(
key={selected.id}
>
<div className="flex gap-2">
{selected.url_immagini && selected.url_immagini[0] ? (
{selected.url_immagini?.[0] ? (
<Image
src={selected.url_immagini[0]}
width={500}

View file

@ -1,8 +1,11 @@
"use client";
import { DialogTrigger } from "@radix-ui/react-dialog";
import { getCookie, setCookie } from "cookies-next/client";
import { add } from "date-fns";
import { ArrowRight, CircleHelp } from "lucide-react";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import { Button } from "~/components/ui/button";
import {
Dialog,
DialogContent,
@ -10,10 +13,6 @@ import {
DialogHeader,
DialogTitle,
} from "~/components/ui/dialog";
import { Button } from "~/components/ui/button";
import { useRouter } from "next/router";
import { ArrowRight, CircleHelp } from "lucide-react";
import { DialogTrigger } from "@radix-ui/react-dialog";
import { useTranslation } from "~/providers/I18nProvider";
const COOKIE_KEY = "tipologia_tutorial_shown";
@ -28,7 +27,7 @@ export const CTA_TipologiaModal = () => {
expires: add(new Date(), { days: 30 }), // Set cookie to expire in 30 days
});
if (v !== null) {
window.location.assign("/annunci?tipo=" + v);
window.location.assign(`/annunci?tipo=${v}`);
}
setOpen(false);
};
@ -36,7 +35,7 @@ export const CTA_TipologiaModal = () => {
const [open, setOpen] = useState(false);
useEffect(() => {
if (path == "/annunci" && !hasCookie) {
if (path === "/annunci" && !hasCookie) {
const timer = setTimeout(() => {
setOpen(true);
}, 1000); // 1 second delay

View file

@ -1,16 +1,16 @@
import { ArrowRight, BadgePlus, LogIn } from "lucide-react";
import { cn } from "~/lib/utils";
import { Button, buttonVariants } from "~/components/ui/button";
import { useRouter } from "next/router";
import { api } from "~/utils/api";
import Link from "next/link";
import { useRouter } from "next/router";
import toast from "react-hot-toast";
import { ContattoAnnuncio } from "~/components/annuncio-interactions/contatto_modal";
import LoadingButton from "~/components/custom_ui/loading-button";
import { Button, buttonVariants } from "~/components/ui/button";
import { cn } from "~/lib/utils";
import { useAnnuncio } from "~/providers/AnnuncioProvider";
import type { SessionContextType } from "~/providers/SessionProvider";
import LoadingButton from "~/components/custom_ui/loading-button";
import type { UsersId } from "~/schemas/public/Users";
import type { AnnunciId } from "~/schemas/public/Annunci";
import { ContattoAnnuncio } from "~/components/annuncio-interactions/contatto_modal";
import toast from "react-hot-toast";
import type { UsersId } from "~/schemas/public/Users";
import { api } from "~/utils/api";
export const AnnuncioInteractions = ({
session,
@ -79,9 +79,9 @@ const ServizioInteraction = ({
if (isLoading) return <LoadingButton loading className="w-full" />;
if (
servizio == undefined ||
servizio.status == "invalid" ||
servizio.status == "not_found"
servizio === undefined ||
servizio.status === "invalid" ||
servizio.status === "not_found"
) {
return (
<div>
@ -90,7 +90,7 @@ const ServizioInteraction = ({
);
}
if (servizio.status == "already_saved") {
if (servizio.status === "already_saved") {
return (
<div className="flex w-full flex-col gap-2">
<div className="w-full text-center font-semibold text-green-500">

View file

@ -1,4 +1,4 @@
import { useAnnuncio } from "~/providers/AnnuncioProvider";
import { MessageCircleQuestion } from "lucide-react";
import {
Credenza,
CredenzaBody,
@ -8,9 +8,9 @@ import {
CredenzaTitle,
CredenzaTrigger,
} from "~/components/custom_ui/credenza";
import { FormContattoAnnucio } from "~/forms/FormContattoAnnuncio";
import { Button } from "~/components/ui/button";
import { MessageCircleQuestion } from "lucide-react";
import { FormContattoAnnucio } from "~/forms/FormContattoAnnuncio";
import { useAnnuncio } from "~/providers/AnnuncioProvider";
export const ContattoAnnuncio = () => {
const { codice } = useAnnuncio();

View file

@ -1,4 +1,8 @@
import { BedDouble, CalendarClock, Maximize2, Ruler } from "lucide-react";
import Image from "next/image";
import Link from "next/link";
import { useState } from "react";
import { ImageFlbk } from "~/components/ImageWithFallback";
import {
Carousel,
CarouselContent,
@ -6,11 +10,6 @@ import {
CarouselNext,
CarouselPrevious,
} from "~/components/ui/carousel";
import { cn, formatCurrency } from "~/lib/utils";
import { BedDouble, CalendarClock, Maximize2, Ruler } from "lucide-react";
import Image from "next/image";
import { useTranslation } from "~/providers/I18nProvider";
import { useState } from "react";
import {
Dialog,
DialogContent,
@ -19,7 +18,8 @@ import {
DialogTitle,
} from "~/components/ui/dialog";
import { camereTesti, handleConsegna } from "~/lib/annuncio_details";
import { ImageFlbk } from "~/components/ImageWithFallback";
import { cn, formatCurrency } from "~/lib/utils";
import { useTranslation } from "~/providers/I18nProvider";
type CardAnnuncioProps = {
id: number;
@ -68,7 +68,7 @@ export const CardAnnuncio = ({
className="block p-2" //duration-700 ease-in-out animate-in fade-in
>
<div className="group relative rounded-xl text-clip">
{stato == "Trattativa" && (
{stato === "Trattativa" && (
<div>
<div className="absolute z-20 h-56 w-full">
<div className="absolute bottom-0 w-full touch-none bg-violet-500 text-center text-lg text-white select-none">
@ -80,8 +80,7 @@ export const CardAnnuncio = ({
<Carousel opts={{ loop: true }}>
<CarouselContent>
{immagini &&
immagini.map((img, idx) => (
{immagini?.map((img, idx) => (
<CarouselItem key={`${img}-${idx}`}>
<ImageFlbk
alt={t.card.alt_immagine}
@ -223,8 +222,7 @@ export const CarouselAnnuncio = ({
<div className="relative">
<Carousel opts={{ loop: true, align: "start" }}>
<CarouselContent>
{immagini &&
immagini.map((img, idx) => (
{immagini?.map((img, idx) => (
<CarouselItem
key={`${img}-${idx}-cF`}
className={cn(
@ -275,8 +273,7 @@ export const CarouselAnnuncio = ({
</DialogHeader>
<Carousel opts={{ loop: true, startIndex: idxModal }}>
<CarouselContent>
{immagini &&
immagini.map((img, idx) => (
{immagini?.map((img, idx) => (
<CarouselItem key={`${img}-${idx}-cD`}>
<Image
alt={`carousel-img-${idx}`}

View file

@ -1,16 +1,4 @@
import toast from "react-hot-toast";
import type {
Storageindex,
StorageindexId,
} from "~/schemas/public/Storageindex";
import type { UsersId } from "~/schemas/public/Users";
import { api } from "~/utils/api";
import { LoadingPage } from "~/components/loading";
import { Status500 } from "~/components/status-page";
import { Separator } from "~/components/ui/separator";
import Link from "next/link";
import { cn } from "~/lib/utils";
import { Button } from "~/components/ui/button";
import { format } from "date-fns";
import {
Download,
File,
@ -26,9 +14,13 @@ import {
Trash2,
TriangleAlert,
} from "lucide-react";
import { useState, type FormEvent } from "react";
import { useTranslation } from "~/providers/I18nProvider";
import Link from "next/link";
import { type FormEvent, useState } from "react";
import toast from "react-hot-toast";
import Input from "~/components/custom_ui/input";
import { LoadingPage } from "~/components/loading";
import { Status500 } from "~/components/status-page";
import { Button } from "~/components/ui/button";
import {
Dialog,
DialogContent,
@ -36,15 +28,23 @@ import {
DialogHeader,
DialogTitle,
} from "~/components/ui/dialog";
import { handleDownload } from "~/hooks/filesHooks";
import { UploadModal } from "~/components/upload_modal";
import { format } from "date-fns";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "~/components/ui/dropdown-menu";
import { Separator } from "~/components/ui/separator";
import { UploadModal } from "~/components/upload_modal";
import { handleDownload } from "~/hooks/filesHooks";
import { cn } from "~/lib/utils";
import { useTranslation } from "~/providers/I18nProvider";
import type {
Storageindex,
StorageindexId,
} from "~/schemas/public/Storageindex";
import type { UsersId } from "~/schemas/public/Users";
import { api } from "~/utils/api";
export const AllegatiComp = ({
userId,

View file

@ -1,5 +1,4 @@
import type { UsersId } from "~/schemas/public/Users";
import { api } from "~/utils/api";
import { useState } from "react";
import {
Accordion,
AccordionContent,
@ -7,7 +6,8 @@ import {
AccordionTrigger,
} from "~/components/ui/accordion";
import { useMediaQuery } from "~/hooks/use-media-query";
import { useState } from "react";
import type { UsersId } from "~/schemas/public/Users";
import { api } from "~/utils/api";
export const EmailAccordion = ({ userId }: { userId: UsersId }) => {
const { data } = api.comunicazioni.getEmails.useQuery({

View file

@ -1,9 +1,8 @@
import { api } from "~/utils/api";
import { LoadingPage } from "~/components/loading";
import type { UsersId } from "~/schemas/public/Users";
import { AccordionComp } from "~/components/accordionComp";
import { useTranslation } from "~/providers/I18nProvider";
import { LoadingPage } from "~/components/loading";
import { TabRicerca } from "~/components/tables/ricerca-table";
import TimeserieBarChart from "~/components/timeserieBarChart";
import TimeserieBarChartStacked from "~/components/timeserieBarChartStacked";
import {
Card,
CardContent,
@ -11,8 +10,9 @@ import {
CardHeader,
CardTitle,
} from "~/components/ui/card";
import TimeserieBarChartStacked from "~/components/timeserieBarChartStacked";
import { TabRicerca } from "~/components/tables/ricerca-table";
import { useTranslation } from "~/providers/I18nProvider";
import type { UsersId } from "~/schemas/public/Users";
import { api } from "~/utils/api";
export const AdminDashboard = () => {
const { data: stats, isLoading } = api.stats.adminDashStats.useQuery();

View file

@ -1,22 +1,19 @@
import { CircleCheck, CircleSlash, ReceiptText, Trash2 } from "lucide-react";
import Link from "next/link";
import toast from "react-hot-toast";
import { Confirm } from "~/components/confirm";
import {
Credenza,
CredenzaBody,
CredenzaClose,
CredenzaContent,
CredenzaDescription,
CredenzaFooter,
CredenzaHeader,
CredenzaTitle,
CredenzaDescription,
CredenzaBody,
CredenzaFooter,
CredenzaClose,
} from "~/components/custom_ui/credenza";
import { PaymentsTable } from "~/components/tables/payments-table";
import type { OrdiniOrdineId } from "~/schemas/public/Ordini";
import { api } from "~/utils/api";
import { Confirm } from "~/components/confirm";
import { Button } from "~/components/ui/button";
import { CircleCheck, CircleSlash, ReceiptText, Trash2 } from "lucide-react";
import toast from "react-hot-toast";
import type { UsersId } from "~/schemas/public/Users";
import { cn } from "~/lib/utils";
import {
DropdownMenu,
DropdownMenuContent,
@ -26,9 +23,12 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "~/components/ui/dropdown-menu";
import PaymentStatusEnum from "~/schemas/public/PaymentStatusEnum";
import Link from "next/link";
import { cn } from "~/lib/utils";
import OrderTypeEnum from "~/schemas/public/OrderTypeEnum";
import type { OrdiniOrdineId } from "~/schemas/public/Ordini";
import PaymentStatusEnum from "~/schemas/public/PaymentStatusEnum";
import type { UsersId } from "~/schemas/public/Users";
import { api } from "~/utils/api";
export const OrdiniModal = ({
isAdmin,

View file

@ -1,12 +1,12 @@
import { usePathname } from "next/navigation";
import { ARMinimizableLinks } from "~/components/navbar/mobile-nav";
import { cn } from "~/lib/utils";
import { Button } from "~/components/ui/button";
import { Expand, Minimize2 } from "lucide-react";
import { motion } from "framer-motion";
import { getCookie, setCookie } from "cookies-next/client";
import { useEffect, useState } from "react";
import { add } from "date-fns";
import { motion } from "framer-motion";
import { Expand, Minimize2 } from "lucide-react";
import { usePathname } from "next/navigation";
import { useEffect, useState } from "react";
import { ARMinimizableLinks } from "~/components/navbar/mobile-nav";
import { Button } from "~/components/ui/button";
import { cn } from "~/lib/utils";
export const Sidebar = ({
isAdmin,

View file

@ -1,11 +1,10 @@
import Link from "next/link";
import { useState } from "react";
import Cookies from "js-cookie";
import { useEffect, type MouseEvent } from "react";
import { X } from "lucide-react";
import type { Banners } from "~/schemas/public/Banners";
import { cn } from "~/lib/utils";
import Link from "next/link";
import { type MouseEvent, useEffect, useState } from "react";
import { IconMatrix, type IconType } from "~/components/IconComponents";
import { cn } from "~/lib/utils";
import type { Banners } from "~/schemas/public/Banners";
export const BannerFactory = (bannerData: Banners) => {
const NEW_BANNER_KEY = `bannercookie_${bannerData.idbanner}`;
@ -35,7 +34,6 @@ export const BannerFactory = (bannerData: Banners) => {
accentColor = "bg-indigo-800";
closeHoverColor = "hover:bg-indigo-500";
break;
case null:
default:
bgColor = "bg-indigo-600";
accentColor = "bg-indigo-800";
@ -98,6 +96,7 @@ export const BannerFactory = (bannerData: Banners) => {
</div>
{bannerData.is_unskippable === false && (
<button
type="button"
className={cn(
"rounded-lg p-2 ring-offset-2 duration-150 hover:bg-indigo-500 focus:ring",
closeHoverColor,

View file

@ -1,27 +1,27 @@
"use client";
import { differenceInDays, differenceInMinutes, format } from "date-fns";
import { Paperclip } from "lucide-react";
import Link from "next/link";
import { ExtIcon } from "~/components/area-riservata/allegati";
import {
Credenza,
CredenzaTrigger,
CredenzaContent,
CredenzaBody,
CredenzaHeader,
CredenzaDescription,
CredenzaTitle,
CredenzaFooter,
CredenzaClose,
CredenzaContent,
CredenzaDescription,
CredenzaFooter,
CredenzaHeader,
CredenzaTitle,
CredenzaTrigger,
} from "~/components/custom_ui/credenza";
import { Button, buttonVariants } from "~/components/ui/button";
import { api } from "~/utils/api";
import { LoadingPage } from "~/components/loading";
import Link from "next/link";
import { Button, buttonVariants } from "~/components/ui/button";
import { UploadComponent } from "~/components/upload_modal";
import { cn } from "~/lib/utils";
import { ExtIcon } from "~/components/area-riservata/allegati";
import { useTranslation } from "~/providers/I18nProvider";
import type { Session } from "~/server/api/trpc";
import type { ChatUserInfo } from "~/server/services/chat.service";
import { UploadComponent } from "~/components/upload_modal";
import { useTranslation } from "~/providers/I18nProvider";
import { differenceInDays, differenceInMinutes, format } from "date-fns";
import { api } from "~/utils/api";
type ChatAttachmentsProps = {
userData: Session;
@ -76,7 +76,7 @@ export const ChatAttachments = ({
<LoadingPage />
) : (
<>
{!attachments || attachments.length == 0 ? (
{!attachments || attachments.length === 0 ? (
<div className="flex h-full items-center justify-center">
<p className="text-center text-lg font-semibold text-gray-500">
{t.allegati.nessun_allegato}
@ -111,7 +111,7 @@ export const ChatAttachments = ({
</Link>
<span
className="text-muted-foreground text-xs"
key={new Date().getTime()}
key={new Date().toString()}
>
{TimeSince(file.created_at)}
</span>

View file

@ -2,35 +2,35 @@
import { SendHorizontal, SmilePlusIcon, ThumbsUp } from "lucide-react";
import {
type ChangeEvent,
useCallback,
useEffect,
useRef,
useState,
type ChangeEvent,
} from "react";
import { Button } from "~/components/ui/button";
import {
AutosizeTextarea,
type AutosizeTextAreaRef,
} from "~/components/custom_ui/autoResizeTextArea";
import { api } from "~/utils/api";
import { ChatAttachments } from "~/components/chat/chat-attachments";
import { useMediaQuery } from "~/hooks/use-media-query";
import { useThrottledIsTypingMutation } from "~/hooks/chatHooks";
import type { Session } from "~/server/api/trpc";
import type { ChatsChatid } from "~/schemas/public/Chats";
import type { ChatUserInfo } from "~/server/services/chat.service";
import {
type AutosizeTextAreaRef,
AutosizeTextarea,
} from "~/components/custom_ui/autoResizeTextArea";
import {
EmojiPicker,
EmojiPickerContent,
EmojiPickerSearch,
} from "~/components/custom_ui/emoji-picker";
import { Button } from "~/components/ui/button";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover";
import {
EmojiPickerContent,
EmojiPickerSearch,
EmojiPicker,
} from "~/components/custom_ui/emoji-picker";
import { useThrottledIsTypingMutation } from "~/hooks/chatHooks";
import { useMediaQuery } from "~/hooks/use-media-query";
import { useTranslation } from "~/providers/I18nProvider";
import type { ChatsChatid } from "~/schemas/public/Chats";
import type { Session } from "~/server/api/trpc";
import type { ChatUserInfo } from "~/server/services/chat.service";
import { api } from "~/utils/api";
type ChatBottombarProps = {
chatId: ChatsChatid;
@ -143,7 +143,7 @@ export default function ChatBottombar({
}}
>
<EmojiPickerSearch
placeholder={locale == "en" ? "Search..." : "Cerca..."}
placeholder={locale === "en" ? "Search..." : "Cerca..."}
/>
<EmojiPickerContent />
</EmojiPicker>
@ -157,10 +157,10 @@ export default function ChatBottombar({
variant="ghost"
className="shrink-0"
onClick={
message.length != 0 ? () => handleSend() : () => handleThumbsUp()
message.length !== 0 ? () => handleSend() : () => handleThumbsUp()
}
>
{message.length != 0 ? (
{message.length !== 0 ? (
<SendHorizontal size={20} className="text-muted-foreground" />
) : (
<ThumbsUp size={20} className="text-muted-foreground" />

View file

@ -1,10 +1,9 @@
import * as React from "react";
import { cva, type VariantProps } from "class-variance-authority";
import MessageLoading from "~/components/chat/message-loading";
import { cn } from "~/lib/utils";
import { Button, type ButtonProps } from "~/components/ui/button";
import { Check, CheckCheck } from "lucide-react";
import * as React from "react";
import MessageLoading from "~/components/chat/message-loading";
import { Button, type ButtonProps } from "~/components/ui/button";
import { cn } from "~/lib/utils";
// ChatBubble
const chatBubbleVariant = cva(
@ -64,8 +63,6 @@ export const ChatBubbleReadStatus = ({ isread }: ChatBubbleReadStatusProps) => {
} else {
return <Check className="text-muted-foreground mt-2 size-4" />;
}
return null;
};
// ChatBubbleMessage

View file

@ -1,27 +1,15 @@
"use client";
import { cn } from "~/lib/utils";
import { AnimatePresence, motion } from "framer-motion";
import { Pencil, Trash2 } from "lucide-react";
import {
type FormEvent,
useCallback,
useEffect,
useRef,
useState,
type FormEvent,
} from "react";
import { api } from "~/utils/api";
import toast from "react-hot-toast";
import Input from "~/components/custom_ui/input";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "~/components/ui/dialog";
import { Button } from "~/components/ui/button";
import { Pencil, Trash2 } from "lucide-react";
import type { MessagesMessageid } from "~/schemas/public/Messages";
import { AnimatePresence, motion } from "framer-motion";
import {
ChatBubble,
ChatBubbleAction,
@ -31,6 +19,8 @@ import {
ChatBubbleTimestamp,
} from "~/components/chat/chat-bubble";
import { ChatMessageList } from "~/components/chat/chat-message-list";
import Input from "~/components/custom_ui/input";
import LoadingButton from "~/components/custom_ui/loading-button";
import {
AlertDialog,
AlertDialogAction,
@ -41,15 +31,25 @@ import {
AlertDialogHeader,
AlertDialogTitle,
} from "~/components/ui/alert-dialog";
import { useTranslation } from "~/providers/I18nProvider";
import type { ChatMessage } from "~/server/services/messages.service";
import type { UsersId } from "~/schemas/public/Users";
import type { WhoIsTyping } from "~/server/sse";
import type { Session } from "~/server/api/trpc";
import type { ChatsChatid } from "~/schemas/public/Chats";
import type { LiveChat } from "~/hooks/chatHooks";
import LoadingButton from "~/components/custom_ui/loading-button";
import { Button } from "~/components/ui/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "~/components/ui/dialog";
import { getUserColor, UserAvatar } from "~/components/user_avatar";
import type { LiveChat } from "~/hooks/chatHooks";
import { cn } from "~/lib/utils";
import { useTranslation } from "~/providers/I18nProvider";
import type { ChatsChatid } from "~/schemas/public/Chats";
import type { MessagesMessageid } from "~/schemas/public/Messages";
import type { UsersId } from "~/schemas/public/Users";
import type { Session } from "~/server/api/trpc";
import type { ChatMessage } from "~/server/services/messages.service";
import type { WhoIsTyping } from "~/server/sse";
import { api } from "~/utils/api";
type ChatListProps = {
chatId: ChatsChatid;
@ -162,13 +162,14 @@ export const ChatList = ({
const isNextSameSender =
index + 1 < messages.length &&
messages[index + 1]?.sender == message.sender;
messages[index + 1]?.sender === message.sender;
const isPreviousSameSender =
index - 1 >= 0 && messages[index - 1]?.sender == message.sender;
index - 1 >= 0 && messages[index - 1]?.sender === message.sender;
const isPrevSameDay =
index - 1 >= 0 &&
// biome-ignore lint/style/noNonNullAssertion: <non lo so>
new Date(messages[index - 1]!.time).toDateString() ===
new Date(message.time).toDateString();
@ -229,7 +230,7 @@ export const ChatList = ({
>
{message.message}
<div className="flex items-center gap-2">
{userData.id == message.sender && (
{userData.id === message.sender && (
<ChatBubbleReadStatus isread={message.isread} />
)}
{message.time && (
@ -315,7 +316,7 @@ const Typers = ({
return (
<motion.div
key={"typers" + messageLenght + index}
key={`typers${messageLenght}${index}`}
layout
initial={{ opacity: 0, scale: 1, y: 50, x: 0 }}
animate={{ opacity: 1, scale: 1, y: 0, x: 0 }}

View file

@ -1,32 +1,10 @@
import { Search, SquarePen } from "lucide-react";
import { cn } from "~/lib/utils";
import { Button, buttonVariants } from "~/components/ui/button";
import { useMediaQuery } from "~/hooks/use-media-query";
import Link from "next/link";
import { useRouter } from "next/router";
import { useCallback, useState } from "react";
import Input from "~/components/custom_ui/input";
import {
CommandDialog,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from "~/components/ui/command";
import { api } from "~/utils/api";
import { useRouter } from "next/router";
import type { ChatsChatid } from "~/schemas/public/Chats";
import {
ContextMenu,
ContextMenuContent,
ContextMenuItem,
ContextMenuSeparator,
ContextMenuSub,
ContextMenuSubContent,
ContextMenuSubTrigger,
ContextMenuTrigger,
} from "~/components/ui/context-menu";
import Link from "next/link";
import { Etichetta, EtichetteModal } from "~/components/etichette";
import { LoadingPage } from "~/components/loading";
import {
AlertDialog,
AlertDialogAction,
@ -37,11 +15,32 @@ import {
AlertDialogHeader,
AlertDialogTitle,
} from "~/components/ui/alert-dialog";
import { Etichetta, EtichetteModal } from "~/components/etichette";
import type { NonNullableUser } from "~/server/controllers/user.controller";
import { LoadingPage } from "~/components/loading";
import { Button, buttonVariants } from "~/components/ui/button";
import {
CommandDialog,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from "~/components/ui/command";
import {
ContextMenu,
ContextMenuContent,
ContextMenuItem,
ContextMenuSeparator,
ContextMenuSub,
ContextMenuSubContent,
ContextMenuSubTrigger,
ContextMenuTrigger,
} from "~/components/ui/context-menu";
import { UserAvatar } from "~/components/user_avatar";
import { useMediaQuery } from "~/hooks/use-media-query";
import { cn } from "~/lib/utils";
import type { ChatsChatid } from "~/schemas/public/Chats";
import type { ActiveChatsType } from "~/server/controllers/chat.controller";
import type { NonNullableUser } from "~/server/controllers/user.controller";
import { api } from "~/utils/api";
type LastMessage = {
message: string | null;
@ -385,6 +384,7 @@ const ChatSidebarContextMenu = ({
<ContextMenuSubContent className="w-48">
<ContextMenuItem asChild>
<button
type="button"
aria-label="Edit Chat Labels"
onClick={() => {
setSelectedChat(chatid);

View file

@ -7,43 +7,43 @@ import {
User,
UserCog,
} from "lucide-react";
import Link from "next/link";
import { cn } from "~/lib/utils";
import { Button, buttonVariants } from "~/components/ui/button";
import Image from "next/image";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover";
import Link from "next/link";
import { useRouter } from "next/router";
import { useCallback } from "react";
import toast from "react-hot-toast";
import { EtichetteDisplayer } from "~/components/etichette";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
AlertDialogCancel,
AlertDialogAction,
} from "~/components/ui/alert-dialog";
import { api } from "~/utils/api";
import { useRouter } from "next/router";
import toast from "react-hot-toast";
import { Button, buttonVariants } from "~/components/ui/button";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover";
import { Separator } from "~/components/ui/separator";
import { EtichetteDisplayer } from "~/components/etichette";
import type { Session } from "~/server/api/trpc";
import type { ChatUserInfo } from "~/server/services/chat.service";
import type { ChatsChatid } from "~/schemas/public/Chats";
import type { OnlineStatus } from "~/server/sse";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "~/components/ui/tooltip";
import { useCallback } from "react";
import { UserAvatar } from "~/components/user_avatar";
import { cn } from "~/lib/utils";
import type { ChatsChatid } from "~/schemas/public/Chats";
import type { Session } from "~/server/api/trpc";
import type { ChatUserInfo } from "~/server/services/chat.service";
import type { OnlineStatus } from "~/server/sse";
import { api } from "~/utils/api";
type ChatTopbarProps = {
chatId: ChatsChatid;

View file

@ -1,13 +1,13 @@
"use client";
import type { ChatsChatid } from "~/schemas/public/Chats";
import { memo } from "react";
import ChatBottombar from "~/components/chat/chat-bottombar";
import { ChatList } from "~/components/chat/chat-list";
import ChatTopbar from "~/components/chat/chat-topbar";
import { useLiveChat } from "~/hooks/chatHooks";
import { api } from "~/utils/api";
import type { ChatsChatid } from "~/schemas/public/Chats";
import type { Session } from "~/server/api/trpc";
import { memo } from "react";
import { api } from "~/utils/api";
const Chat = memo(
({ chatId, userData }: { chatId: ChatsChatid; userData: Session }) => {

View file

@ -8,6 +8,7 @@ export default function MessageLoading() {
xmlns="http://www.w3.org/2000/svg"
className="text-foreground"
>
<title>Loading</title>
<circle cx="4" cy="12" r="2" fill="currentColor">
<animate
id="spinner_qFRN"

View file

@ -1,14 +1,14 @@
"use client";
import { useRouter } from "next/router";
import { CircleOff } from "lucide-react";
import Link from "next/link";
import { api } from "~/utils/api";
import { useRouter } from "next/router";
import { useEffect, useRef, useState } from "react";
import Input from "~/components/custom_ui/input";
import { cn } from "~/lib/utils";
import { StaggeredFade } from "~/components/custom_ui/staggered-fade";
import { useTranslation } from "~/providers/I18nProvider";
import { useClickOutside } from "~/hooks/useClickOutside";
import { CircleOff } from "lucide-react";
import { cn } from "~/lib/utils";
import { useTranslation } from "~/providers/I18nProvider";
import { api } from "~/utils/api";
export const CodiceBox = ({
className,
@ -62,7 +62,7 @@ const AutocompleteSearchBox = ({
useClickOutside([wrapperRef, listRef], () => setOpen(false));
useEffect(() => {
if (searchValue.trim() == "" || searchValue.length == 0) {
if (searchValue.trim() === "" || searchValue.length === 0) {
setResults(options);
} else {
setResults(
@ -100,7 +100,7 @@ const AutocompleteSearchBox = ({
className,
)}
/>
<MovingText hidden={isFocused || searchValue != ""} />
<MovingText hidden={isFocused || searchValue !== ""} />
</div>
{open && (
<div
@ -116,6 +116,7 @@ const AutocompleteSearchBox = ({
navigationEnter &&
"[&>li:first-child>a]:bg-neutral-100 [&>li:first-child>a]:underline [&>li:first-child>a]:underline-offset-2",
)}
// biome-ignore lint/a11y/noNoninteractiveElementToInteractiveRole: <need list>
role="listbox"
>
{loading ? (
@ -160,6 +161,7 @@ const MovingText = ({ hidden }: { hidden: boolean }) => {
const { t } = useTranslation();
const [randomFrase, setRandomFrase] = useState<string>(
// biome-ignore lint/style/noNonNullAssertion: <exists>
t.code_search_frases[0]!,
);
useEffect(() => {
@ -167,6 +169,7 @@ const MovingText = ({ hidden }: { hidden: boolean }) => {
const randomIndex = Math.floor(
Math.random() * t.code_search_frases.length,
);
// biome-ignore lint/style/noNonNullAssertion: <exists>
setRandomFrase(t.code_search_frases[randomIndex]!);
}, 5000);

View file

@ -1,15 +1,15 @@
import { forwardRef, useMemo, useState } from "react";
import { HexColorPicker } from "react-colorful";
import { cn } from "~/lib/utils";
import { useForwardedRef } from "~/lib/use_fowarded_ref";
import type { ButtonProps } from "~/components/ui/button";
import { Button } from "~/components/ui/button";
import { Input } from "~/components/ui/input";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover";
import { Input } from "~/components/ui/input";
import { useForwardedRef } from "~/lib/use_fowarded_ref";
import { cn } from "~/lib/utils";
interface ColorPickerProps {
value: string;

View file

@ -54,7 +54,7 @@ export const ComeFunziona = () => {
src={feature.image}
width={400}
height={200}
alt={"img" + idx}
alt={`img${idx}`}
/>
</div>
<div className="flex basis-1/2 flex-col">

View file

@ -1,17 +1,17 @@
import { cn } from "~/lib/utils";
import type { ReactNode } from "react";
import {
AlertDialog,
AlertDialogTrigger,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogCancel,
AlertDialogAction,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "~/components/ui/alert-dialog";
import { buttonVariants } from "~/components/ui/button";
import type { ReactNode } from "react";
import { cn } from "~/lib/utils";
export const Confirm = ({
children,
title,
@ -47,7 +47,7 @@ export const Confirm = ({
<AlertDialogDescription>{description}</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel onClick={() => onCancel && onCancel()}>
<AlertDialogCancel onClick={() => onCancel?.()}>
{cancelText || "Annulla"}
</AlertDialogCancel>
<AlertDialogAction

View file

@ -1,31 +1,31 @@
"use client";
import {
type PropsWithChildren,
createContext,
useContext,
useEffect,
useState,
} from "react";
import {
Tooltip,
TooltipTrigger,
TooltipContent,
} from "~/components/ui/tooltip";
import {
Popover,
PopoverTrigger,
PopoverContent,
} from "~/components/ui/popover";
import type {
TooltipContentProps,
TooltipProps,
TooltipTriggerProps,
} from "@radix-ui/react-tooltip";
import type {
PopoverContentProps,
PopoverProps,
PopoverTriggerProps,
} from "@radix-ui/react-popover";
import type {
TooltipContentProps,
TooltipProps,
TooltipTriggerProps,
} from "@radix-ui/react-tooltip";
import {
createContext,
type PropsWithChildren,
useContext,
useEffect,
useState,
} from "react";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "~/components/ui/tooltip";
const TouchContext = createContext<boolean | undefined>(undefined);
const useTouch = () => useContext(TouchContext);

View file

@ -1,12 +1,12 @@
import { useAnimate, type AnimationSequence } from "framer-motion";
import { Button } from "~/components/ui/button";
import { IconMatrix, type IconType } from "~/components/IconComponents";
import { cn } from "~/lib/utils";
import { type AnimationSequence, useAnimate } from "framer-motion";
import {
type ComponentPropsWithoutRef,
forwardRef,
useImperativeHandle,
type ComponentPropsWithoutRef,
} from "react";
import { IconMatrix, type IconType } from "~/components/IconComponents";
import { Button } from "~/components/ui/button";
import { cn } from "~/lib/utils";
const randomNumberBetween = (min: number, max: number) => {
return Math.floor(Math.random() * (max - min + 1) + min);
@ -111,7 +111,6 @@ export const AnimatedButton = forwardRef<
<IconMatrix
type={sparklesIcon}
className={cn(
// eslint-disable-next-line better-tailwindcss/no-unregistered-classes
`absolute top-1/2 left-1/2 opacity-0 sparkle-${index}`,
sparklesClassName,
)}

View file

@ -1,12 +1,13 @@
"use client";
import { useEffect } from "react";
import {
type MotionValue,
motion,
useSpring,
useTransform,
} from "framer-motion";
import { useEffect } from "react";
//DOC: https://www.cult-ui.com/docs/components/animated-number
interface AnimatedNumberProps {

View file

@ -1,13 +1,13 @@
import { cn } from "~/lib/utils";
import {
forwardRef,
type Ref,
type TextareaHTMLAttributes,
useEffect,
useImperativeHandle,
useRef,
useState,
type Ref,
type TextareaHTMLAttributes,
} from "react";
import { cn } from "~/lib/utils";
interface UseAutosizeTextAreaProps {
textAreaRef: HTMLTextAreaElement | null;
@ -84,6 +84,7 @@ export const AutosizeTextarea = forwardRef<
});
useImperativeHandle(ref, () => ({
// biome-ignore lint/style/noNonNullAssertion: <it exists>
textArea: textAreaRef.current!,
focus: () => textAreaRef.current?.focus(),
maxHeight,

View file

@ -1,6 +1,7 @@
"use client";
import { useMediaQuery } from "~/hooks/use-media-query";
import { createContext, type ReactNode, useContext } from "react";
import type { Drawer as DrawerPrimitive } from "vaul";
import {
Dialog,
DialogClose,
@ -22,9 +23,8 @@ import {
DrawerTitle,
DrawerTrigger,
} from "~/components/ui/drawer";
import { type Drawer as DrawerPrimitive } from "vaul";
import { useMediaQuery } from "~/hooks/use-media-query";
import { cn } from "~/lib/utils";
import { createContext, useContext, type ReactNode } from "react";
interface BaseProps {
children: ReactNode;

View file

@ -1,18 +1,26 @@
import {
type ColumnDef,
useReactTable,
getCoreRowModel,
flexRender,
getSortedRowModel,
type VisibilityState,
type ColumnFiltersState,
getFilteredRowModel,
type SortingState,
getPaginationRowModel,
type ColumnSort,
flexRender,
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
type RowSelectionState,
type SortingState,
type Table as TableType,
useReactTable,
type VisibilityState,
} from "@tanstack/react-table";
import { useVirtualizer } from "@tanstack/react-virtual";
import { useEffect, useRef, useState } from "react";
import { DataTablePagination } from "~/components/custom_ui/dataTable-pagination";
import {
DataTableToolbar,
type PinnedFiltro,
type SearchFiltro,
} from "~/components/custom_ui/dataTable-toolbar";
import {
Table,
TableBody,
@ -21,15 +29,7 @@ import {
TableHeader,
TableRow,
} from "~/components/ui/table";
import { DataTablePagination } from "~/components/custom_ui/dataTable-pagination";
import {
DataTableToolbar,
type SearchFiltro,
type PinnedFiltro,
} from "~/components/custom_ui/dataTable-toolbar";
import { useVirtualizer } from "@tanstack/react-virtual";
import { cn } from "~/lib/utils";
import { useEffect, useRef, useState } from "react";
interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[];
@ -150,6 +150,7 @@ export function DataTable<TData, TValue>({
<TableBody className={tabClassName}>
{virtualizer.getVirtualItems().length ? (
virtualizer.getVirtualItems().map((virtualRow, index) => {
// biome-ignore lint/style/noNonNullAssertion: <always exists>
const row = rows[virtualRow.index]!;
return (
<TableRow

View file

@ -1,13 +1,8 @@
import type { Column } from "@tanstack/react-table";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover";
import { Button } from "~/components/ui/button";
import { CheckIcon, CirclePlus } from "lucide-react";
import { Separator } from "~/components/ui/separator";
import type { ComponentType } from "react";
import { Badge } from "~/components/ui/badge";
import { Button } from "~/components/ui/button";
import {
Command,
CommandEmpty,
@ -17,8 +12,13 @@ import {
CommandList,
CommandSeparator,
} from "~/components/ui/command";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover";
import { Separator } from "~/components/ui/separator";
import { cn } from "~/lib/utils";
import { type ComponentType } from "react";
interface DataTableFacetedFilterProps<TData, TValue> {
column?: Column<TData, TValue>;

View file

@ -1,4 +1,6 @@
import type { Table } from "@tanstack/react-table";
import { Filter } from "lucide-react";
import { Button } from "~/components/ui/button";
import {
DropdownMenu,
DropdownMenuCheckboxItem,
@ -7,8 +9,7 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "~/components/ui/dropdown-menu";
import { Button } from "~/components/ui/button";
import { Filter } from "lucide-react";
interface DataTableViewOptionsProps<TData> {
table: Table<TData>;
columns_titles: Record<string, string>;

View file

@ -1,5 +1,12 @@
import type { Column } from "@tanstack/react-table";
import { cn } from "~/lib/utils";
import {
ArrowDownIcon,
ArrowUpIcon,
ChevronsUpDown,
EyeOff,
} from "lucide-react";
import type { HTMLAttributes } from "react";
import { Button } from "~/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
@ -7,14 +14,7 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "~/components/ui/dropdown-menu";
import { Button } from "~/components/ui/button";
import {
ArrowDownIcon,
ArrowUpIcon,
ChevronsUpDown,
EyeOff,
} from "lucide-react";
import { type HTMLAttributes } from "react";
import { cn } from "~/lib/utils";
interface DataTableColumnHeaderProps<TData, TValue>
extends HTMLAttributes<HTMLDivElement> {

View file

@ -1,4 +1,11 @@
import type { Table } from "@tanstack/react-table";
import {
ChevronFirst,
ChevronLast,
ChevronLeftIcon,
ChevronRightIcon,
} from "lucide-react";
import { Button } from "~/components/ui/button";
import {
Select,
SelectContent,
@ -6,13 +13,7 @@ import {
SelectTrigger,
SelectValue,
} from "~/components/ui/select";
import { Button } from "~/components/ui/button";
import {
ChevronFirst,
ChevronLast,
ChevronLeftIcon,
ChevronRightIcon,
} from "lucide-react";
interface DataTablePaginationProps<TData> {
table: Table<TData>;
hasSelectRow?: boolean;

View file

@ -1,10 +1,10 @@
import type { Table } from "@tanstack/react-table";
import Input from "~/components/custom_ui/input";
import { DataTableViewOptions } from "~/components/custom_ui/dataTable-ViewToggle";
import { Button } from "~/components/ui/button";
import { DataTableFacetedFilter } from "~/components/custom_ui/dataTable-FacetedFilter";
import { RotateCcw } from "lucide-react";
import type { ComponentType } from "react";
import { DataTableFacetedFilter } from "~/components/custom_ui/dataTable-FacetedFilter";
import { DataTableViewOptions } from "~/components/custom_ui/dataTable-ViewToggle";
import Input from "~/components/custom_ui/input";
import { Button } from "~/components/ui/button";
export type PinnedFiltro = {
title: string;
@ -59,8 +59,7 @@ export function DataTableToolbar<TData>(props: {
className="mt-0 h-8 w-[150px]"
/>
))}
{pinnedColumns &&
pinnedColumns.map(
{pinnedColumns?.map(
(column) =>
table.getColumn(column.columnName) && (
<DataTableFacetedFilter

View file

@ -11,7 +11,7 @@ import {
// useSkinTone,
} from "frimousse";
import { LoaderIcon, SearchIcon } from "lucide-react";
import * as React from "react";
import type * as React from "react";
// import { Button } from "~/components/ui/button";
// import {

View file

@ -1,6 +1,5 @@
"use client";
import { cn } from "~/lib/utils";
import { Slot } from "@radix-ui/react-slot";
import {
FileArchiveIcon,
@ -12,8 +11,15 @@ import {
FileVideoIcon,
} from "lucide-react";
import {
type ChangeEvent,
type ComponentPropsWithoutRef,
createContext,
type DragEvent,
forwardRef,
type KeyboardEvent,
type MouseEvent,
type ReactNode,
type RefObject,
useCallback,
useContext,
useEffect,
@ -22,14 +28,8 @@ import {
useMemo,
useRef,
useSyncExternalStore,
type ChangeEvent,
type ComponentPropsWithoutRef,
type DragEvent,
type KeyboardEvent,
type MouseEvent,
type ReactNode,
type RefObject,
} from "react";
import { cn } from "~/lib/utils";
const ROOT_NAME = "FileUpload";
const DROPZONE_NAME = "FileUploadDropzone";
@ -340,15 +340,14 @@ const FileUploadRoot = forwardRef<HTMLDivElement, FileUploadRootProps>(
value,
defaultValue,
onValueChange,
/* eslint-disable @typescript-eslint/no-unused-vars */
onAccept,
onFileAccept,
onFileReject,
onFileValidate,
onUpload,
//onAccept,
//onFileAccept,
//onFileReject,
//onFileValidate,
//onUpload,
accept,
maxFiles,
maxSize,
//maxFiles,
//maxSize,
dir: dirProp,
label,
name,
@ -361,7 +360,6 @@ const FileUploadRoot = forwardRef<HTMLDivElement, FileUploadRootProps>(
className,
...rootProps
} = props;
/* eslint-enable @typescript-eslint/no-unused-vars */
const inputId = useId();
const dropzoneId = useId();
@ -1042,7 +1040,7 @@ const FileUploadItemPreview = forwardRef<
if (isImage) {
return (
// eslint-disable-next-line @next/next/no-img-element
// biome-ignore lint/a11y/noNoninteractiveElementInteractions: <intended>
<img
src={URL.createObjectURL(file)}
alt={file.name}
@ -1186,6 +1184,7 @@ const FileUploadItemProgress = forwardRef<
fill="none"
stroke="currentColor"
>
<title>Progress</title>
<circle
className="text-primary/20"
strokeWidth="2"

View file

@ -1,6 +1,6 @@
import * as React from "react";
import type * as LabelPrimitive from "@radix-ui/react-label";
import { Slot } from "@radix-ui/react-slot";
import * as React from "react";
import {
Controller,
type ControllerProps,
@ -9,9 +9,8 @@ import {
FormProvider,
useFormContext,
} from "react-hook-form";
import { cn } from "src/lib/utils";
import { Label } from "src/components/ui/label";
import { cn } from "src/lib/utils";
import { env } from "~/env.mjs";
const Form = FormProvider;

View file

@ -1,6 +1,6 @@
import {
forwardRef,
type ComponentPropsWithoutRef,
forwardRef,
type ReactNode,
} from "react";
import Input from "~/components/custom_ui/input";
@ -15,14 +15,14 @@ const InputWIcon = forwardRef<HTMLInputElement, InputWIconProps>(
return (
<div className="relative">
<Input
className={cn("peer", iconPosition == "start" ? "ps-9" : "pe-9")}
className={cn("peer", iconPosition === "start" ? "ps-9" : "pe-9")}
{...props}
ref={ref}
/>
<div
className={cn(
"pointer-events-none absolute inset-y-0 flex items-center justify-center text-muted-foreground/80 peer-disabled:opacity-50",
iconPosition == "start" ? "start-0 ps-3" : "end-0 pe-3",
iconPosition === "start" ? "start-0 ps-3" : "end-0 pe-3",
)}
>
{children}

View file

@ -1,5 +1,6 @@
import { type ReactNode } from "react";
import type { ReactNode } from "react";
import { cn } from "~/lib/utils";
const DualInputLayout = (props: {
children1: ReactNode;
children2: ReactNode;

View file

@ -1,9 +1,9 @@
import { LoaderCircle } from "lucide-react";
import {
Button,
buttonVariants,
type ButtonProps,
buttonVariants,
} from "~/components/ui/button";
import { LoaderCircle } from "lucide-react";
import { cn } from "~/lib/utils";
const LoadingButton = ({

View file

@ -1,7 +1,18 @@
"use client";
import { CheckIcon, ChevronsUpDownIcon, XIcon } from "lucide-react";
import { cn } from "~/lib/utils";
import {
type ComponentPropsWithoutRef,
createContext,
type ReactNode,
useCallback,
useContext,
useEffect,
useLayoutEffect,
useRef,
useState,
} from "react";
import { Badge } from "~/components/ui/badge";
import { Button } from "~/components/ui/button";
import {
Command,
@ -17,18 +28,7 @@ import {
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover";
import {
createContext,
useCallback,
useContext,
useEffect,
useLayoutEffect,
useRef,
useState,
type ComponentPropsWithoutRef,
type ReactNode,
} from "react";
import { Badge } from "~/components/ui/badge";
import { cn } from "~/lib/utils";
type MultiSelectContextType = {
open: boolean;
@ -273,8 +273,13 @@ export function MultiSelectContent({
}
/>
) : (
// eslint-disable-next-line jsx-a11y/no-autofocus
<button autoFocus aria-hidden="true" className="sr-only" />
// biome-ignore lint/a11y/noAriaHiddenOnFocusable: <intended>
<button
autoFocus
aria-hidden="true"
className="sr-only"
type="button"
/>
)}
<CommandList>
{canSearch && (

View file

@ -1,10 +1,9 @@
/* eslint-disable better-tailwindcss/no-unregistered-classes */
import { useVirtualizer } from "@tanstack/react-virtual";
import { useRef, useState, type JSX } from "react";
import { type JSX, useRef, useState } from "react";
import ReactSelect, {
type MenuListProps,
type GroupBase,
type CSSObjectWithLabel,
type GroupBase,
type MenuListProps,
} from "react-select";
import { cn } from "~/lib/utils";
@ -282,11 +281,13 @@ type RepackValues = {
export const RepackValues = ({ values, options }: RepackValues) => {
if (Array.isArray(values)) {
return values.map((v) => ({
// biome-ignore lint/style/noNonNullAssertion: <intended>
label: options[Number.parseInt(v)]!,
value: v,
}));
}
return {
// biome-ignore lint/style/noNonNullAssertion: <intended>
label: options[Number.parseInt(values)]!,
value: values,
};

View file

@ -3,19 +3,19 @@
import * as DialogPrimitive from "@radix-ui/react-dialog";
import { X } from "lucide-react";
import {
createContext,
forwardRef,
useContext,
useEffect,
useRef,
useState,
type ComponentPropsWithoutRef,
createContext,
type Dispatch,
type ElementRef,
forwardRef,
type HTMLAttributes,
type PointerEvent,
type ReactNode,
type SetStateAction,
useContext,
useEffect,
useRef,
useState,
} from "react";
import { cn } from "~/lib/utils";

View file

@ -1,7 +1,7 @@
"use client";
import { cn } from "~/lib/utils";
import { motion, useInView } from "framer-motion";
import * as React from "react";
import { cn } from "~/lib/utils";
type TextStaggeredFadeProps = {
text: string;

View file

@ -1,7 +1,6 @@
import { Plus } from "lucide-react";
import { useState } from "react";
import { cn } from "~/lib/utils";
import type { ChatsChatid } from "~/schemas/public/Chats";
import { api } from "~/utils/api";
import { Button } from "~/components/ui/button";
import {
Dialog,
DialogContent,
@ -9,9 +8,6 @@ import {
DialogHeader,
DialogTitle,
} from "~/components/ui/dialog";
import type { EtichetteIdEtichetta } from "~/schemas/public/Etichette";
import { Button } from "~/components/ui/button";
import { Separator } from "~/components/ui/separator";
import {
Select,
SelectContent,
@ -19,7 +15,11 @@ import {
SelectTrigger,
SelectValue,
} from "~/components/ui/select";
import { Plus } from "lucide-react";
import { Separator } from "~/components/ui/separator";
import { cn } from "~/lib/utils";
import type { ChatsChatid } from "~/schemas/public/Chats";
import type { EtichetteIdEtichetta } from "~/schemas/public/Etichette";
import { api } from "~/utils/api";
export const EtichetteDisplayer = ({
chatId,
@ -50,6 +50,7 @@ export const EtichetteDisplayer = ({
/>
))}
<button
type="button"
onClick={() => setOpenEdit(true)}
className="flex items-center justify-center rounded-lg border p-1"
>
@ -185,7 +186,7 @@ function hexToRgb(hex: string): { r: number; g: number; b: number } {
}
export function colorIsDarkSimple(color: string) {
if (color == "#FFFFFF") return false;
if (color === "#FFFFFF") return false;
const { r, g, b } = hexToRgb(color);
return r * 0.299 + g * 0.587 + b * 0.114 <= 186;
}

View file

@ -1,7 +1,7 @@
import Link from "next/link";
import { useRouter } from "next/router";
import { useTranslation } from "~/providers/I18nProvider";
import { HomeIcon } from "~/components/IconComponents";
import { useTranslation } from "~/providers/I18nProvider";
export default function FailedAnnuncioLoading() {
const router = useRouter();
@ -17,6 +17,7 @@ export default function FailedAnnuncioLoading() {
<p className="text-neutral-600">{t.annuncio_load_fail.sottotitolo}</p>
<div className="flex flex-wrap items-center justify-center gap-3">
<button
type="button"
onClick={() => {
router.back();
}}

View file

@ -6,10 +6,7 @@ export const Footer = () => {
const { t } = useTranslation();
return (
<div className="mt-auto">
<footer
aria-label="Site Footer"
className="bg-muted text-muted-foreground bottom-0 z-40 w-full"
>
<footer className="bg-muted text-muted-foreground bottom-0 z-40 w-full">
<div className="mx-auto max-w-6xl px-4 py-6 sm:px-6 lg:px-8">
<div className="text-center">
<Link
@ -80,10 +77,7 @@ export const MiniFooter = () => {
const { t } = useTranslation();
return (
<div className="mt-auto flex w-full">
<footer
aria-label="Site Footer"
className="dark:bg-primary z-40 w-full bg-neutral-100 text-neutral-700 dark:text-white"
>
<footer className="dark:bg-primary z-40 w-full bg-neutral-100 text-neutral-700 dark:text-white">
<div className="mx-auto max-w-5xl px-2 py-2 sm:px-6 lg:px-8">
<div className="text-center">
<Link

View file

@ -1,21 +1,21 @@
"use client";
import {
Circle,
MapContainer,
TileLayer,
Marker,
Popup,
Circle,
TileLayer,
useMapEvents,
} from "react-leaflet";
import "leaflet/dist/leaflet.css";
import "leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.css";
import "leaflet-defaulticon-compatibility";
import { cn } from "~/lib/utils";
import MapMarker from "~/components/map/map_marker";
import { Marker as CustomMarker } from "~/components/map/custom_marker";
import { Home } from "lucide-react";
import { Marker as CustomMarker } from "~/components/map/custom_marker";
import MapMarker from "~/components/map/map_marker";
import { cn } from "~/lib/utils";
type LatLon = {
lat: number;
@ -63,7 +63,7 @@ const MedianPoint = (pos: posData[]) => {
return { lat, lng };
};
const Map = ({
const MapComp = ({
posix,
autocenter,
zoom = defaults.zoom,
@ -196,7 +196,7 @@ const Map = ({
);
};
export default Map;
export default MapComp;
/*
const PuntiInteresse: {

View file

@ -1,14 +1,24 @@
import {
useState,
useId,
useMemo,
type DivIconOptions,
DomEvent,
divIcon,
type LeafletEventHandlerFn,
type LeafletEventHandlerFnMap,
type Marker as LeafletMarker,
type PointExpression,
type PointTuple,
} from "leaflet";
import {
type ComponentType,
forwardRef,
isValidElement,
type ReactElement,
useCallback,
isValidElement,
type ComponentType,
useLayoutEffect,
forwardRef,
useEffect,
useId,
useLayoutEffect,
useMemo,
useState,
} from "react";
import { createPortal } from "react-dom";
import { isValidElementType } from "react-is";
@ -16,22 +26,12 @@ import {
Marker as ReactLeafletMarker,
type MarkerProps as ReactLeafletMarkerProps,
} from "react-leaflet";
import {
divIcon,
DomEvent,
type LeafletEventHandlerFn,
type LeafletEventHandlerFnMap,
type PointExpression,
type DivIconOptions,
type Marker as LeafletMarker,
type PointTuple,
} from "leaflet";
import { type SetRequired } from "type-fest";
import {
createHtmlPortalNode,
OutPortal,
InPortal,
OutPortal,
} from "react-reverse-portal";
import type { SetRequired } from "type-fest";
const getCoordsFromPointExpression = (expression?: PointExpression) => {
if (!expression) return [];
@ -127,7 +127,8 @@ type CoreComponentMarkerOpts = {
};
type UnionKeys<T> = T extends T ? keyof T : never;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
// biome-ignore lint/suspicious/noExplicitAny: <intended>
type StrictUnionHelper<T, TAll> = T extends any
? T & Partial<Record<Exclude<UnionKeys<TAll>, keyof T>, undefined>>
: never;
@ -147,7 +148,8 @@ type BaseMarkerProps<AdditionalIconTypes = never> = Omit<
"icon"
> & {
/** A {@link ReactElement} representing the Markers icon, or any type from [react-leaflet Marker](https://react-leaflet.js.org/docs/api-components/#marker) component. */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
// biome-ignore lint/suspicious/noExplicitAny: <intended>
icon: ReactElement<any> | AdditionalIconTypes;
/**
@ -182,7 +184,7 @@ const ComponentMarker = forwardRef<LeafletMarker, BaseMarkerProps>(
) => {
const [markerRendered, setMarkerRendered] = useState(false);
const [, setChangeCount] = useState(0);
const id = "marker-" + useId();
const id = `marker-${useId()}`;
const portalNode = useMemo(
() =>

View file

@ -1,6 +1,6 @@
"use client";
import { cn } from "~/lib/utils";
import type { ReactNode } from "react";
import { cn } from "~/lib/utils";
interface MapMarkerProps {
label: ReactNode;

View file

@ -1,9 +1,9 @@
import { useState } from "react";
import { useRouter } from "next/router";
import { setCookie } from "cookies-next/client";
import { EngFlag, ItaFlag } from "~/components/svgs";
import LoadingButton from "~/components/custom_ui/loading-button";
import { add } from "date-fns";
import { useRouter } from "next/router";
import { useState } from "react";
import LoadingButton from "~/components/custom_ui/loading-button";
import { EngFlag, ItaFlag } from "~/components/svgs";
export const LangToggle = () => {
const router = useRouter();

View file

@ -1,7 +1,11 @@
"use client";
import { LogIn, LogOut } from "lucide-react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { useRouter } from "next/router";
import { useSession } from "~/providers/SessionProvider";
import { api } from "~/utils/api";
import { IconMatrix, type IconType } from "~/components/IconComponents";
import { LoadingSpinner } from "~/components/spinner";
import { Button } from "~/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
@ -11,15 +15,11 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "~/components/ui/dropdown-menu";
import { Button } from "~/components/ui/button";
import Link from "next/link";
import { LogIn, LogOut } from "lucide-react";
import { useTranslation } from "~/providers/I18nProvider";
import { cn } from "~/lib/utils";
import { IconMatrix, type IconType } from "~/components/IconComponents";
import { usePathname } from "next/navigation";
import { UserAvatar } from "~/components/user_avatar";
import { LoadingSpinner } from "~/components/spinner";
import { cn } from "~/lib/utils";
import { useTranslation } from "~/providers/I18nProvider";
import { useSession } from "~/providers/SessionProvider";
import { api } from "~/utils/api";
type LoginButtonProps = {
open: boolean;

View file

@ -1,7 +1,8 @@
import Link from "next/link";
import { cn } from "~/lib/utils";
import { LogoSvg } from "~/components/svgs";
import { cn } from "~/lib/utils";
import { useTranslation } from "~/providers/I18nProvider";
type MainNavProps = {
pathname: string;
};

View file

@ -1,7 +1,13 @@
import type { ReactNode } from "react";
import { cn } from "~/lib/utils";
import { Button } from "~/components/ui/button";
import { AlignLeft, Home } from "lucide-react";
import Link, { type LinkProps } from "next/link";
import { useRouter } from "next/navigation";
import type { ReactNode } from "react";
import { IconMatrix } from "~/components/IconComponents";
import { LangToggle } from "~/components/navbar/lang-toggle";
import { UserHeaderSection } from "~/components/navbar/login-button";
import { ASvg, LogoSvg } from "~/components/svgs";
import { Button } from "~/components/ui/button";
import { Separator } from "~/components/ui/separator";
import {
Sheet,
SheetContent,
@ -10,16 +16,10 @@ import {
SheetTitle,
SheetTrigger,
} from "~/components/ui/sheet";
import { AlignLeft, Home } from "lucide-react";
import { useRouter } from "next/navigation";
import { useSession } from "~/providers/SessionProvider";
import { IconMatrix } from "~/components/IconComponents";
import { useTranslation } from "~/providers/I18nProvider";
import { Separator } from "~/components/ui/separator";
import { UserHeaderSection } from "~/components/navbar/login-button";
import { ASvg, LogoSvg } from "~/components/svgs";
import { useMediaQuery } from "~/hooks/use-media-query";
import { LangToggle } from "~/components/navbar/lang-toggle";
import { cn } from "~/lib/utils";
import { useTranslation } from "~/providers/I18nProvider";
import { useSession } from "~/providers/SessionProvider";
type MobileNavProps = {
pathname: string;
@ -74,7 +74,7 @@ export function MobileNav({
<div className="flex h-full flex-col space-y-2 pt-4">
{pathname.startsWith("/area-riservata") && (
<>
{session && session.user && (
{session?.user && (
<AreaRiservataLinks
isAdmin={session.user.isAdmin}
pathname={pathname}
@ -166,7 +166,6 @@ function MobileLink({
onOpenChange?.(false);
} else {
router.push(
// eslint-disable-next-line @typescript-eslint/no-base-to-string
href.toString(),
);
onOpenChange?.(false);

View file

@ -1,19 +1,18 @@
"use client";
import { Search } from "lucide-react";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import { CodiceBox } from "~/components/codiceRicerca";
import { Button } from "~/components/ui/button";
import {
Dialog,
DialogTrigger,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogDescription,
DialogTrigger,
} from "~/components/ui/dialog";
import { CodiceBox } from "~/components/codiceRicerca";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
export function RicercaCommand() {
const [open, setOpen] = useState(false);

View file

@ -1,6 +1,6 @@
import { Button } from "~/components/ui/button";
import { Settings } from "lucide-react";
import { LangToggle } from "~/components/navbar/lang-toggle";
import { Button } from "~/components/ui/button";
import {
Popover,

View file

@ -1,11 +1,11 @@
"use client";
import { usePathname } from "next/navigation";
import { MainNav } from "~/components/navbar/main-nav";
import { MobileNav } from "~/components/navbar/mobile-nav";
import { useState } from "react";
import { UserHeaderSection } from "~/components/navbar/login-button";
import { SettingsPopover } from "~/components/navbar/settings-modal";
import { MainNav } from "~/components/navbar/main-nav";
import { MobileNav } from "~/components/navbar/mobile-nav";
import { RicercaCommand } from "~/components/navbar/ricerca_command";
import { SettingsPopover } from "~/components/navbar/settings-modal";
export function SiteHeader() {
const pathname = usePathname();

View file

@ -1,6 +1,6 @@
import { motion, type Transition } from "framer-motion";
import { Moon, Sun } from "lucide-react";
import { useTheme } from "next-themes";
import { motion, type Transition } from "framer-motion";
import { cn } from "~/lib/utils";
export const ThemeSwitch = () => {
@ -19,7 +19,7 @@ export const ThemeSwitch = () => {
onClick={() => setTheme(theme === "light" ? "dark" : "light")}
className={cn(
`flex h-10 w-20 rounded-full bg-neutral-200 p-[5px] shadow-inner hover:cursor-pointer dark:bg-neutral-700`,
theme == "light" && "place-content-end",
theme === "light" && "place-content-end",
)}
>
<motion.div
@ -31,7 +31,7 @@ export const ThemeSwitch = () => {
transition={spring}
>
<motion.div whileTap={{ rotate: 360 }}>
{theme == "light" ? (
{theme === "light" ? (
<Sun className="size-6 stroke-yellow-300" />
) : (
<Moon className="size-6 stroke-slate-200" />

View file

@ -1,4 +1,5 @@
import { CheckCircle, AlertCircle, Loader2 } from "lucide-react";
import { AlertCircle, CheckCircle, Loader2 } from "lucide-react";
type PaymentStatus = "success" | "processing" | "error";
interface PaymentStatusProps {

View file

@ -186,6 +186,7 @@ const CountrySelect = React.memo(
height: `${size}px`,
transform: `translateY(${start}px)`,
}}
// biome-ignore lint/style/noNonNullAssertion: <exists>
onSelect={() => onChange(country.value!)}
value={country.value}
>

View file

@ -1,21 +1,21 @@
import { useTranslation } from "~/providers/I18nProvider";
import { ExternalLink } from "lucide-react";
import Link from "next/link";
import { useEffect, useState } from "react";
import { AnimatedNumber } from "~/components/custom_ui/animated-number";
import { LoadingPage } from "~/components/loading";
import { Button } from "~/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
CardDescription,
CardContent,
} from "~/components/ui/card";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/components/ui/tabs";
import { cn } from "~/lib/utils";
import { AnimatedNumber } from "~/components/custom_ui/animated-number";
import { ExternalLink } from "lucide-react";
import { Tabs, TabsList, TabsTrigger, TabsContent } from "~/components/ui/tabs";
import Link from "next/link";
import { api } from "~/utils/api";
import { LoadingPage } from "~/components/loading";
import { useTranslation } from "~/providers/I18nProvider";
import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum";
import { useEffect, useState } from "react";
import { api } from "~/utils/api";
export const PricingChoice = () => {
const { t } = useTranslation();
@ -185,7 +185,7 @@ export const PricingComponent = ({
Contratto
</h2>
{tipo == TipologiaPosizioneEnum.Transitorio ? (
{tipo === TipologiaPosizioneEnum.Transitorio ? (
<div className="flex flex-col justify-center leading-none">
<span
className="xs:text-3xl text-2xl font-semibold sm:text-6xl"

View file

@ -36,7 +36,7 @@ export const ProgressRedirect = ({ href }: { href: string }) => {
await router.push(href);
}
if (progress == 100) {
if (progress === 100) {
redirect().catch((error) => {
console.error("Error during redirect:", error);
});

View file

@ -1,5 +1,3 @@
import { Confirm } from "~/components/confirm";
import { Button, buttonVariants } from "~/components/ui/button";
import {
Check,
ChevronsUpDown,
@ -12,28 +10,16 @@ import {
Trash2,
Wrench,
} from "lucide-react";
import type {
Storageindex,
StorageindexId,
} from "~/schemas/public/Storageindex";
import { Label } from "~/components/ui/label";
import { UploadModal } from "~/components/upload_modal";
import { ExtIcon } from "~/components/area-riservata/allegati";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover";
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from "~/components/ui/command";
import { api } from "~/utils/api";
import Link from "next/link";
import { useRef, useState } from "react";
import toast from "react-hot-toast";
import { z } from "zod/v4";
import { ExtIcon } from "~/components/area-riservata/allegati";
import { Confirm } from "~/components/confirm";
import {
AnimatedButton,
type AnimatedButtonRef,
} from "~/components/custom_ui/animated-button";
import {
Credenza,
CredenzaBody,
@ -46,11 +32,7 @@ import {
CredenzaTrigger,
} from "~/components/custom_ui/credenza";
import { LoadingPage } from "~/components/loading";
import Link from "next/link";
import { cn, formatCurrency } from "~/lib/utils";
import { useRef, useState } from "react";
import { z } from "zod/v4";
import { Separator } from "~/components/ui/separator";
import { Button, buttonVariants } from "~/components/ui/button";
import {
Card,
CardContent,
@ -59,16 +41,34 @@ import {
CardHeader,
CardTitle,
} from "~/components/ui/card";
import type { ServizioAnnunciUpdate } from "~/schemas/public/ServizioAnnunci";
import { Switch } from "~/components/ui/switch";
import { useServizio, useServizioAnnuncio } from "~/providers/ServizioProvider";
import {
AnimatedButton,
type AnimatedButtonRef,
} from "~/components/custom_ui/animated-button";
import type { AnnunciId } from "~/schemas/public/Annunci";
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from "~/components/ui/command";
import { Label } from "~/components/ui/label";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover";
import { Separator } from "~/components/ui/separator";
import { Switch } from "~/components/ui/switch";
import { UploadModal } from "~/components/upload_modal";
import { cn, formatCurrency } from "~/lib/utils";
import { useTranslation } from "~/providers/I18nProvider";
import { useServizio, useServizioAnnuncio } from "~/providers/ServizioProvider";
import type { AnnunciId } from "~/schemas/public/Annunci";
import type { ServizioAnnunciUpdate } from "~/schemas/public/ServizioAnnunci";
import type {
Storageindex,
StorageindexId,
} from "~/schemas/public/Storageindex";
import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum";
import { api } from "~/utils/api";
export const AnnuncioActions = () => {
const { servizioId, userId, isAdmin } = useServizio();
@ -527,7 +527,7 @@ const ContrattoSection = ({
};
if (isLoading) return <LoadingPage />;
if (files == undefined) {
if (files === undefined) {
return <p>Errore nel caricamento dei documenti</p>;
}
return (
@ -619,7 +619,7 @@ const RicevutaSection = ({
};
if (isLoading) return <LoadingPage />;
if (files == undefined) {
if (files === undefined) {
return <p>Errore nel caricamento dei documenti</p>;
}
return (
@ -773,7 +773,7 @@ const DocSection = ({
});
if (isLoading) return <LoadingPage />;
if (files == undefined) {
if (files === undefined) {
return <p>Errore nel caricamento dei documenti</p>;
}
return (
@ -905,6 +905,7 @@ const DocCombo = ({
value={file.id}
onSelect={(currentValue) => {
if (currentValue !== current) {
// biome-ignore lint/style/noNonNullAssertion: <exists>
onSelect(files.find((f) => f.id === currentValue)!);
}
setOpen(false);

View file

@ -1,14 +1,5 @@
import { useServizioAnnuncio } from "~/providers/ServizioProvider";
import { Interactions } from "~/components/servizio/interactions";
import type { Annunci } from "~/schemas/public/Annunci";
import { useTranslation } from "~/providers/I18nProvider";
import { cn, formatCurrency } from "~/lib/utils";
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
import { ImageFlbk } from "~/components/ImageWithFallback";
import { Button } from "~/components/ui/button";
import { ExternalLink, UnfoldVertical } from "lucide-react";
import Link from "next/link";
import { handleConsegna } from "~/lib/annuncio_details";
import {
Credenza,
CredenzaBody,
@ -20,6 +11,11 @@ import {
CredenzaTitle,
CredenzaTrigger,
} from "~/components/custom_ui/credenza";
import { ImageFlbk } from "~/components/ImageWithFallback";
import { AnnuncioActions } from "~/components/servizio/annuncio_actions";
import { Interactions } from "~/components/servizio/interactions";
import { Button } from "~/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
import {
Carousel,
CarouselContent,
@ -27,7 +23,11 @@ import {
CarouselNext,
CarouselPrevious,
} from "~/components/ui/carousel";
import { AnnuncioActions } from "~/components/servizio/annuncio_actions";
import { handleConsegna } from "~/lib/annuncio_details";
import { cn, formatCurrency } from "~/lib/utils";
import { useTranslation } from "~/providers/I18nProvider";
import { useServizioAnnuncio } from "~/providers/ServizioProvider";
import type { Annunci } from "~/schemas/public/Annunci";
export const AnnuncioCard = ({ className }: { className?: string }) => {
const { data } = useServizioAnnuncio();
@ -193,8 +193,7 @@ const AnnuncioDettaglio = ({
<div className="flex flex-col gap-2 px-2">
<Carousel opts={{ loop: true }}>
<CarouselContent>
{data.url_immagini &&
data.url_immagini.map((img, idx) => (
{data?.url_immagini?.map((img, idx) => (
<CarouselItem key={img}>
<ImageFlbk
alt={`${data.codice} - ${idx}`}

View file

@ -1,10 +1,10 @@
import type { StorageindexId } from "~/schemas/public/Storageindex";
import { api } from "~/utils/api";
import { LoadingPage } from "~/components/loading";
import { AllegatoIframe } from "~/components/allegato-iframe";
import { LoadingPage } from "~/components/loading";
import { Button } from "~/components/ui/button";
import { handleDownload } from "~/hooks/filesHooks";
import { useTranslation } from "~/providers/I18nProvider";
import type { StorageindexId } from "~/schemas/public/Storageindex";
import { api } from "~/utils/api";
export const FileSection = ({ storageId }: { storageId: StorageindexId }) => {
const { data: fileInfos, isLoading } = api.storage.getStorageFromId.useQuery({

View file

@ -1,19 +1,3 @@
import Link from "next/link";
import { Button, type ButtonConfigs } from "~/components/ui/button";
import { useTranslation } from "~/providers/I18nProvider";
import { api } from "~/utils/api";
import toast from "react-hot-toast";
import {
Credenza,
CredenzaBody,
CredenzaClose,
CredenzaContent,
CredenzaDescription,
CredenzaFooter,
CredenzaHeader,
CredenzaTitle,
CredenzaTrigger,
} from "~/components/custom_ui/credenza";
import {
CircleCheck,
CircleUser,
@ -26,19 +10,35 @@ import {
Pointer,
TriangleAlert,
} from "lucide-react";
import Link from "next/link";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import toast from "react-hot-toast";
import {
Credenza,
CredenzaBody,
CredenzaClose,
CredenzaContent,
CredenzaDescription,
CredenzaFooter,
CredenzaHeader,
CredenzaTitle,
CredenzaTrigger,
} from "~/components/custom_ui/credenza";
import LoadingButton from "~/components/custom_ui/loading-button";
import { LoadingPage } from "~/components/loading";
import { useRouter } from "next/router";
import { cn } from "~/lib/utils";
import { useEffect, useState } from "react";
import { useServizio, useServizioAnnuncio } from "~/providers/ServizioProvider";
import { Button, type ButtonConfigs } from "~/components/ui/button";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "~/components/ui/tooltip";
import { cn } from "~/lib/utils";
import { useTranslation } from "~/providers/I18nProvider";
import { useServizio, useServizioAnnuncio } from "~/providers/ServizioProvider";
import type { AnnunciId } from "~/schemas/public/Annunci";
import { api } from "~/utils/api";
export const Interactions = () => {
const { servizio, servizioId } = useServizio();

View file

@ -1,4 +1,21 @@
import type { UsersId } from "~/schemas/public/Users";
import { Package, PackageCheck, UserCircle } from "lucide-react";
import Link from "next/link";
import { useRouter } from "next/router";
import { useEffect } from "react";
import toast from "react-hot-toast";
import { AnnuncioCard } from "~/components/servizio/annuncio_card";
import { SaldoButton } from "~/components/servizio/interactions";
import { ServizioDuration } from "~/components/servizio/service-duration-display";
import {
ServizioActions,
ServizioActions2,
} from "~/components/servizio/servizio_actions";
import {
AnnunciCompatibili,
AnnunciInConferma,
AnnunciSelezionati,
} from "~/components/servizio/servizio_annunci_accordions";
import { Button } from "~/components/ui/button";
import {
Card,
CardContent,
@ -6,33 +23,16 @@ import {
CardHeader,
CardTitle,
} from "~/components/ui/card";
import { cn } from "~/lib/utils";
import { Button } from "~/components/ui/button";
import type { ServizioData } from "~/server/controllers/servizio.controller";
import { Package, PackageCheck, UserCircle } from "lucide-react";
import Link from "next/link";
import { Progress } from "~/components/ui/progress";
import {
ServizioActions,
ServizioActions2,
} from "~/components/servizio/servizio_actions";
import { SaldoButton } from "~/components/servizio/interactions";
import { api } from "~/utils/api";
import { cn } from "~/lib/utils";
import {
ServizioAnnuncioProvider,
ServizioProvider,
useServizio,
} from "~/providers/ServizioProvider";
import { useRouter } from "next/router";
import { useEffect } from "react";
import toast from "react-hot-toast";
import {
AnnunciCompatibili,
AnnunciInConferma,
AnnunciSelezionati,
} from "~/components/servizio/servizio_annunci_accordions";
import { AnnuncioCard } from "~/components/servizio/annuncio_card";
import { ServizioDuration } from "~/components/servizio/service-duration-display";
import type { UsersId } from "~/schemas/public/Users";
import type { ServizioData } from "~/server/controllers/servizio.controller";
import { api } from "~/utils/api";
export const ServizioContainer = ({
servizio,
@ -316,6 +316,7 @@ export const ServizioContent = () => {
>
<h3>
{a.codice} - confermato il:{" "}
{/** biome-ignore lint/style/noNonNullAssertion: <already checked above> */}
{new Date(a.accettato_conferma_at!).toLocaleDateString(
"it",
{
@ -577,6 +578,7 @@ const ServizioMain = () => {
>
<h3>
{a.codice} - confermato il:{" "}
{/** biome-ignore lint/style/noNonNullAssertion: <already checked> */}
{new Date(a.accettato_conferma_at!).toLocaleDateString(
"it",
{

View file

@ -1,13 +1,13 @@
import { Card, CardContent } from "~/components/ui/card";
import { CalendarDays, Hourglass, CalendarClock, Clock } from "lucide-react";
import { Progress } from "~/components/ui/progress"; // Import the Progress component
import { add, differenceInDays } from "date-fns";
import { CalendarClock, CalendarDays, Clock, Hourglass } from "lucide-react";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "~/components/ui/accordion";
import { Card, CardContent } from "~/components/ui/card";
import { Progress } from "~/components/ui/progress"; // Import the Progress component
import { useMediaQuery } from "~/hooks/use-media-query";
export const ServizioDuration = ({

View file

@ -1,19 +1,18 @@
import toast from "react-hot-toast";
import type { AnnunciId } from "~/schemas/public/Annunci";
import { api } from "~/utils/api";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "~/components/ui/dialog";
import { Button } from "~/components/ui/button";
import { LoadingPage } from "~/components/loading";
import { MultiSelect } from "~/components/custom_ui/multiselect";
import { add } from "date-fns";
import { Bug, Calculator, ClockAlert, Plus, Wrench } from "lucide-react";
import { useState } from "react";
import toast from "react-hot-toast";
import {
Credenza,
CredenzaBody,
CredenzaContent,
CredenzaDescription,
CredenzaHeader,
CredenzaTitle,
CredenzaTrigger,
} from "~/components/custom_ui/credenza";
import { MultiSelect } from "~/components/custom_ui/multiselect";
import { LoadingPage } from "~/components/loading";
import {
AlertDialog,
AlertDialogAction,
@ -25,31 +24,31 @@ import {
AlertDialogTitle,
AlertDialogTrigger,
} from "~/components/ui/alert-dialog";
import { Bug, Calculator, ClockAlert, Plus, Wrench } from "lucide-react";
import { FormNewServizio, type FormValues } from "~/forms/FormNewServizio";
import {
Credenza,
CredenzaBody,
CredenzaContent,
CredenzaDescription,
CredenzaHeader,
CredenzaTitle,
CredenzaTrigger,
} from "~/components/custom_ui/credenza";
import { useState } from "react";
import { useServizio } from "~/providers/ServizioProvider";
import type { ServizioServizioId } from "~/schemas/public/Servizio";
import type { UsersId } from "~/schemas/public/Users";
import {
FormEditServizio,
type FormValues as EditFormValues,
} from "~/forms/FormEditServizioAdmin";
import { Button } from "~/components/ui/button";
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "~/components/ui/collapsible";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "~/components/ui/dialog";
import {
type FormValues as EditFormValues,
FormEditServizio,
} from "~/forms/FormEditServizioAdmin";
import { FormNewServizio, type FormValues } from "~/forms/FormNewServizio";
import { useServizio } from "~/providers/ServizioProvider";
import type { AnnunciId } from "~/schemas/public/Annunci";
import type { ServizioServizioId } from "~/schemas/public/Servizio";
import type { UsersId } from "~/schemas/public/Users";
import { api } from "~/utils/api";
export const ServizioActions = () => {
const { servizio, isAdmin, userId } = useServizio();
@ -411,7 +410,7 @@ const EditServizioAdmin = () => {
</CollapsibleTrigger>
<CollapsibleContent>
{(() => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
// biome-ignore lint/correctness/noUnusedVariables: <need to extract>
const { annunci, ...rest } = servizio;
return <pre>{JSON.stringify(rest, null, 2)}</pre>;
})()}

View file

@ -1,26 +1,26 @@
import { api } from "~/utils/api";
import { ExternalLink, Trash2 } from "lucide-react";
import Link from "next/link";
import toast from "react-hot-toast";
import { InteressatoButtonBatchV } from "~/components/annuncio-interactions/annuncio_interactions";
import { AddButton } from "~/components/servizio/annuncio_actions";
import {
AnnuncioCard,
BasicAnnuncioCard,
} from "~/components/servizio/annuncio_card";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "~/components/ui/accordion";
import type { UsersId } from "~/schemas/public/Users";
import {
AnnuncioCard,
BasicAnnuncioCard,
} from "~/components/servizio/annuncio_card";
import { Button } from "~/components/ui/button";
import { AddButton } from "~/components/servizio/annuncio_actions";
import { InteressatoButtonBatchV } from "~/components/annuncio-interactions/annuncio_interactions";
import {
ServizioAnnuncioProvider,
useServizio,
} from "~/providers/ServizioProvider";
import { ExternalLink, Trash2 } from "lucide-react";
import Link from "next/link";
import type { UsersId } from "~/schemas/public/Users";
import type { ServizioData } from "~/server/controllers/servizio.controller";
import toast from "react-hot-toast";
import { api } from "~/utils/api";
export const AnnunciInConferma = ({
annunci,
@ -118,7 +118,7 @@ export const AnnunciCompatibili = () => {
<Accordion
type="single"
collapsible
defaultValue={!data || data.length == 0 ? "compatibili" : undefined}
defaultValue={!data || data.length === 0 ? "compatibili" : undefined}
>
<AccordionItem value="compatibili" className="space-y-4">
<AccordionTrigger className="cursor-pointer rounded-md border-2 border-neutral-500 bg-white p-2">
@ -126,7 +126,7 @@ export const AnnunciCompatibili = () => {
</AccordionTrigger>
<AccordionContent>
<div className="flex flex-col flex-wrap gap-5">
{!data || data.length == 0 ? (
{!data || data.length === 0 ? (
<div className="flex items-center justify-center gap-1 rounded-md bg-white p-4 sm:flex">
<span>
Nessun annuncio compatibile trovato. Amplia la ricerca per
@ -187,7 +187,7 @@ export const AnnunciRichiesti = ({ userId }: { userId: UsersId }) => {
</AccordionTrigger>
<AccordionContent>
<div className="flex flex-col flex-wrap gap-5">
{!data || data.length == 0 ? (
{!data || data.length === 0 ? (
<div className="flex items-center justify-center gap-1 rounded-md bg-white p-4 sm:flex">
<span>
Nessun annuncio compatibile trovato. Amplia la ricerca per

View file

@ -26,6 +26,7 @@ export const LoadingSpinner = ({
strokeWidth="2"
viewBox="0 0 24 24"
>
<title>spinner</title>
<path d="M21 12a9 9 0 1 1-6.219-8.56" />
</svg>
);

View file

@ -1,7 +1,7 @@
import Link from "next/link";
import { useRouter } from "next/router";
import { useTranslation } from "~/providers/I18nProvider";
import { ShieldExclamationIcon } from "~/components/IconComponents";
import { useTranslation } from "~/providers/I18nProvider";
export const Status500 = () => {
const router = useRouter();
@ -16,6 +16,7 @@ export const Status500 = () => {
<p className="text-neutral-600">{t[500].sottotitolo}</p>
<div className="flex flex-wrap items-center justify-center gap-3">
<button
type="button"
onClick={() => {
router.back();
}}

View file

@ -8,6 +8,7 @@ export const HeroSvg = (props: SVGProps<SVGSVGElement>) => (
height={500}
width={500}
>
<title>hero</title>
<path
d="m240.441 54.013-137.11 137.098V362.3h285.188V202.08L240.441 54.013Z"
fill="#EAEAEA"
@ -399,6 +400,7 @@ export const ASvg = (props: SVGProps<SVGSVGElement>) => (
viewBox="20 0 10 12"
{...props}
>
<title>{"\u0410"}</title>
<g
style={{
fill: "#E0211A",
@ -426,6 +428,7 @@ export const LogoSvg = (props: SVGProps<SVGSVGElement>) => (
viewBox="0 0 68.463 13.175"
{...props}
>
<title>{"lloggi.it Info"}</title>
<defs>
<path id="a" d="M69.953 191.276h677.665v225.16H69.953z" />
<path id="b" d="M69.953 191.276h677.665v225.16H69.953z" />
@ -506,6 +509,7 @@ export const EngFlag = (props: SVGProps<SVGSVGElement>) => (
viewBox="0 0 512 512"
{...props}
>
<title>EnglishFlag</title>
<path
d="M473.655 88.276H38.345C17.167 88.276 0 105.443 0 126.621V385.38c0 21.177 17.167 38.345 38.345 38.345h435.31c21.177 0 38.345-17.167 38.345-38.345V126.621c0-21.178-17.167-38.345-38.345-38.345z"
style={{
@ -540,6 +544,7 @@ export const ItaFlag = (props: SVGProps<SVGSVGElement>) => (
viewBox="0 0 512 512"
{...props}
>
<title>ItalianFlag</title>
<path
d="M38.345 88.273C17.167 88.273 0 105.44 0 126.618v258.759c0 21.177 17.167 38.345 38.345 38.345h132.322V88.273H38.345z"
style={{
@ -574,6 +579,7 @@ export const MissingFile = ({ className }: { className?: string }) => (
}}
className={className}
>
<title>MissingFile</title>
<path
d="M152.5 31.5a79.737 79.737 0 0 1 21 1.5c1.929 3.256 2.429 6.756 1.5 10.5-.5 1.833-1.667 3-3.5 3.5-5.886-.04-11.553.96-17 3a14.442 14.442 0 0 0-2.5 5.5 59.854 59.854 0 0 1-2 14c-3.256 1.928-6.756 2.428-10.5 1.5-1.833-.5-3-1.667-3.5-3.5-4.35-16.87 1.15-28.87 16.5-36Z"
style={{

View file

@ -1,13 +1,12 @@
import type { ColumnDef } from "@tanstack/react-table";
import { DataTableColumnHeader } from "~/components/custom_ui/dataTable-header";
import { Button } from "~/components/ui/button";
import { Cog } from "lucide-react";
import type { SearchFiltro } from "~/components/custom_ui/dataTable-toolbar";
import { DataTable } from "~/components/custom_ui/data-table";
import type { Annunci } from "~/schemas/public/Annunci";
import Link from "next/link";
import { DataTable } from "~/components/custom_ui/data-table";
import { DataTableColumnHeader } from "~/components/custom_ui/dataTable-header";
import type { SearchFiltro } from "~/components/custom_ui/dataTable-toolbar";
import { Button } from "~/components/ui/button";
import { StatusBadge } from "~/pages/area-riservata/admin/edit-annuncio/[id]";
import type { Annunci } from "~/schemas/public/Annunci";
export const AnnunciTable = ({
data,
}: {

View file

@ -1,7 +1,7 @@
import type { ColumnDef } from "@tanstack/react-table";
import { DataTableColumnHeader } from "~/components/custom_ui/dataTable-header";
import { Cog } from "lucide-react";
import { DataTable } from "~/components/custom_ui/data-table";
import { DataTableColumnHeader } from "~/components/custom_ui/dataTable-header";
import type { SearchFiltro } from "~/components/custom_ui/dataTable-toolbar";
import { Button } from "~/components/ui/button";
import type { Banlist } from "~/schemas/public/Banlist";

View file

@ -1,7 +1,7 @@
import type { ColumnDef } from "@tanstack/react-table";
import { DataTableColumnHeader } from "~/components/custom_ui/dataTable-header";
import { Cog } from "lucide-react";
import { DataTable } from "~/components/custom_ui/data-table";
import { DataTableColumnHeader } from "~/components/custom_ui/dataTable-header";
import type { SearchFiltro } from "~/components/custom_ui/dataTable-toolbar";
import { Button } from "~/components/ui/button";
import type { Banners } from "~/schemas/public/Banners";

Some files were not shown because too many files have changed in this diff Show more