xtablo-source/apps/main/src/components/WebcalModal.tsx
Arthur Belleville 7a0a5548f9
Lint and format
2025-10-23 21:36:21 +02:00

185 lines
6.4 KiB
TypeScript

import { toast } from "@xtablo/shared";
import { Button } from "@xtablo/ui/components/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "@xtablo/ui/components/dialog";
import { Input } from "@xtablo/ui/components/input";
import { Label } from "@xtablo/ui/components/label";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@xtablo/ui/components/select";
import { CopyIcon } from "lucide-react";
import { useState } from "react";
import { useTablosList } from "../hooks/tablos";
import { useGenerateWebcalToken } from "../hooks/webcal";
interface WebcalModalProps {
open: boolean;
onOpenChange: (open: boolean) => void;
}
export const WebcalModal = ({ open, onOpenChange }: WebcalModalProps) => {
const [selectedTabloId, setSelectedTabloId] = useState<string | null>(null);
const { data: tablos, isLoading: tablosLoading } = useTablosList();
const { generateWebcalUrl, isPending, data: webcalUrl } = useGenerateWebcalToken();
const copyToClipboard = async (text: string, type: string) => {
try {
await navigator.clipboard.writeText(text);
toast.add(
{
title: "Copié !",
description: `${type} copié dans le presse-papiers`,
type: "success",
},
{ timeout: 2000 }
);
} catch (_error) {
toast.add(
{
title: "Erreur",
description: "Impossible de copier dans le presse-papiers",
type: "error",
},
{ timeout: 3000 }
);
}
};
const getTabloName = (tabloId: string) => {
if (tabloId === null) return "Tous les tablos";
return tablos?.find((t) => t.id === tabloId)?.name || "Tablo inconnu";
};
return (
<Dialog
open={open}
onOpenChange={(open) => {
onOpenChange(open);
setSelectedTabloId(null);
}}
>
<DialogContent className="max-w-2xl max-h-[90vh] overflow-y-auto">
<DialogHeader className="bg-linear-to-r from-purple-500 to-purple-600 -m-6 mb-0 p-6 text-white rounded-t-lg">
<DialogTitle className="text-xl font-medium text-white">
Synchronisation de calendrier
</DialogTitle>
<DialogDescription className="text-purple-100">
Synchronisez vos événements avec votre application de calendrier préférée
</DialogDescription>
</DialogHeader>
<div className="p-6 pt-0">
{/* Generate new subscription */}
<div className="mb-2">
<div className="space-y-4">
<div>
<Label> Calendrier à synchroniser </Label>
<Select
value={selectedTabloId || undefined}
onValueChange={(value) => setSelectedTabloId(value)}
disabled={tablosLoading}
>
<SelectTrigger className="w-full my-2" aria-label="Sélectionner un calendrier">
<SelectValue
placeholder={tablosLoading ? "Chargement..." : "Sélectionner un calendrier"}
/>
</SelectTrigger>
<SelectContent>
{tablos?.map((tablo) => (
<SelectItem key={tablo.id} value={tablo.id}>
{tablo.name}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<Button
onClick={() => generateWebcalUrl(selectedTabloId)}
disabled={isPending || selectedTabloId === null}
variant="secondary"
>
{isPending ? "Génération..." : "Générer l'URL de synchronisation"}
</Button>
</div>
{/* Generated webcal URLs */}
{webcalUrl && (
<div className="mt-6 p-4 bg-muted border border-border rounded-lg">
<h4 className="font-medium text-foreground mb-3">
URL générée pour &ldquo;
{getTabloName(selectedTabloId || "")}
&rdquo;
</h4>
<div className="space-y-3">
{/* TODO: Add webcal URL */}
{/* <div>
<Label className="block mb-1">
URL de souscription (webcal://)
</Label>
<div className="flex gap-2">
<Input
type="text"
value={webcalUrl.http_url}
readOnly
className="flex-1"
/>
<Button
onClick={() =>
copyToClipboard(
webcalUrl.http_url,
"URL de souscription"
)
}
variant="secondary"
size="icon"
title="Copier l'URL"
>
<CopyIcon className="h-4 w-4" />
</Button>
</div>
</div> */}
<div>
<div className="flex gap-2">
<Input type="text" value={webcalUrl.http_url} readOnly className="flex-1" />
<Button
onClick={() => copyToClipboard(webcalUrl.http_url, "URL HTTP")}
variant="secondary"
size="icon"
title="Copier l'URL"
>
<CopyIcon className="h-4 w-4" />
</Button>
</div>
</div>
</div>
<div className="mt-3 text-sm text-muted-foreground">
<p className="font-medium">Instructions :</p>
<ul className="list-disc list-inside mt-1 space-y-1">
<li>
Copiez l&apos;URL de souscription et ajoutez-la à votre application de
calendrier
</li>
<li>Les événements se synchroniseront automatiquement toutes les heures</li>
</ul>
</div>
</div>
)}
</div>
</div>
</DialogContent>
</Dialog>
);
};