Skip to content
This repository was archived by the owner on Aug 19, 2025. It is now read-only.

Commit 6d60dad

Browse files
generate put component
1 parent 34bc931 commit 6d60dad

File tree

3 files changed

+240
-27
lines changed

3 files changed

+240
-27
lines changed

src/components/tables/index.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import comment from "../../comment";
44
import type { File, HookFile } from "../../types";
55
import { parseNameFormats } from "../../utils";
66
import { mapHookFileToCreateComponent } from "./create";
7+
import { mapHookFileToUpdateComponent } from "./update";
78
import { mapHookFileToDeleteComponent } from "./delete";
89
import { mapHookFileToGetComponent } from "./get";
910

@@ -17,6 +18,7 @@ export const mapHookFileToComponent = async (
1718
const componentName = fileName.replace("use", "");
1819
const getComponentName = `Get${componentName}`;
1920
const createComponentName = `Create${componentName}`;
21+
const updateComponentName = `Update${componentName}`;
2022
const deleteComponentName = `Delete${componentName}`;
2123
const { camelCasePlural, pascalCase, pascalCasePlural } =
2224
parseNameFormats(componentName);
@@ -29,15 +31,17 @@ export const mapHookFileToComponent = async (
2931
import ${fileName} from "../../hooks/${fileName}";
3032
import ${getComponentName} from "./${getComponentName}";
3133
import ${createComponentName} from "./${createComponentName}";
34+
import ${updateComponentName} from "./${updateComponentName}";
3235
import ${deleteComponentName} from "./${deleteComponentName}";
3336
3437
export default function ${componentName}() {
35-
const { ${camelCasePlural}, fetch${pascalCasePlural}, create${pascalCase}, delete${pascalCase} } = ${fileName}();
38+
const { ${camelCasePlural}, fetch${pascalCasePlural}, create${pascalCase}, update${pascalCase}, delete${pascalCase} } = ${fileName}();
3639
3740
return (
3841
<div>
3942
<${getComponentName} ${camelCasePlural}={${camelCasePlural}} onFetch={fetch${pascalCasePlural}} />
4043
<${createComponentName} onCreate={create${pascalCase}} onFetch={fetch${pascalCasePlural}} />
44+
<${updateComponentName} onUpdate={update${pascalCase}} onFetch={fetch${pascalCasePlural}} />
4145
<${deleteComponentName} onDelete={delete${pascalCase}} onFetch={fetch${pascalCasePlural}} />
4246
</div>
4347
)
@@ -67,13 +71,17 @@ export const parseComponentFilesForTables = async (
6771
const createComponentPromises = tableHookFiles.map((tableHookFile) =>
6872
mapHookFileToCreateComponent(tableHookFile, tables)
6973
);
74+
const updateComponentPromises = tableHookFiles.map((tableHookFile) =>
75+
mapHookFileToUpdateComponent(tableHookFile, tables)
76+
);
7077
const deleteComponentPromises = tableHookFiles.map((tableHookFile) =>
7178
mapHookFileToDeleteComponent(tableHookFile, tables)
7279
);
7380

7481
const files = await Promise.all([
7582
...componentPromises,
7683
...createComponentPromises,
84+
...updateComponentPromises,
7785
...getComponentPromises,
7886
...deleteComponentPromises,
7987
]);

src/components/tables/update.ts

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
import prettier from "prettier";
2+
import comment from "../../comment";
3+
import type { ColumnResponse, TablesResponse } from "../../pgMeta/fetchTables";
4+
import type { File, HookFile } from "../../types";
5+
import { parseNameFormats } from "../../utils";
6+
7+
const mapColumns = (
8+
columns?: ColumnResponse[]
9+
): { fields: string; inputs: string } => {
10+
if (!columns) {
11+
return { fields: "", inputs: "" };
12+
}
13+
14+
const filteredColumns = columns.filter(
15+
(column) => column.isIdentity || column.isUpdatable
16+
);
17+
const fields = filteredColumns
18+
.filter((column) => !column.isIdentity)
19+
.map((column) => `"${column.name}"`)
20+
.join(",");
21+
const inputs = filteredColumns
22+
.map((column, index) => {
23+
const label = column.isIdentity ? `${column.name}*` : column.name;
24+
return `
25+
<div className="flex items-center">
26+
<label
27+
htmlFor="${column.name}"
28+
style={{
29+
flexBasis: "200px",
30+
marginRight: "10px"
31+
}}
32+
>
33+
${label}
34+
</label>
35+
<label
36+
htmlFor="${column.name}"
37+
style={{
38+
flexBasis: "200px",
39+
}}
40+
>
41+
${column.dataType}
42+
</label>
43+
<input
44+
type="text"
45+
id="${column.name}"
46+
style={{
47+
${index > 0 ? 'marginTop: "10px",' : ""}
48+
background: "#000",
49+
color: "#fff",
50+
border: "1px solid #34383A",
51+
marginLeft: "10px",
52+
flex: "1",
53+
borderRadius: "0.375rem",
54+
padding: "4px 16px",
55+
}}
56+
/>
57+
</div>
58+
`;
59+
})
60+
.join(" ");
61+
62+
return { fields, inputs };
63+
};
64+
65+
export const mapHookFileToUpdateComponent = async (
66+
hookFile: HookFile,
67+
tables: TablesResponse
68+
): Promise<File> => {
69+
const {
70+
entityName,
71+
file: { fileName },
72+
} = hookFile;
73+
74+
const table = tables.find((table) => table.name === entityName);
75+
const componentName = `${fileName.replace("use", "")}`;
76+
const { pascalCase } = parseNameFormats(componentName);
77+
78+
const { fields, inputs } = mapColumns(table?.columns);
79+
80+
const content = `
81+
${comment}
82+
83+
"use client";
84+
85+
import { FormEventHandler, MouseEventHandler, useState } from "react";
86+
import type { Row, Update${pascalCase} } from "../../hooks/${fileName}";
87+
88+
const fields: Array<keyof Update${pascalCase}> = [${fields}]
89+
90+
export default function Update${componentName}({
91+
onUpdate,
92+
onFetch
93+
}: {
94+
onUpdate: (id: Row["id"], updatedRow: Update${pascalCase}) => Promise<Row | undefined>,
95+
onFetch: () => Promise<void>
96+
}) {
97+
const [message, setMessage] = useState<string>();
98+
99+
const handleSubmit: FormEventHandler = (event) => {
100+
event.preventDefault();
101+
const target = event.target as typeof event.target & Update${pascalCase};
102+
const id = (target["id"] as any)?.value;
103+
const updatedRow = fields
104+
.map((field) => ({ field, value: (target[field] as any)?.value }))
105+
.reduce((newRow, { field,value }) => {
106+
if (value.trim() !== "") {
107+
newRow[field] = value;
108+
}
109+
return newRow;
110+
}, {} as Record<keyof Update${pascalCase}, any>);
111+
onUpdate(id, updatedRow)
112+
.then((task) => {
113+
if (task) {
114+
setMessage("row with id " + task.id + " updated!");
115+
onFetch();
116+
} else {
117+
setMessage("failed to update row!");
118+
}
119+
})
120+
.catch((error) => {
121+
if (error.message) {
122+
setMessage(error.message);
123+
} else {
124+
setMessage("failed to update row!");
125+
}
126+
});
127+
};
128+
129+
const handleClick: MouseEventHandler<HTMLButtonElement> = () => {
130+
setMessage(undefined);
131+
}
132+
133+
if (message) {
134+
return <div style={{ display: "flex", flexDirection: "column", height: "98px", justifyContent: "end" }}>
135+
{message}
136+
<button
137+
style={{
138+
background: "#fff",
139+
color: "#000",
140+
marginTop: "20px",
141+
padding: "8px 10px",
142+
width: "200px",
143+
borderRadius: "0.375rem",
144+
display: "flex",
145+
alignItems: "center",
146+
justifyContent: "center",
147+
}}
148+
onClick={handleClick}
149+
>
150+
Go Back
151+
</button>
152+
</div>
153+
}
154+
155+
return (
156+
<div
157+
style={{
158+
paddingTop: "20px",
159+
}}
160+
>
161+
<form onSubmit={handleSubmit} style={{ display: "flex", flexDirection: "column" }}>
162+
${inputs}
163+
<button
164+
type="submit"
165+
style={{
166+
background: "#fff",
167+
color: "#000",
168+
marginTop: "10px",
169+
padding: "8px 10px",
170+
width: "200px",
171+
borderRadius: "0.375rem",
172+
display: "flex",
173+
alignItems: "center",
174+
justifyContent: "center",
175+
}}
176+
>
177+
<div style={{ marginRight: "10px" }}>Run PUT</div>
178+
<svg
179+
fill="none"
180+
viewBox="0 0 24 24"
181+
strokeWidth={1.5}
182+
stroke="currentColor"
183+
style={{
184+
height: "20px",
185+
}}
186+
>
187+
<path
188+
strokeLinecap="round"
189+
strokeLinejoin="round"
190+
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"
191+
/>
192+
</svg>
193+
</button>
194+
</form>
195+
</div>
196+
);
197+
}
198+
`;
199+
200+
const formattedContent = await prettier.format(content, {
201+
parser: "typescript",
202+
});
203+
204+
return {
205+
fileName: `Update${componentName}.tsx`,
206+
content: formattedContent,
207+
};
208+
};

src/hooks/table.ts

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,17 @@ const mapTableToFile = async (table: TableResponse): Promise<HookFile> => {
2929
}, []);
3030
3131
const fetch${pascalCasePlural} = async() => {
32-
try {
33-
const { data, error } = await supabase
34-
.from("${tableName}")
35-
.select();
36-
if (error) {
37-
throw error;
38-
}
39-
set${pascalCasePlural}(data || []);
40-
} catch (error) {
41-
console.error("Error fetching", error);
32+
try {
33+
const { data, error } = await supabase
34+
.from("${tableName}")
35+
.select();
36+
if (error) {
37+
throw error;
4238
}
39+
set${pascalCasePlural}(data || []);
40+
} catch (error) {
41+
console.error("Error fetching", error);
42+
}
4343
};
4444
4545
const create${pascalCase} = async (newData: Insert${pascalCase}) => {
@@ -55,23 +55,20 @@ const mapTableToFile = async (table: TableResponse): Promise<HookFile> => {
5555
};
5656
5757
const update${pascalCase} = async (id: Row["id"], updatedData: Update${pascalCase}) => {
58-
try {
59-
const { data, error } = await supabase
60-
.from("${tableName}")
61-
.update(updatedData)
62-
.eq("id", id)
63-
.select();
64-
if (error) {
65-
throw error;
66-
}
67-
set${pascalCasePlural}(
68-
${camelCasePlural}.map((${camelCase}) =>
69-
${camelCase}.id === id ? { ...${camelCase}, ...data[0] } : ${camelCase}
70-
)
71-
);
72-
} catch (error) {
73-
console.error("Error updating alert:", error);
58+
const { data, error } = await supabase
59+
.from("${tableName}")
60+
.update(updatedData)
61+
.eq("id", id)
62+
.select();
63+
if (error) {
64+
throw error;
7465
}
66+
set${pascalCasePlural}(
67+
${camelCasePlural}.map((${camelCase}) =>
68+
${camelCase}.id === id ? { ...${camelCase}, ...data[0] } : ${camelCase}
69+
)
70+
);
71+
return data[0];
7572
};
7673
7774
const delete${pascalCase} = async (id: Row["id"]): Promise<number | null> => {

0 commit comments

Comments
 (0)