185 lines
6.4 KiB
TypeScript
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 “
|
|
{getTabloName(selectedTabloId || "")}
|
|
”
|
|
</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'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>
|
|
);
|
|
};
|