Skip to content
Draft
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
133 changes: 133 additions & 0 deletions web-app/app/(profile)/question.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
"use client";

import * as React from "react"
import { Input } from "../../components/ui/input";
import { Label } from "../../components/ui/label";

import { cn } from "@/lib/utils"
import { Textarea } from "../../components/ui/textarea";
import { useState } from "react";

type QuestionProps = {
question: string;
questionDataName: string;
}

type QuestionPropsScale = QuestionProps & {
scaleOptions: any[];
}

// /**
// * The red star next to a required question.
// * @param required Whether or not to display the star.
// */
// function QuestionRequiredStar({ required }: { required: boolean }) {
// if (required) {
// return (
// <span className={cn("text-red-500 ml-1")}>*</span>
// )
// }
// return (<span></span>);
// }

// /**
// * Component with an input (like a radio or checkbox) with a label below it.
// * The width of the label does not effect the width of the component.
// * @param textLabel The label below the option item.
// * @param dataName The name in the form of the response.
// * @param type The type of input (like "checkbox", "radio").
// */
// function QuestionOptionItem({ textLabel, dataName, type }: { textLabel: string, dataName: string, type: string }) {
// return (

// )
// }

/**
* Displays the options for a question and aligns them, along with the question text itself.
* Used to align radio and multiple choice questions.
* @param children The question text component.
* @param items The `QuestionOptionItem`s to select from.
*/
function QuestionScaleContainer({ children, items }: React.ComponentProps<"div"> & { items: any[] }) {
return (<div className="ml-2 mb-9">
<h3 className="mb-1">
{children}
</h3>
<div className="flex gap-10">
{items}
</div>
</div>);
}

/**
* A radio question (select one).
*/
function QuestionScale({ question, questionDataName, scaleOptions }: QuestionPropsScale) {
const items = [];

for (let i = 0; i < scaleOptions.length; i++) {
const id = `${questionDataName}-radio-${question}`;
items.push(
<div id={`${id}-container`} className="relative flex flex-col items-center basis-4 w-sm">
<Input type="radio" name={questionDataName} id={id} className="h-fit" />
<Label className="absolute top-full mt-1 whitespace-nowrap text-neutral-500 text-sm" htmlFor={id}>{scaleOptions[i]}</Label>
</div>
);
}

return (<QuestionScaleContainer items={items}>{question}</QuestionScaleContainer>);
}

/**
* A checkbox question (select multiple).
*/
function QuestionScaleMultiple({ question, questionDataName, scaleOptions }: QuestionPropsScale) {
const items = [];

for (let i = 0; i < scaleOptions.length; i++) {
const id = `${questionDataName}-radio-${question}`;
items.push(
<div id={`${id}-container`} className="relative flex flex-col items-center basis-4 w-sm">
<Input type="checkbox" name={questionDataName} id={id} className="h-fit" />
<Label className="absolute top-full mt-1 whitespace-nowrap text-neutral-500 text-sm" htmlFor={id}>{scaleOptions[i]}</Label>
</div>
)
}

return (<QuestionScaleContainer items={items}>{question}</QuestionScaleContainer>);
}

/**
* A freeform textarea question.
*/
function QuestionFreeform({ question, questionDataName }: QuestionProps) {
return (
<div className="ml-2 mb-9">
<h3 className="mb-1">{question}</h3>
<Textarea name={questionDataName} placeholder=". . ." className="w-xs" />
</div>
);
}

/**
* A yes or no question.
* TODO make it a proper switch. Right now it looks awful.
*/
function QuestionBoolean({ question, questionDataName }: QuestionProps) {

const [ value, setValue ] = useState(false);

return (
<div className="ml-2 mb-9">
<h3 className="mb-1">{question}</h3>
<i className="text-xs text-neutral-500">placeholder for a proper switch component</i>
<Input type="checkbox" className="h-9 w-6" checked={value} onChange={(e) => {
setValue(e.target.checked);
console.log("hello");
}} />
</div>
);
}

export { QuestionScale, QuestionScaleMultiple, QuestionFreeform, QuestionBoolean };
104 changes: 104 additions & 0 deletions web-app/app/(profile)/questions-test/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { QuestionScale, QuestionScaleMultiple, QuestionFreeform, QuestionBoolean } from "@/app/(profile)/question";
import { requireAuth } from "@/lib/auth";

/**
* A testing page for the form components.
*/
export default async function FormTestPage() {
const user = await requireAuth();



return (
<div className="min-h-screen bg-zinc-50 font-sans dark:bg-black p-3">
{/* <div className="max-w-lg mb-4">
<i className="text-sm/3 text-neutral-400">
<QuestionRequiredStar required /> = required question
</i>
</div> */}
<section>
<h2 className="text-lg font-bold">Roommate Habits</h2>
<ol className="list-decimal ml-4">
<li>
<QuestionScale
question="How often are you okay with guests during the day?"
questionDataName="guests-day"
scaleOptions={["Never", "", "", "", "Always"]}
/>
</li>
<li>
<QuestionScale
question="How often are you okay with overnight guests?"
questionDataName="guests-night"
scaleOptions={["Never", "", "", "", "Always"]}
/>
</li>
<li>
<QuestionScale
question="How tidy do you want to keep your dorm/apt?"
questionDataName="cleanliness"
scaleOptions={["Dirty", "", "", "", "Pristine"]}
/>
</li>
<li>
<QuestionScale
question="How comfortable with sharing supplies (like paper towels, tp...) are you?"
questionDataName="sharing"
scaleOptions={["Hardly", "", "", "", "Very"]}
/>
</li>
<li>
<QuestionScale
question="How often do you need privacy?"
questionDataName="privacy"
scaleOptions={["Never", "", "", "", "Always"]}
/>
</li>
<li>
<QuestionScale
question="How often do you need quiet (like studying or meetings)?"
questionDataName="quiet"
scaleOptions={["Never", "", "", "", "Always"]}
/>
</li>
<li>
<QuestionScale
question="When do you wake up?"
questionDataName="wake"
scaleOptions={["Earlier", "6AM", "7AM", "8AM", "9AM", "10AM", "Later"]}
/>
</li>
</ol>
</section>

<section>
<h2 className="text-lg font-bold">Roommate Demographics</h2>
<ol className="list-decimal ml-4">
<li>
<QuestionScaleMultiple
question="What year(s) are you okay to room with?"
questionDataName="years"
scaleOptions={["1st", "2nd", "3rd", "4th", "Grad"]}
/>
</li>
<li>
<QuestionFreeform
question="What languages other than English do you speak?"
questionDataName="language"
/>
</li>
<li>
<QuestionBoolean
question="Are you okay with a smoker?"
questionDataName="smoker"
/>
</li>
</ol>
</section>
<br />
<br />
<br />
<br />
</div>
);
}