Skip to content

Commit

Permalink
generate put component
Browse files Browse the repository at this point in the history
  • Loading branch information
charliecooper45 committed Aug 30, 2023
1 parent 34bc931 commit 6d60dad
Show file tree
Hide file tree
Showing 3 changed files with 240 additions and 27 deletions.
10 changes: 9 additions & 1 deletion src/components/tables/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import comment from "../../comment";
import type { File, HookFile } from "../../types";
import { parseNameFormats } from "../../utils";
import { mapHookFileToCreateComponent } from "./create";
import { mapHookFileToUpdateComponent } from "./update";
import { mapHookFileToDeleteComponent } from "./delete";
import { mapHookFileToGetComponent } from "./get";

Expand All @@ -17,6 +18,7 @@ export const mapHookFileToComponent = async (
const componentName = fileName.replace("use", "");
const getComponentName = `Get${componentName}`;
const createComponentName = `Create${componentName}`;
const updateComponentName = `Update${componentName}`;
const deleteComponentName = `Delete${componentName}`;
const { camelCasePlural, pascalCase, pascalCasePlural } =
parseNameFormats(componentName);
Expand All @@ -29,15 +31,17 @@ export const mapHookFileToComponent = async (
import ${fileName} from "../../hooks/${fileName}";
import ${getComponentName} from "./${getComponentName}";
import ${createComponentName} from "./${createComponentName}";
import ${updateComponentName} from "./${updateComponentName}";
import ${deleteComponentName} from "./${deleteComponentName}";
export default function ${componentName}() {
const { ${camelCasePlural}, fetch${pascalCasePlural}, create${pascalCase}, delete${pascalCase} } = ${fileName}();
const { ${camelCasePlural}, fetch${pascalCasePlural}, create${pascalCase}, update${pascalCase}, delete${pascalCase} } = ${fileName}();
return (
<div>
<${getComponentName} ${camelCasePlural}={${camelCasePlural}} onFetch={fetch${pascalCasePlural}} />
<${createComponentName} onCreate={create${pascalCase}} onFetch={fetch${pascalCasePlural}} />
<${updateComponentName} onUpdate={update${pascalCase}} onFetch={fetch${pascalCasePlural}} />
<${deleteComponentName} onDelete={delete${pascalCase}} onFetch={fetch${pascalCasePlural}} />
</div>
)
Expand Down Expand Up @@ -67,13 +71,17 @@ export const parseComponentFilesForTables = async (
const createComponentPromises = tableHookFiles.map((tableHookFile) =>
mapHookFileToCreateComponent(tableHookFile, tables)
);
const updateComponentPromises = tableHookFiles.map((tableHookFile) =>
mapHookFileToUpdateComponent(tableHookFile, tables)
);
const deleteComponentPromises = tableHookFiles.map((tableHookFile) =>
mapHookFileToDeleteComponent(tableHookFile, tables)
);

const files = await Promise.all([
...componentPromises,
...createComponentPromises,
...updateComponentPromises,
...getComponentPromises,
...deleteComponentPromises,
]);
Expand Down
208 changes: 208 additions & 0 deletions src/components/tables/update.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
import prettier from "prettier";
import comment from "../../comment";
import type { ColumnResponse, TablesResponse } from "../../pgMeta/fetchTables";
import type { File, HookFile } from "../../types";
import { parseNameFormats } from "../../utils";

const mapColumns = (
columns?: ColumnResponse[]
): { fields: string; inputs: string } => {
if (!columns) {
return { fields: "", inputs: "" };
}

const filteredColumns = columns.filter(
(column) => column.isIdentity || column.isUpdatable
);
const fields = filteredColumns
.filter((column) => !column.isIdentity)
.map((column) => `"${column.name}"`)
.join(",");
const inputs = filteredColumns
.map((column, index) => {
const label = column.isIdentity ? `${column.name}*` : column.name;
return `
<div className="flex items-center">
<label
htmlFor="${column.name}"
style={{
flexBasis: "200px",
marginRight: "10px"
}}
>
${label}
</label>
<label
htmlFor="${column.name}"
style={{
flexBasis: "200px",
}}
>
${column.dataType}
</label>
<input
type="text"
id="${column.name}"
style={{
${index > 0 ? 'marginTop: "10px",' : ""}
background: "#000",
color: "#fff",
border: "1px solid #34383A",
marginLeft: "10px",
flex: "1",
borderRadius: "0.375rem",
padding: "4px 16px",
}}
/>
</div>
`;
})
.join(" ");

return { fields, inputs };
};

export const mapHookFileToUpdateComponent = async (
hookFile: HookFile,
tables: TablesResponse
): Promise<File> => {
const {
entityName,
file: { fileName },
} = hookFile;

const table = tables.find((table) => table.name === entityName);
const componentName = `${fileName.replace("use", "")}`;
const { pascalCase } = parseNameFormats(componentName);

const { fields, inputs } = mapColumns(table?.columns);

const content = `
${comment}
"use client";
import { FormEventHandler, MouseEventHandler, useState } from "react";
import type { Row, Update${pascalCase} } from "../../hooks/${fileName}";
const fields: Array<keyof Update${pascalCase}> = [${fields}]
export default function Update${componentName}({
onUpdate,
onFetch
}: {
onUpdate: (id: Row["id"], updatedRow: Update${pascalCase}) => Promise<Row | undefined>,
onFetch: () => Promise<void>
}) {
const [message, setMessage] = useState<string>();
const handleSubmit: FormEventHandler = (event) => {
event.preventDefault();
const target = event.target as typeof event.target & Update${pascalCase};
const id = (target["id"] as any)?.value;
const updatedRow = fields
.map((field) => ({ field, value: (target[field] as any)?.value }))
.reduce((newRow, { field,value }) => {
if (value.trim() !== "") {
newRow[field] = value;
}
return newRow;
}, {} as Record<keyof Update${pascalCase}, any>);
onUpdate(id, updatedRow)
.then((task) => {
if (task) {
setMessage("row with id " + task.id + " updated!");
onFetch();
} else {
setMessage("failed to update row!");
}
})
.catch((error) => {
if (error.message) {
setMessage(error.message);
} else {
setMessage("failed to update row!");
}
});
};
const handleClick: MouseEventHandler<HTMLButtonElement> = () => {
setMessage(undefined);
}
if (message) {
return <div style={{ display: "flex", flexDirection: "column", height: "98px", justifyContent: "end" }}>
{message}
<button
style={{
background: "#fff",
color: "#000",
marginTop: "20px",
padding: "8px 10px",
width: "200px",
borderRadius: "0.375rem",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
onClick={handleClick}
>
Go Back
</button>
</div>
}
return (
<div
style={{
paddingTop: "20px",
}}
>
<form onSubmit={handleSubmit} style={{ display: "flex", flexDirection: "column" }}>
${inputs}
<button
type="submit"
style={{
background: "#fff",
color: "#000",
marginTop: "10px",
padding: "8px 10px",
width: "200px",
borderRadius: "0.375rem",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<div style={{ marginRight: "10px" }}>Run PUT</div>
<svg
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
style={{
height: "20px",
}}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.348a1.125 1.125 0 010 1.971l-11.54 6.347a1.125 1.125 0 01-1.667-.985V5.653z"
/>
</svg>
</button>
</form>
</div>
);
}
`;

const formattedContent = await prettier.format(content, {
parser: "typescript",
});

return {
fileName: `Update${componentName}.tsx`,
content: formattedContent,
};
};
49 changes: 23 additions & 26 deletions src/hooks/table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,17 @@ const mapTableToFile = async (table: TableResponse): Promise<HookFile> => {
}, []);
const fetch${pascalCasePlural} = async() => {
try {
const { data, error } = await supabase
.from("${tableName}")
.select();
if (error) {
throw error;
}
set${pascalCasePlural}(data || []);
} catch (error) {
console.error("Error fetching", error);
try {
const { data, error } = await supabase
.from("${tableName}")
.select();
if (error) {
throw error;
}
set${pascalCasePlural}(data || []);
} catch (error) {
console.error("Error fetching", error);
}
};
const create${pascalCase} = async (newData: Insert${pascalCase}) => {
Expand All @@ -55,23 +55,20 @@ const mapTableToFile = async (table: TableResponse): Promise<HookFile> => {
};
const update${pascalCase} = async (id: Row["id"], updatedData: Update${pascalCase}) => {
try {
const { data, error } = await supabase
.from("${tableName}")
.update(updatedData)
.eq("id", id)
.select();
if (error) {
throw error;
}
set${pascalCasePlural}(
${camelCasePlural}.map((${camelCase}) =>
${camelCase}.id === id ? { ...${camelCase}, ...data[0] } : ${camelCase}
)
);
} catch (error) {
console.error("Error updating alert:", error);
const { data, error } = await supabase
.from("${tableName}")
.update(updatedData)
.eq("id", id)
.select();
if (error) {
throw error;
}
set${pascalCasePlural}(
${camelCasePlural}.map((${camelCase}) =>
${camelCase}.id === id ? { ...${camelCase}, ...data[0] } : ${camelCase}
)
);
return data[0];
};
const delete${pascalCase} = async (id: Row["id"]): Promise<number | null> => {
Expand Down

0 comments on commit 6d60dad

Please sign in to comment.