diff --git a/ui/src/App.tsx b/ui/src/App.tsx index d89292f..8f89cd9 100644 --- a/ui/src/App.tsx +++ b/ui/src/App.tsx @@ -16,6 +16,7 @@ import { FacturesPage } from "./pages/factures"; import { PlanningPage } from "./pages/planning"; import { ChantiersPage } from "./pages/chantiers"; import { ChatPage } from "./pages/chat"; +import { FeedbackPage } from "./pages/feedback"; import { AllCommunityModule, ModuleRegistry } from "ag-grid-community"; import ChatProvider from "./providers/ChatProvider"; import { UserStoreProvider } from "./providers/UserStoreProvider"; @@ -83,6 +84,14 @@ export const App = () => { } /> + + + + } + /> } /> } /> diff --git a/ui/src/components/NavigationBar.tsx b/ui/src/components/NavigationBar.tsx index c980b9f..d6b88bf 100644 --- a/ui/src/components/NavigationBar.tsx +++ b/ui/src/components/NavigationBar.tsx @@ -354,7 +354,7 @@ export function MainNavigation({ isCollapsed }: { isCollapsed: boolean }) {
  • diff --git a/ui/src/hooks/feedback.ts b/ui/src/hooks/feedback.ts new file mode 100644 index 0000000..276c578 --- /dev/null +++ b/ui/src/hooks/feedback.ts @@ -0,0 +1,22 @@ +import { useMutation } from "@tanstack/react-query"; +import { supabase } from "./auth"; +import { useUser } from "@ui/providers/UserStoreProvider"; +import { FeedbackData } from "@ui/pages/feedback"; + +// Create new feedback +export const useCreateFeedback = () => { + const user = useUser(); + const { mutate, isSuccess, isPending } = useMutation({ + mutationFn: async ({ fd_type, message }: FeedbackData) => { + const { error } = await supabase.from("feedbacks").insert({ + fd_type, + message, + user_id: user?.id ?? "", + }); + if (error) throw error; + }, + onSuccess: () => {}, + }); + + return { createFeedback: mutate, isSuccess, isPending }; +}; diff --git a/ui/src/pages/feedback.tsx b/ui/src/pages/feedback.tsx new file mode 100644 index 0000000..fe49df9 --- /dev/null +++ b/ui/src/pages/feedback.tsx @@ -0,0 +1,157 @@ +import React, { useState } from "react"; +import { Button } from "@ui/ui-library/button"; +import { Form } from "@ui/ui-library/form"; +import { TextField, Label, TextArea, Description } from "@ui/ui-library/field"; +import { Text } from "@ui/ui-library/text"; +import { Separator } from "react-aria-components"; +import { SendIcon, ArrowLeftIcon } from "lucide-react"; +import { twMerge } from "tailwind-merge"; +import { useNavigate } from "react-router-dom"; +import { useCreateFeedback } from "@ui/hooks/feedback"; + +export interface FeedbackData { + fd_type: "bug" | "feature" | "improvement" | "other"; + message: string; +} + +export function FeedbackPage() { + const navigate = useNavigate(); + const [formData, setFormData] = useState({ + fd_type: "improvement", + message: "", + }); + + const { createFeedback, isSuccess, isPending } = useCreateFeedback(); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + createFeedback(formData); + }; + + const handleInputChange = (field: keyof FeedbackData, value: string) => { + setFormData((prev) => ({ ...prev, [field]: value })); + }; + + return ( +
    + {/* Header */} +
    +
    + +
    + Envoyer un commentaire + + Aidez-nous à améliorer XTablo en partageant vos idées + +
    +
    +
    + + + + {isSuccess ? ( +
    +
    + +
    + + Merci pour votre commentaire ! + + + Votre commentaire a été envoyé avec succès. Nous apprécions que vous + ayez pris le temps de nous aider à nous améliorer. + + +
    + ) : ( +
    +
    + {/* Feedback Type */} + + + + + + {/* Message Field */} + + +