Skip to content

Commit

Permalink
moved everything
Browse files Browse the repository at this point in the history
  • Loading branch information
Johan committed Jan 15, 2024
1 parent 61157a4 commit 590b83d
Show file tree
Hide file tree
Showing 15 changed files with 472 additions and 395 deletions.
2 changes: 1 addition & 1 deletion src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export default () => (
<Route path={links.layout.link + "/*"} element={<LayoutComponent />} />
<Route path={links.view.link} element={<View />} />
<Route path={links.card.link} element={<Card />} />
<Route path={links.form.link} element={<Form />} />
<Route path={links.form.link + "/*"} element={<Form />} />
<Route path={links.loadDataAsync.link} element={<LoadDataAsync />} />
<Route path={links.notifications.link} element={<Notifications />} />
<Route path={links.code.link} element={<Code />} />
Expand Down
58 changes: 57 additions & 1 deletion src/components/buttons/with-action.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";

import Spinner from "../spinner";
import BtnWithActionGeneric, { BtnProps } from "../../lib/buttons/with-action";
import { SubmitButtonProps } from "../../lib/form/type";

const Btn = ({ children, disabled, onClick }: BtnProps) => {
return (
Expand All @@ -19,3 +20,58 @@ const Btn = ({ children, disabled, onClick }: BtnProps) => {
const BtnWithAction = BtnWithActionGeneric(Btn);

export default BtnWithAction;

const getButtonClassName = (context?: "primary") => {
const classBase = "m-2 px-4 py-2 border rounded-md text-sm font-medium ";

if (context === "primary") {
return (
classBase +
"border-transparent rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:bg-blue-300"
);
}
return classBase + "hover:bg-gray-100 px-4 py-2";
};

export const Button = ({
onClick,
context,
disabled,
type,
children,
}: {
type?: "submit";
disabled?: boolean;
context?: "primary";
onClick?: () => void;
children: string | JSX.Element;
}) => {
const className = getButtonClassName(context);

return (
<button
type={type}
disabled={disabled}
className={className}
onClick={onClick}
>
{children}
</button>
);
};

export const SubmitButton = ({ disabled, loading }: SubmitButtonProps) => {
if (loading) {
return <Spinner />;
}

return (
<Button type="submit" disabled={disabled} context="primary">
Submit
</Button>
);
};

export const BackButton = ({ onClick }: { onClick: () => void }) => (
<Button onClick={onClick}>Back</Button>
);
143 changes: 143 additions & 0 deletions src/examples/form/free-ui.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import React from "react";

import * as T from "../../lib/form/type";

import {
Input,
Checkbox as InputCheckbox,
SelectObject as InputOptions,
Select as InputOptionsScalar,
InputWrapper as Wrapper,
} from "../../components/form/inputs";
import { FormWrapper } from "../../lib/form/generator2";
import { SubmitButton } from "../../components/buttons/with-action";

enum UIStyle {
card = 1,
list = 2,
}

interface FormData {
name: string;
isUuid: boolean;
country: { id: number; name: string };
lang: { id: string; name: string };
uiStyle: UIStyle;
}

const countries: T.OptionUnit<number>[] = [
{ id: 1, name: "Switzerland" },
{ id: 2, name: "Australia" },
];

const langs: T.OptionUnit[] = [
{ id: "en", name: "English" },
{ id: "fr", name: "French" },
];

const uiStyles: T.OptionUnit<UIStyle>[] = Object.keys(UIStyle)
.filter((x) => !isNaN(x as any))
.map((id) => ({
id: id as any as UIStyle,
name: UIStyle[id as any as UIStyle],
}));

const FormUI = ({
onSubmit,
errors,
form,
setForm,
loading,
}: T.FormUIProps<FormData>) => {
console.log(errors);
return (
<form onSubmit={onSubmit}>
<Wrapper label="Name" error={errors["name"]}>
<Input
value={form["name"]}
onChange={(name) => setForm({ ...form, name })}
/>
</Wrapper>
<Wrapper label={"is uuid"} error={errors["isUuid"]}>
<InputCheckbox
value={form["isUuid"]}
onChange={(isUuid) => setForm({ ...form, isUuid })}
/>
</Wrapper>
<Wrapper
label="Country"
info={"Pick a country from the list"}
error={errors["country"]}
>
<InputOptions<number, number>
options={countries}
value={form["country"]}
onChange={(country) => setForm({ ...form, country })}
/>
</Wrapper>
<Wrapper
label="Language"
info={"Pick a language from the list"}
error={errors["lang"]}
>
<InputOptions<string, string>
options={langs}
value={form["lang"]}
onChange={(lang) => setForm({ ...form, lang })}
/>
</Wrapper>

<Wrapper
label="UI Style"
info={"Pick a UI style from the list"}
error={errors["uiStyle"]}
>
<InputOptionsScalar<UIStyle, UIStyle>
options={uiStyles}
value={form["uiStyle"]}
onChange={(uiStyle) => setForm({ ...form, uiStyle })}
/>
</Wrapper>

<SubmitButton loading={loading} />
</form>
);
};

const clientValidationFunction = (
v: Partial<FormData>
): T.FormErrors<FormData> => {
console.log(v);

const e: T.FormErrors<FormData> = {};

if (!("name" in v) || v["name"] === "") {
e.name = "wth dude";
}

if (!("isUuid" in v) || v.isUuid === false) {
e.isUuid = "wth dude";
}

return e;
};

const asyncCall = () =>
new Promise((r, f) => {
setTimeout(() => {
console.log("sdf");
f({ country: "sdf" });
}, 2000);
});

const FreeUI = () => {
return (
<FormWrapper
FormUI={FormUI}
onSuccess={console.log}
clientValidationFunction={clientValidationFunction}
asyncCall={asyncCall}
/>
);
};
export default FreeUI;
78 changes: 78 additions & 0 deletions src/examples/form/generated-form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import React from "react";

import * as T from "../../lib/form/type";

import { FormWrapper, generateFormUI } from "../../lib/form/generator2/index";
import {
InputGeneric,
InputWrapper as Wrapper,
} from "../../components/form/inputs";
import { SubmitButton } from "../../components/buttons/with-action";

enum UIStyle {
card = 1,
list = 2,
}

interface FormData {
name: string;
isUuid: boolean;
country: { id: number; name: string };
lang: { id: string; name: string };
uiStyle: UIStyle;
}

const clientValidationFunction = (
v: Partial<FormData>
): T.FormErrors<FormData> => {
console.log(v);

const e: T.FormErrors<FormData> = {};

if (!("name" in v) || v["name"] === "") {
e.name = "wth dude";
}

if (!("isUuid" in v) || v.isUuid === false) {
e.isUuid = "wth dude";
}

return e;
};

const asyncCall = () =>
new Promise((r, f) => {
setTimeout(() => {
console.log("sdf");
f({ country: "sdf" });
}, 2000);
});

const formDef: T.FormDefUnit<FormData>[] = [
{
name: "name",
label: "Name",
uxType: T.FormUIType.Text,
placeholder: "add something here",
},
{
name: "isUuid",
label: "Is Uuid",
uxType: T.FormUIType.Switch,
placeholder: "add something here",
},
];

const GeneratedForm = () => {
return (
<>
<FormWrapper
FormUI={generateFormUI(InputGeneric, Wrapper, SubmitButton)(formDef)}
onSuccess={console.log}
clientValidationFunction={clientValidationFunction}
asyncCall={asyncCall}
/>
</>
);
};
export default GeneratedForm;
27 changes: 24 additions & 3 deletions src/examples/form/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@ import FormUI from "./ui";
import FormGenerated from "./generated";

import { apiCall, onSuccess, cartoonCharacters, shape } from "./utils";
import FreeUI from "./free-ui";
import GeneratedForm from "./generated-form";
import FormDefs from "./ui-generate";

const Form = FormWrapper<FormDataShape, Out>(FormUI, shape, apiCall);

export default () => (
<>
<h1>Form</h1>
<h1 className="font-bold text-2xl py-2">Form</h1>
<h3 className="font-bold text-xl py-2">Form Simple</h3>

<p>
Form demo.&nbsp;
Expand All @@ -24,10 +28,27 @@ export default () => (

<Form onSuccess={onSuccess} onErrors={(errors) => ({ errors })} />

<hr />
<hr className="my-3" />

<h3>Form Generated</h3>
<h3 className="font-bold text-xl py-2">Form Generated</h3>

<FormGenerated onSuccess={onSuccess} onErrors={(errors) => ({ errors })} />
<hr className="my-3" />

<h3 className="font-bold text-xl py-2">Form Free UI</h3>

<FreeUI />

<hr className="my-3" />

<h3 className="font-bold text-xl py-2">Generated Form</h3>

<GeneratedForm />

<hr className="my-3" />

<h3 className="font-bold text-xl py-2">UI for Form Generation</h3>

<FormDefs />
</>
);
Loading

0 comments on commit 590b83d

Please sign in to comment.