Add UI input & textarea
Signed-off-by: Bryan Frimin <bryan@getprobo.com> Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
committed by
Sacha Al Himdani
parent
a86181c83d
commit
15cf471454
15
apps/console2/src/hooks/useFetchQuery.ts
Normal file
15
apps/console2/src/hooks/useFetchQuery.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { useQuery, type UseQueryOptions } from "@tanstack/react-query";
|
||||
|
||||
/**
|
||||
* Wrapper around useQuery to fetch data from an API endpoint
|
||||
*/
|
||||
export function useFetchQuery<T>(
|
||||
url: string,
|
||||
options?: Omit<UseQueryOptions<T>, "queryKey" | "queryFn">
|
||||
) {
|
||||
return useQuery<T>({
|
||||
...options,
|
||||
queryKey: [url],
|
||||
queryFn: () => fetch(url).then((res) => res.json()),
|
||||
});
|
||||
}
|
||||
@@ -1,16 +1,27 @@
|
||||
import { StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import "./index.css";
|
||||
import { App } from "./App.tsx";
|
||||
import { RelayProvider } from "./providers/RelayProviders.tsx";
|
||||
import { TranslatorProvider } from "./providers/TranslatorProvider.tsx";
|
||||
import { App } from "./App";
|
||||
import { RelayProvider } from "./providers/RelayProviders";
|
||||
import { TranslatorProvider } from "./providers/TranslatorProvider";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
refetchOnWindowFocus: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<StrictMode>
|
||||
<RelayProvider>
|
||||
<TranslatorProvider>
|
||||
<App />
|
||||
</TranslatorProvider>
|
||||
</RelayProvider>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<RelayProvider>
|
||||
<TranslatorProvider>
|
||||
<App />
|
||||
</TranslatorProvider>
|
||||
</RelayProvider>
|
||||
</QueryClientProvider>
|
||||
</StrictMode>
|
||||
);
|
||||
|
||||
@@ -5,28 +5,58 @@ import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
Label,
|
||||
Select,
|
||||
Option,
|
||||
Field,
|
||||
} from "@probo/ui";
|
||||
import type { ReactNode } from "react";
|
||||
import { useMemo, useState, type ReactNode } from "react";
|
||||
import { useFetchQuery } from "../../../hooks/useFetchQuery";
|
||||
|
||||
type Props = {
|
||||
trigger: ReactNode;
|
||||
};
|
||||
|
||||
type Risk = {
|
||||
category: string;
|
||||
name: string;
|
||||
description: string;
|
||||
};
|
||||
|
||||
export default function NewRiskDialog({ trigger }: Props) {
|
||||
const { __ } = useTranslate();
|
||||
|
||||
const onTemplateChange = (risk: Risk) => {
|
||||
console.log(risk);
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open
|
||||
onClose={() => {}}
|
||||
trigger={trigger}
|
||||
title={<Breadcrumb items={[__("Risks"), __("New Risk")]}></Breadcrumb>}
|
||||
>
|
||||
<form>
|
||||
<DialogContent>
|
||||
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Velit harum
|
||||
maiores dolor hic nisi repudiandae autem quod rem eveniet iure
|
||||
quibusdam sint iste numquam, suscipit ad delectus aspernatur. Quo,
|
||||
amet.
|
||||
<DialogContent className="grid grid-cols-[1fr_420px]">
|
||||
{/* Main form */}
|
||||
<div className="py-8 px-12 space-y-6">
|
||||
<TemplateSelector onChange={onTemplateChange} />
|
||||
<Field
|
||||
label={__("Risk name")}
|
||||
name="name"
|
||||
placeholder={__("Service Outage")}
|
||||
/>
|
||||
<Field
|
||||
label={__("Description")}
|
||||
name="description"
|
||||
placeholder={__("Type your description here")}
|
||||
type="textarea"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Properties form */}
|
||||
<div className="py-5 px-6 bg-subtle"></div>
|
||||
</DialogContent>
|
||||
<DialogFooter>
|
||||
<Button type="submit">{__("Create risk")}</Button>
|
||||
@@ -35,3 +65,58 @@ export default function NewRiskDialog({ trigger }: Props) {
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
function TemplateSelector({ onChange }: { onChange: (risk: Risk) => void }) {
|
||||
const { __ } = useTranslate();
|
||||
const { data: risks } = useFetchQuery<Risk[]>("/data/risks/risks.json", {
|
||||
staleTime: 100_000,
|
||||
});
|
||||
|
||||
const categories = useMemo(
|
||||
() => Array.from(new Set(risks?.map((t) => t.category))),
|
||||
[risks]
|
||||
);
|
||||
|
||||
const [selectedCategory, setSelectedCategory] = useState<string | null>(null);
|
||||
|
||||
const templates = useMemo(
|
||||
() => risks?.filter((r) => r.category === selectedCategory) ?? [],
|
||||
[risks, selectedCategory]
|
||||
);
|
||||
|
||||
const onTemplateChange = (template: string) => {
|
||||
const risk = risks?.find((r) => r.name === template);
|
||||
if (!risk) {
|
||||
throw new Error("Risk not found");
|
||||
}
|
||||
onChange(risk);
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<Label>{__("Risk category")}</Label>
|
||||
<div className="grid grid-cols-2 gap-2 mt-[6px]">
|
||||
<Select
|
||||
placeholder={__("Select a category")}
|
||||
onChange={setSelectedCategory}
|
||||
>
|
||||
{categories.map((category) => (
|
||||
<Option key={category} value={category}>
|
||||
{category}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
<Select
|
||||
empty={templates?.length === 0}
|
||||
placeholder={__("Select template")}
|
||||
onChange={onTemplateChange}
|
||||
>
|
||||
{templates?.map((template) => (
|
||||
<Option key={template.name} value={template.name}>
|
||||
{template.name}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user