[questions][ui] revamp landing page look

pull/411/head
Jeff Sieu 3 years ago
parent db8379bdc8
commit 1609355544

@ -1,13 +1,15 @@
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { ArrowSmallRightIcon } from '@heroicons/react/24/outline';
import type { QuestionsQuestionType } from '@prisma/client';
import { Button, Select } from '@tih/ui';
import {
COMPANIES,
LOCATIONS,
QUESTION_TYPES,
} from '~/utils/questions/constants';
import { QUESTION_TYPES } from '~/utils/questions/constants';
import useDefaultCompany from '~/utils/questions/useDefaultCompany';
import useDefaultLocation from '~/utils/questions/useDefaultLocation';
import type { FilterChoice } from './filter/FilterSection';
import CompanyTypeahead from './typeahead/CompanyTypeahead';
import LocationTypeahead from './typeahead/LocationTypeahead';
export type LandingQueryData = {
company: string;
@ -22,76 +24,109 @@ export type LandingComponentProps = {
export default function LandingComponent({
onLanded: handleLandingQuery,
}: LandingComponentProps) {
const [landingQueryData, setLandingQueryData] = useState<LandingQueryData>({
company: 'Google',
location: 'Singapore',
questionType: 'CODING',
});
const defaultCompany = useDefaultCompany();
const defaultLocation = useDefaultLocation();
const [company, setCompany] = useState<FilterChoice | undefined>(
defaultCompany,
);
const [location, setLocation] = useState<FilterChoice | undefined>(
defaultLocation,
);
const [questionType, setQuestionType] =
useState<QuestionsQuestionType>('CODING');
const handleChangeCompany = (company: string) => {
setLandingQueryData((prev) => ({ ...prev, company }));
const handleChangeCompany = (newCompany: FilterChoice) => {
setCompany(newCompany);
};
const handleChangeLocation = (location: string) => {
setLandingQueryData((prev) => ({ ...prev, location }));
const handleChangeLocation = (newLocation: FilterChoice) => {
setCompany(newLocation);
};
const handleChangeType = (questionType: QuestionsQuestionType) => {
setLandingQueryData((prev) => ({ ...prev, questionType }));
const handleChangeType = (newQuestionType: QuestionsQuestionType) => {
setQuestionType(newQuestionType);
};
useEffect(() => {
if (company === undefined) {
setCompany(defaultCompany);
}
}, [defaultCompany, company]);
useEffect(() => {
if (location !== undefined) {
setLocation(defaultLocation);
}
}, [defaultLocation, location]);
return (
<main className="flex flex-1 flex-col items-stretch overflow-y-auto bg-white">
<div className="pb-4"></div>
<div className="flex flex-1 flex-col justify-center gap-3">
<main className="flex flex-1 flex-col items-center overflow-y-auto bg-white">
<div className="flex flex-1 flex-col items-start justify-center gap-12 px-4">
<header className="flex flex-col items-start">
<div className="flex items-center justify-center">
<img alt="app logo" className=" h-20 w-20" src="/logo.svg"></img>
<h1 className="text-primary-600 p-4 text-center text-5xl font-bold">
<h1 className="text-3xl font-semibold text-slate-900">
Tech Interview Question Bank
</h1>
<img alt="app logo" className="h-20 w-20" src="/logo.svg"></img>
</div>
<p className="mx-auto max-w-lg p-6 text-center text-xl text-black sm:max-w-3xl">
Get to know the latest SWE interview questions asked by top companies
<p className="mb-2 max-w-lg text-5xl font-semibold text-slate-900 sm:max-w-3xl">
Know the{' '}
<span className="text-primary-700">
latest SWE interview questions
</span>{' '}
asked by top companies.
</p>
<div className="mx-auto flex max-w-lg items-baseline gap-3 p-4 text-center text-xl text-black sm:max-w-3xl">
<p>Find</p>
<div className=" space-x-2">
</header>
<div className="flex flex-col items-start gap-3 text-xl font-semibold text-slate-900">
<p className="text-3xl">Find questions</p>
<div className="grid grid-cols-2">
<p className="text-slate-600">about</p>
<Select
isLabelHidden={true}
label="Type"
options={QUESTION_TYPES}
value={landingQueryData.questionType}
value={questionType}
onChange={(value) => {
handleChangeType(value.toUpperCase() as QuestionsQuestionType);
}}
/>
</div>
<p>questions from</p>
<Select
<p className="text-slate-600">from</p>
<CompanyTypeahead
isLabelHidden={true}
label="Company"
options={COMPANIES}
value={landingQueryData.company}
onChange={handleChangeCompany}
value={company}
onSelect={(value) => {
handleChangeCompany(value);
}}
/>
<p>in</p>
<Select
<p className="text-slate-600">in</p>
<LocationTypeahead
isLabelHidden={true}
label="Location"
options={LOCATIONS}
value={landingQueryData.location}
onChange={handleChangeLocation}
value={location}
onSelect={(value) => {
handleChangeLocation(value);
}}
/>
</div>
<Button
addonPosition="end"
icon={ArrowSmallRightIcon}
label="Go"
size="md"
variant="primary"
onClick={() => handleLandingQuery(landingQueryData)}></Button>
onClick={() => {
if (company !== undefined && location !== undefined) {
return handleLandingQuery({
company: company.value,
location: location.value,
questionType,
});
}
}}
/>
</div>
<div className="flex justify-center p-4">
<div className="flex justify-center">
<iframe
height={30}
src="https://ghbtns.com/github-btn.html?user=yangshun&amp;repo=tech-interview-handbook&amp;type=star&amp;count=true&amp;size=large"

@ -3,15 +3,18 @@ import type { UseFormRegisterReturn } from 'react-hook-form';
import { useForm } from 'react-hook-form';
import { CheckboxInput, Collapsible, RadioList } from '@tih/ui';
export type FilterOption<V extends string = string> = {
checked: boolean;
export type FilterChoice<V extends string = string> = {
id: string;
label: string;
value: V;
};
export type FilterOption<V extends string = string> = FilterChoice<V> & {
checked: boolean;
};
export type FilterChoices<V extends string = string> = ReadonlyArray<
Omit<FilterOption<V>, 'checked'>
FilterChoice<V>
>;
type FilterSectionType<FilterOptions extends Array<FilterOption>> =

@ -89,8 +89,6 @@ export default function ContributeQuestionForm({
render={({ field }) => (
<LocationTypeahead
required={true}
// eslint-disable-next-line @typescript-eslint/no-empty-function
onQueryChange={() => {}}
onSelect={(option) => {
field.onChange(option.value);
}}
@ -143,8 +141,6 @@ export default function ContributeQuestionForm({
render={({ field }) => (
<RoleTypeahead
required={true}
// eslint-disable-next-line @typescript-eslint/no-empty-function
onQueryChange={() => {}}
onSelect={(option) => {
field.onChange(option.value);
}}

@ -59,8 +59,6 @@ export default function CreateQuestionEncounterForm({
isLabelHidden={true}
placeholder="Other location"
suggestedCount={3}
// eslint-disable-next-line @typescript-eslint/no-empty-function
onQueryChange={() => {}}
onSelect={({ value: location }) => {
setSelectedLocation(location);
}}
@ -77,8 +75,6 @@ export default function CreateQuestionEncounterForm({
isLabelHidden={true}
placeholder="Other role"
suggestedCount={3}
// eslint-disable-next-line @typescript-eslint/no-empty-function
onQueryChange={() => {}}
onSelect={({ value: role }) => {
setSelectedRole(role);
}}

@ -5,7 +5,7 @@ import ExpandedTypeahead from './ExpandedTypeahead';
export type LocationTypeaheadProps = Omit<
ExpandedTypeaheadProps,
'label' | 'options'
'label' | 'onQueryChange' | 'options'
>;
export default function LocationTypeahead(props: LocationTypeaheadProps) {
@ -14,6 +14,8 @@ export default function LocationTypeahead(props: LocationTypeaheadProps) {
{...(props as ExpandedTypeaheadProps)}
label="Location"
options={LOCATIONS}
// eslint-disable-next-line @typescript-eslint/no-empty-function
onQueryChange={() => {}}
/>
);
}

@ -5,7 +5,7 @@ import ExpandedTypeahead from './ExpandedTypeahead';
export type RoleTypeaheadProps = Omit<
ExpandedTypeaheadProps,
'label' | 'options'
'label' | 'onQueryChange' | 'options'
>;
export default function RoleTypeahead(props: RoleTypeaheadProps) {
@ -14,6 +14,8 @@ export default function RoleTypeahead(props: RoleTypeaheadProps) {
{...(props as ExpandedTypeaheadProps)}
label="Role"
options={ROLES}
// eslint-disable-next-line @typescript-eslint/no-empty-function
onQueryChange={() => {}}
/>
);
}

@ -0,0 +1,22 @@
import type { FilterChoice } from '~/components/questions/filter/FilterSection';
import { trpc } from '../trpc';
export default function useDefaultCompany(): FilterChoice | undefined {
const { data: companies } = trpc.useQuery([
'companies.list',
{
name: '',
},
]);
const company = companies?.[0];
if (company === undefined) {
return company;
}
return {
id: company.id,
label: company.name,
value: company.id,
};
}

@ -0,0 +1,7 @@
import type { FilterChoice } from '~/components/questions/filter/FilterSection';
import { LOCATIONS } from './constants';
export default function useDefaultLocation(): FilterChoice | undefined {
return LOCATIONS[0];
}
Loading…
Cancel
Save