Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add home info conform #150

Merged
merged 7 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { Form } from '@remix-run/react'
import { Button } from '#/app/components/ui/button.tsx'

Check warning on line 2 in heat-stack/app/components/ui/heat/CaseSummaryComponents/CurrentHeatingSystem.tsx

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

'Button' is defined but never used

import { Input } from '#/app/components/ui/input.tsx'
import { Label } from '#/app/components/ui/label.tsx'

export function CurrentHeatingSystem() {
const titleClass = 'text-5xl font-extrabold tracking-wide'
const subtitleClass = 'text-2xl font-semibold text-zinc-950 mt-9'
const descriptiveClass = 'mt-2 text-sm text-slate-500'
const componentMargin = 'mt-10'
const subtitleClass = 'text-2xl font-semibold text-zinc-950 mt-9'

return (
<div>
Expand Down Expand Up @@ -110,10 +110,7 @@
</div>
</div>

<div>
<h6 className={`${subtitleClass}`}>Heating Fuel Usage</h6>
<Button type="submit">Upload</Button>
</div>

</Form>

{/* removed temporarily for single page app format */}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
import { AnalysisHeader } from './AnalysisHeader.tsx'
import { EnergyUseHistoryChart } from './EnergyUseHistoryChart.tsx'
import { Button } from '#/app/components/ui/button.tsx'

Check warning on line 3 in heat-stack/app/components/ui/heat/CaseSummaryComponents/EnergyUseHistory.tsx

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

`#/app/components/ui/button.tsx` import should occur before import of `./AnalysisHeader.tsx`

import { Form } from '@remix-run/react'

Check warning on line 5 in heat-stack/app/components/ui/heat/CaseSummaryComponents/EnergyUseHistory.tsx

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

`@remix-run/react` import should occur before import of `./AnalysisHeader.tsx`

Check warning on line 5 in heat-stack/app/components/ui/heat/CaseSummaryComponents/EnergyUseHistory.tsx

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

'Form' is defined but never used
import { ErrorList } from "./ErrorList.tsx"

Check warning on line 6 in heat-stack/app/components/ui/heat/CaseSummaryComponents/EnergyUseHistory.tsx

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

'ErrorList' is defined but never used
import { Input } from '#/app/components/ui/input.tsx'
import { Label } from '#/app/components/ui/label.tsx'
import { FieldMetadata, useForm } from '@conform-to/react'


export function EnergyUseHistory() {
const titleClass = 'text-5xl font-extrabold tracking-wide mt-10'
const subtitleClass = 'text-2xl font-semibold text-zinc-950 mt-9'

return (
<div>
<h2 className={`${titleClass}`}>Energy Use History</h2>
<div>
<Button type="submit">Upload</Button>
</div>
<AnalysisHeader />
<EnergyUseHistoryChart />
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export function ErrorList({
id,
errors,
}: {
id?: string
errors?: Array<string> | null
}) {
return errors?.length ? (
<ul id={id} className="flex flex-col gap-1">
{errors.map((error, i) => (
<li key={i} className="text-[10px] text-foreground-destructive">
{error}
</li>
))}
</ul>
) : null
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,63 @@
import { Form } from '@remix-run/react'
// import { Button } from '#/app/components/ui/button.tsx'
import { ErrorList } from "./ErrorList.tsx"
import { Button } from '#/app/components/ui/button.tsx'
import { Input } from '#/app/components/ui/input.tsx'
import { Label } from '#/app/components/ui/label.tsx'
import { FieldMetadata, useForm } from '@conform-to/react'

// /** THE BELOW PROBABLY NEED TO MOVE TO A ROUTE RATHER THAN A COMPONENT, including action function, */
// // import { redirect } from '@remix-run/react'
// import { json, ActionFunctionArgs } from '@remix-run/node'
// import { invariantResponse } from '@epic-web/invariant'
// import { parseWithZod } from '@conform-to/zod'
// import { z } from 'zod'

// const nameMaxLength = 1
// const addressMaxLength = 1

// /** Modeled off the conform example at
// * https://github.com/epicweb-dev/web-forms/blob/b69e441f5577b91e7df116eba415d4714daacb9d/exercises/03.schema-validation/03.solution.conform-form/app/routes/users%2B/%24username_%2B/notes.%24noteId_.edit.tsx#L48 */
// const HomeInformationSchema = z.object({
// name: z.string().max(nameMaxLength),
// address: z.string().max(addressMaxLength),
// livingSpace: z.number().min(1),
// })

// export async function action({ request, params }: ActionFunctionArgs) {
// invariantResponse(params.homeId, 'homeId param is required')

// const formData = await request.formData()
// const submission = parseWithZod(formData, {
// schema: HomeInformationSchema,
// })

// if (!submission.value) {
// return json({ status: 'error', submission } as const, {
// status: 400,
// })
// }
// const { name, address, livingSpace } = submission.value

// // await updateNote({ id: params.noteId, title, content })

// // return redirect(`/inputs1`)
// }
type HomeInformationProps = {fields: {
name: FieldMetadata<string, {
name: string;
address: string;
livingSpace: number;
}, string[]>;
address: FieldMetadata<string, {
name: string;
address: string;
livingSpace: number;
}, string[]>;
livingSpace: FieldMetadata<any>;
}};

export function HomeInformation(props: HomeInformationProps) {

export function HomeInformation() {
const titleClass = 'text-5xl font-extrabold tracking-wide'
const subtitleClass = 'text-2xl font-semibold text-zinc-950 mt-9'
const descriptiveClass = 'mt-2 text-sm text-slate-500'
Expand All @@ -12,18 +66,20 @@ export function HomeInformation() {
<div>
<h2 className={`${titleClass}`}>Home Information</h2>

<Form method="post" action="/homes">
{/* <Form method="post" action="/inputs1"> */}
<div className={`${componentMargin}`}>
<h6 className={`${subtitleClass}`}>Resident/Client</h6>

<div className="mt-4 flex space-x-4">
<div>
<Label htmlFor="firstName">First Name</Label>
<Input name="firstName" id="firstName" type="text" />
</div>
<div>
<Label htmlFor="lastName">Last Name</Label>
<Input name="lastName" id="lastName" type="text" />
<Label htmlFor="name">Name</Label>
<Input name={props.fields.name.name} id="name" type="text" />
<div className="min-h-[32px] px-4 pb-3 pt-1">
<ErrorList
id={props.fields.name.errorId}
errors={props.fields.name.errors}
/>
</div>
</div>
</div>
</div>
Expand All @@ -33,23 +89,13 @@ export function HomeInformation() {

<div className="mt-4 flex space-x-4">
<div>
<Label htmlFor="address">Street address</Label>
<Input name="address" id="address" type="text" />
<Input name="addressTwo" id="adressTwo" type="text" />

<div className="mt-4 flex space-x-4">
<div>
<Label htmlFor="city">City/Town</Label>
<Input name="city" id="city" type="text" />
</div>
<div>
<Label htmlFor="state">State</Label>
<Input name="state" id="state" type="text" />
</div>
<div>
<Label htmlFor="zipcode">Zipcode</Label>
<Input name="zipcode" id="zipcode" type="text" />
</div>
<Label htmlFor="address">Address</Label>
<Input name={props.fields.address.name} id="address" type="text" />
<div className="min-h-[32px] px-4 pb-3 pt-1">
<ErrorList
id={props.fields.address.errorId}
errors={props.fields.address.errors}
/>
</div>
</div>
</div>
Expand All @@ -64,7 +110,13 @@ export function HomeInformation() {

<div className="mt-4 flex space-x-2">
<div>
<Input name="livingArea" id="livingArea" type="number" />
<Input name={props.fields.livingSpace.name} id="livingArea" type="number" />
<div className="min-h-[32px] px-4 pb-3 pt-1">
<ErrorList
id={props.fields.livingSpace.errorId}
errors={props.fields.livingSpace.errors}
/>
</div>
<p className={`${descriptiveClass}`}>
The home's above-grade, conditioned space
</p>
Expand All @@ -74,9 +126,10 @@ export function HomeInformation() {

{/* removed temporarily for single page app format */}
{/* <div>
<Button type="submit">Next ={'>'}</Button>
</div> */}
</Form>
<Button type="submit">Next ={'>'}</Button>
</div> */}

{/* </Form> */}
</div>
)
}
83 changes: 80 additions & 3 deletions heat-stack/app/routes/_heat+/Inputs1.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,86 @@


// Archived 03/19/2024


import { useForm } from '@conform-to/react'
import { HomeInformation } from '../../components/ui/heat/CaseSummaryComponents/HomeInformation.tsx'

/** THE BELOW PROBABLY NEED TO MOVE TO A ROUTE RATHER THAN A COMPONENT, including action function, */
// import { redirect } from '@remix-run/react'
import { json, ActionFunctionArgs } from '@remix-run/node'
import { parseWithZod } from '@conform-to/zod'
import { invariantResponse } from '@epic-web/invariant'
import { Form, redirect, useActionData } from '@remix-run/react'
import { z } from 'zod'
import { ErrorList } from '#app/components/ui/heat/CaseSummaryComponents/ErrorList.tsx'

const nameMaxLength = 50
const addressMaxLength = 100

/** Modeled off the conform example at
* https://github.com/epicweb-dev/web-forms/blob/b69e441f5577b91e7df116eba415d4714daacb9d/exercises/03.schema-validation/03.solution.conform-form/app/routes/users%2B/%24username_%2B/notes.%24noteId_.edit.tsx#L48 */
const HomeInformationSchema = z.object({
name: z.string().min(1).max(nameMaxLength),
address: z.string().min(1).max(addressMaxLength),
livingSpace: z.number().min(1),
})

export async function action({ request, params }: ActionFunctionArgs) {
// Checks if url has a homeId parameter, throws 400 if not there
// invariantResponse(params.homeId, 'homeId param is required')

const formData = await request.formData()
const submission = parseWithZod(formData, {
schema: HomeInformationSchema,
})

if(submission.status !== "success") {
return submission.reply()
// submission.reply({
// // You can also pass additional error to the `reply` method
// formErrors: ['Submission failed'],
// fieldErrors: {
// address: ['Address is invalid'],
// },

// // or avoid sending the the field value back to client by specifying the field names
// hideFields: ['password'],
// }),
// {status: submission.status === "error" ? 400 : 200}
}

// TODO NEXT WEEK
// - [x] Server side error checking/handling
// - [ ] Save to cookie and redirect to next form
// - [ ] Build form #2 and #3
// - [ ] Form errors (if we think of a use case - 2 fields conflicting...)

const { name, address, livingSpace } = submission.value

// await updateNote({ id: params.noteId, title, content })

return redirect(`/inputs1`)
}

export default function Inputs1() {
const lastResult = useActionData<typeof action>()
const [form, fields] = useForm({
lastResult,
onValidate({ formData }) {
return parseWithZod(formData, { schema: HomeInformationSchema })
},
defaultValue: {

},
shouldValidate: 'onBlur',
})

return (
<div>
<HomeInformation />
</div>

<Form id={form.id} method="post" onSubmit={form.onSubmit} action="/inputs1">
<HomeInformation fields={fields} />
<ErrorList id={form.errorId} errors={form.errors} />
</Form>
)
}
Loading
Loading