feat: GET and POST provider are working as expected and the error is shown correctly

This commit is contained in:
Pablo Lara
2024-08-04 18:18:53 +02:00
parent b16a7150fa
commit 485482c868
9 changed files with 139 additions and 34 deletions
+3 -9
View File
@@ -13,8 +13,8 @@ export const getProvider = async () => {
"X-Tenant-ID": `${process.env.HEADER_TENANT_ID}`,
},
});
const data = await providers.json();
revalidatePath("/providers")
return parseStringify(data);
} catch (error) {
return undefined;
@@ -47,10 +47,8 @@ export const addProvider = async (formData: FormData) => {
}),
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.message || "Request error");
}
revalidatePath("/providers")
return parseStringify(data);
} catch (error) {
console.error(error)
return {
@@ -58,7 +56,6 @@ export const addProvider = async (formData: FormData) => {
}
}
revalidatePath("/providers")
};
export const deleteProvider = async (formData: FormData) => {
@@ -73,15 +70,12 @@ export const deleteProvider = async (formData: FormData) => {
"X-Tenant-ID": `${process.env.HEADER_TENANT_ID}`,
},
});
} catch (error) {
console.error(error)
return {
error: getErrorMessage(error),
}
}
revalidatePath("/providers")
};
export const getErrorMessage = (error: unknown): string => {
+24
View File
@@ -304,6 +304,30 @@ export const WifiPendingIcon: React.FC<IconSvgProps> = ({
</svg>
);
export const DeleteIcon: React.FC<IconSvgProps> = ({
size = 24,
width,
height,
...props
}) => (
<svg
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true"
fill="none"
focusable="false"
height={size || height}
role="presentation"
viewBox="0 0 24 24"
width={size || width}
{...props}
>
<path
fill="currentColor"
d="M10 5h4a2 2 0 1 0-4 0M8.5 5a3.5 3.5 0 1 1 7 0h5.75a.75.75 0 0 1 0 1.5h-1.32l-1.17 12.111A3.75 3.75 0 0 1 15.026 22H8.974a3.75 3.75 0 0 1-3.733-3.389L4.07 6.5H2.75a.75.75 0 0 1 0-1.5zm2 4.75a.75.75 0 0 0-1.5 0v7.5a.75.75 0 0 0 1.5 0zM14.25 9a.75.75 0 0 1 .75.75v7.5a.75.75 0 0 1-1.5 0v-7.5a.75.75 0 0 1 .75-.75m-7.516 9.467a2.25 2.25 0 0 0 2.24 2.033h6.052a2.25 2.25 0 0 0 2.24-2.033L18.424 6.5H5.576z"
/>
</svg>
);
export const RocketIcon: React.FC<IconSvgProps> = ({
size = 24,
width,
+2
View File
@@ -1,4 +1,6 @@
export * from "./providers/AddProvider";
export * from "./providers/ButtonAddProvider";
export * from "./providers/ButtonDeleteProvider";
export * from "./providers/DateWithTime";
export * from "./providers/ProviderInfo";
export * from "./providers/ScanStatus";
+13 -14
View File
@@ -2,34 +2,35 @@
import { addProvider } from "@/actions";
import { useRef } from "react";
import { useToast } from "../ui/toast";
import { ButtonAddProvider } from "./ButtonAddProvider";
import { toast, useToast } from "../ui/toast";
import { ToastAction } from "@radix-ui/react-toast";
export const AddProvider = () => {
const ref = useRef<HTMLFormElement>(null)
const { toast } = useToast()
async function clientAction(formData:FormData) {
// reset the form
ref.current?.reset();
// client-side validation
const result = await addProvider(formData)
if (result?.error) {
const error = result.error
//show error
toast({
title: `${error}`,
description: "There was a problem with your request.",
})
if (result?.errors) {
result.errors.forEach((error: { detail: string }) => {
let errorMessage = `${error.detail}`;
// show error
toast({
title: "Wops! Something went wrong",
description: errorMessage,
});
});
} else {
toast({
title: "Success!",
description: "The provider was added successfully.",
})
});
}
}
return (
<form ref={ref} action={clientAction} className="flex gap-x-2">
<input
@@ -51,8 +52,6 @@ export const AddProvider = () => {
className="py-2 px-3 rounded-sm"
/>
<ButtonAddProvider />
</form>
);
};
+5 -1
View File
@@ -1,3 +1,5 @@
"use client";
import { Button } from "@nextui-org/react";
import React from "react";
import { useFormStatus } from "react-dom";
@@ -5,6 +7,8 @@ import { useFormStatus } from "react-dom";
export const ButtonAddProvider = () => {
const { pending } = useFormStatus();
return (
<Button type="submit">{pending ? "Adding..." : "Add provider"}</Button>
<Button type="submit" area-disabled={pending}>
{pending ? "Adding..." : "Add provider"}
</Button>
);
};
@@ -0,0 +1,21 @@
"use client";
import { Button } from "@nextui-org/react";
import React from "react";
import { useFormStatus } from "react-dom";
import { DeleteIcon } from "../icons";
export const ButtonDeleteProvider = () => {
const { pending } = useFormStatus();
return (
<Button
variant="light"
spinner={pending ? "Removing..." : " Remove"}
type="submit"
area-disabled={pending}
>
<DeleteIcon size={20} /> Delete
</Button>
);
};
+58
View File
@@ -0,0 +1,58 @@
"use client";
import { useRef } from "react";
import { deleteProvider } from "@/actions";
import { useToast } from "../ui/toast";
import { ButtonDeleteProvider } from "./ButtonDeleteProvider";
export const DeleteProvider = ({ id }: { id: string }) => {
const ref = useRef<HTMLFormElement>(null);
const { toast } = useToast();
// const [state, formAction] = useFormState(deleteProvider, initialState);
async function clientAction(formData: FormData) {
// reset the form
ref.current?.reset();
// client-side validation
const result = await deleteProvider(formData);
if (result?.error) {
const error = result.error;
//show error
toast({
title: `${error}`,
description: "There was a problem with your request.",
});
} else {
toast({
title: "Success!",
description: "The provider was removed successfully.",
});
}
}
return (
<form ref={ref} action={clientAction} className="flex gap-x-2">
<input type="hidden" name="id" value={id} />
<ButtonDeleteProvider />
{/* <p aria-live="polite" className="sr-only" role="status">
{state?.message}
</p> */}
</form>
);
};
// const [state, formAction] = useFormState(deleteTodo, initialState);
// return (
// <form action={formAction}>
// <input type="hidden" name="id" value={id} />
// <input type="hidden" name="todo" value={todo} />
// <DeleteButton />
// <p aria-live="polite" className="sr-only" role="status">
// {state?.message}
// </p>
// </form>
// );
@@ -16,9 +16,10 @@ import { ProviderProps } from "@/types";
import { DateWithTime } from "../DateWithTime";
import { ProviderInfo } from "../ProviderInfo";
import { DeleteProvider } from "../DeleteProvider";
const getProviderAttributes = (row: { original: ProviderProps }) => {
return row.original.attributes;
const getProviderData= (row: { original: ProviderProps }) => {
return row.original;
};
export const ColumnsProviders: ColumnDef<ProviderProps>[] = [
@@ -30,8 +31,7 @@ export const ColumnsProviders: ColumnDef<ProviderProps>[] = [
accessorKey: "account",
header: "Account",
cell: ({ row }) => {
const { connection, provider, alias, provider_id } =
getProviderAttributes(row);
const { attributes: { connection, provider, alias, provider_id } } = getProviderData(row);
return (
<ProviderInfo
connected={connection.connected}
@@ -54,7 +54,7 @@ export const ColumnsProviders: ColumnDef<ProviderProps>[] = [
accessorKey: "lastScan",
header: "Last Scan",
cell: ({ row }) => {
const { updated_at } = getProviderAttributes(row);
const { attributes: {updated_at} } = getProviderData(row);
return <DateWithTime dateTime={updated_at} />;
},
},
@@ -62,7 +62,7 @@ export const ColumnsProviders: ColumnDef<ProviderProps>[] = [
accessorKey: "nextScan",
header: "Next Scan",
cell: ({ row }) => {
const { updated_at } = getProviderAttributes(row);
const { attributes: {updated_at} } = getProviderData(row);
const nextDay = add(new Date(updated_at), {
hours: 24,
});
@@ -81,7 +81,7 @@ export const ColumnsProviders: ColumnDef<ProviderProps>[] = [
accessorKey: "added",
header: "Added",
cell: ({ row }) => {
const { inserted_at } = getProviderAttributes(row);
const { attributes: {inserted_at} } = getProviderData(row);
return <DateWithTime dateTime={inserted_at} showTime={false} />;
},
},
@@ -89,7 +89,8 @@ export const ColumnsProviders: ColumnDef<ProviderProps>[] = [
accessorKey: "actions",
header: () => <div className="text-right">Actions</div>,
id: "actions",
cell: () => {
cell: ({ row }) => {
const { id } = getProviderData(row);
return (
<div className="relative flex justify-end items-center gap-2">
<Dropdown className="bg-background border-1 border-default-200">
@@ -101,7 +102,9 @@ export const ColumnsProviders: ColumnDef<ProviderProps>[] = [
<DropdownMenu>
<DropdownItem>Check connection</DropdownItem>
<DropdownItem>Manage</DropdownItem>
<DropdownItem>Delete</DropdownItem>
<DropdownItem>
<DeleteProvider id={id} />
</DropdownItem>
</DropdownMenu>
</Dropdown>
</div>
+1 -1
View File
@@ -5,7 +5,7 @@ import * as React from "react";
import type { ToastActionElement, ToastProps } from "@/components";
const TOAST_LIMIT = 1;
const TOAST_LIMIT = 6;
const TOAST_REMOVE_DELAY = 1000000;
type ToasterToast = ToastProps & {