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

feat: limit textarea characters #79

Merged
merged 12 commits into from
Aug 6, 2024
399 changes: 203 additions & 196 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"@types/react": "^18.2.64",
"@types/react-dom": "^18.2.21",
"astro": "^4.3.6",
"firebase": "^10.8.1",
"firebase": "^10.12.4",
"i": "^0.3.7",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
116 changes: 73 additions & 43 deletions src/components/DataForm.tsx
Original file line number Diff line number Diff line change
@@ -1,52 +1,82 @@
import React, { useState } from "react"
import DataTable from "../components/DataTable"
import DownloadModal from "../components/DownloadModal"
import { Controller, type SubmitHandler, useForm } from "react-hook-form"
import * as Form from "@radix-ui/react-form"
import { addHistoryData } from "../firebase"
import { Input } from "./Input.tsx"
import { Textarea } from "./Textarea.tsx"
import Button from "./Button.tsx"

export interface FileItem {
title: string
cat: string
file: string
description?: string
selected: boolean
export interface Inputs {
name: string
institution: string
email: string
description: string
}

interface DataFormProps {
allFiles: {
data: {
title: string
cat: string
file: string
description?: string
}
}[]
}

const DataForm: React.FC<DataFormProps> = ({ allFiles }) => {
const [files, setFiles] = useState(
allFiles.map((file) => {
return { ...file.data, selected: false }
})
)
const DataForm = () => {
const { handleSubmit, control, register } = useForm<Inputs>()

/**
* Given a target file name and new `selected` field for that file, update the matching file object in{@link files}
* with the new value for `selected`.
*/
const updateFileList = ({ file: targetFile }: FileItem, selection: boolean) => {
setFiles((prevFiles) => {
return prevFiles.map(({ file, selected, ...rest }) => {
return file === targetFile
? { file, selected: selection, ...rest }
: { file, selected, ...rest }
})
})
const onSubmit: SubmitHandler<Inputs> = async (data) => {
await addHistoryData(data)
window.location.replace("https://repository.library.brown.edu/studio/item/bdr:p54c6u36/")
}

return (
<div className="space-y-4">
<DownloadModal filesToDownload={files.map((file) => file.file)} />
<DataTable allFiles={files} updateFileList={updateFileList} />
</div>
<Form.Root
className="p-6 rounded outline outline-neutral-100 outline-1 shadow-md space-y-4"
onSubmit={handleSubmit(onSubmit)}
>
<Controller
name="name"
control={control}
render={() => (
<Input label="Name" placeholder="Heather Yu" {...register("name")} required />
)}
/>
<Controller
name="institution"
control={control}
render={() => (
<Input
label="Institution"
placeholder="Brown University"
{...register("institution")}
required
/>
)}
/>
<Controller
name="email"
control={control}
render={() => (
<Input
label="Email"
placeholder="[email protected]"
match="typeMismatch"
errorMessage="Please provide a valid email"
{...register("email")}
required
/>
)}
/>
<Controller
name="description"
control={control}
render={() => (
<Textarea
label="Description"
placeholder="Why you need this file..."
{...register("description")}
required
/>
)}
/>

<Form.Submit asChild>
<Button>
<span>Submit</span>
</Button>
</Form.Submit>
</Form.Root>
)
}

export default DataForm
9 changes: 8 additions & 1 deletion src/components/DataTable.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import React, { useState } from "react"
import * as Checkbox from "@radix-ui/react-checkbox"
import { CheckIcon } from "@radix-ui/react-icons"
import type { FileItem } from "./DataForm.tsx"

export interface FileItem {
title: string
cat: string
file: string
description?: string
selected: boolean
}

type updateFileListType = (fileToUpdate: FileItem, selection: boolean) => void

Expand Down
138 changes: 0 additions & 138 deletions src/components/DownloadModal.tsx

This file was deleted.

13 changes: 7 additions & 6 deletions src/components/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ export const Input = React.forwardRef<HTMLInputElement, InputProps>(
return (
<Form.Field name={name} className="flex flex-col gap-2">
<Form.Label>{label}</Form.Label>
<Form.Control asChild>
<div className="flex items-center gap-2 bg-white rounded-full shadow-inner min-w-60 w-max py-3 px-5 focus-within:shadow-inner-focus">
<span className="text-neutral-300 w-5 h-5">{icon}</span>
<div className="flex items-center gap-2 bg-white rounded-full shadow-inner min-w-60 w-max py-3 px-5 focus-within:shadow-inner-focus">
{icon && <span className="text-neutral-300 w-5 h-5">{icon}</span>}

<Form.Control asChild>
<input {...delegated} ref={ref} />
</div>
</Form.Control>
<Form.Message className="text-primary-300" match="valueMissing">
</Form.Control>
</div>
<Form.Message className="px-2 text-primary-300" match="valueMissing">
Please enter your {label}
</Form.Message>
{match !== undefined && (
Expand Down
44 changes: 27 additions & 17 deletions src/components/Textarea.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react"
import React, { useState } from "react"
import * as Form from "@radix-ui/react-form"

interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
Expand All @@ -7,20 +7,30 @@ interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement
}

export const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
({ name, label, ...delegated }, ref) => (
<Form.Field name={name} className="flex flex-col gap-2">
<Form.Label>{label}</Form.Label>
<Form.Control asChild>
<textarea
rows={4}
className="text-gray-400 text-sm font-medium outline-none border-b-2 w-full"
{...delegated}
ref={ref}
/>
</Form.Control>
<Form.Message className="text-primary-300" match="valueMissing">
Please enter your {label}
</Form.Message>
</Form.Field>
)
({ name, label, ...delegated }, ref) => {
const [characterCount, setCharacterCount] = useState(0)
const maxLength = 300

return (
<Form.Field name={name} className="relative flex flex-col gap-2">
<Form.Label>{label}</Form.Label>
<span className="px-2 py-1 text-xs text-neutral-300 rounded absolute top-9 right-1">
{characterCount}/{maxLength}
</span>
<Form.Control asChild>
<textarea
rows={4}
maxLength={maxLength}
className="text-gray-400 text-sm font-medium outline-none border-b-2 w-full py-6"
{...delegated}
ref={ref}
onChange={(e) => setCharacterCount(e.target.value.length)}
/>
</Form.Control>
<Form.Message className="text-primary-300 px-2" match="valueMissing">
Please enter your {label}
</Form.Message>
</Form.Field>
)
}
)
6 changes: 5 additions & 1 deletion src/content/pages/data.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@
title: Data
---

Instructions to users
## Accessing the Data

After submitting this form, you will be redirected to the Brown Digital Repository to download the data.

The data is currently available for SPSS and STATA file formats.
8 changes: 8 additions & 0 deletions src/firebase-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"apiKey": "AIzaSyBaGckKaSh8Kg7h6QnucrxP5pKPSETFRLE",
"authDomain": "mmp-site-b1c9b.firebaseapp.com",
"projectId": "mmp-site-b1c9b",
"storageBucket": "mmp-site-b1c9b.appspot.com",
"messagingSenderId": "364364593490",
"appId": "1:364364593490:web:9636e89bda12afe7f2a28b"
}
Loading