the Header is now styled, add TestForm and QualificationSelector

This commit is contained in:
Dawid Wysokiński 2021-03-27 07:48:49 +01:00
parent 2cb1b1d573
commit aa34386e4a
10 changed files with 203 additions and 55 deletions

View File

@ -19,6 +19,7 @@
"graphql-request": "^3.4.0",
"lodash": "^4.17.21",
"next": "10.0.9",
"polish-plurals": "^1.1.0",
"react": "17.0.1",
"react-dom": "17.0.1"
},

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -2,3 +2,8 @@ export const AUTHOR = {
FULL_NAME: 'Dawid Wysokiński',
CONTACT: 'https://dwysokinski.me/#contact',
};
export const QUESTIONS = [1, 40];
export const GOOGLE_PLAY_URL =
'https://play.google.com/store/apps/details?id=com.dawidwysokinski.zdamegzaminzawodowy';

View File

@ -1,3 +1,4 @@
export enum Route {
IndexPage = '/',
TestPage = '/kwalifikacja/[slug]/test/[questions]',
}

View File

@ -18,7 +18,7 @@ interface IndexPageProps {
const IndexPage = ({ qualifications }: IndexPageProps) => {
return (
<Layout transparentTopBar absoluteTopBar padding={false}>
<Layout padding={false}>
<Header qualifications={qualifications} />
</Layout>
);

View File

@ -1,35 +1,22 @@
import { useState } from 'react';
import { Maybe, Qualification } from 'libs/graphql';
import { GOOGLE_PLAY_URL } from 'config/app';
import Image from 'next/image';
import { makeStyles } from '@material-ui/core/styles';
import {
Container,
Toolbar,
Grid,
Typography,
Divider,
TextField,
InputAdornment,
} from '@material-ui/core';
import { Search as SearchIcon } from '@material-ui/icons';
import { Autocomplete } from '@material-ui/lab';
import ThemeProvider from 'libs/material-ui/ThemeProvider';
import { Container, Grid, Typography, Divider } from '@material-ui/core';
import Link from 'common/Link/Link';
import QualificationSelector, {
QualificationSelectorProps,
} from './QualificationSelector';
interface HeaderProps {
qualifications: Qualification[];
qualifications: QualificationSelectorProps['qualifications'];
}
const Header = ({ qualifications = [] }: HeaderProps) => {
const [selectedQualification, setSelectedQualification] = useState<
Maybe<Qualification>
>(null);
const classes = useStyles();
console.log(selectedQualification);
return (
<header className={classes.header}>
<Toolbar />
<Divider />
<Container className={classes.container}>
<div>
@ -44,37 +31,20 @@ const Header = ({ qualifications = [] }: HeaderProps) => {
ubiegłych. Wyszukaj poniżej interesującą Cię kwalifikację i
zacznij rozwiązywać testy!
</Typography>
<ThemeProvider cssBaseline={false} paletteType="dark">
<Autocomplete
getOptionLabel={option => `${option.name} (${option.code})`}
noOptionsText="Nie znaleziono żadnej kwalifikacji"
clearText="Wyczyść"
onChange={(e, value) => {
setSelectedQualification(value);
}}
renderInput={params => {
return (
<TextField
{...params}
fullWidth
label="Wpisz nazwę kwalifikacji lub jej oznaczenie"
placeholder="Na przykład: EE.08"
variant="outlined"
color="secondary"
InputProps={{
...params.InputProps,
startAdornment: (
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
),
}}
/>
);
}}
options={qualifications}
/>
</ThemeProvider>
<QualificationSelector qualifications={qualifications} />
<Divider className={classes.divider} />
<div>
<Link
href={GOOGLE_PLAY_URL}
title="Pobierz aplikację na Androida z Google Play"
>
<img
className={classes.googlePlayBadge}
src="/images/google-play-badge.svg"
alt="Pobierz aplikację na Androida z Google Play"
/>
</Link>
</div>
</Grid>
<Grid item md={5} xs={12} className={classes.imageWrapper}>
<Image
@ -93,9 +63,7 @@ const Header = ({ qualifications = [] }: HeaderProps) => {
const useStyles = makeStyles(theme => ({
header: {
color: theme.palette.common.white,
position: 'relative',
backgroundColor: theme.palette.primary.dark,
overflowX: 'hidden',
},
container: {
@ -104,11 +72,17 @@ const useStyles = makeStyles(theme => ({
justifyContent: 'center',
paddingTop: theme.spacing(3),
paddingBottom: theme.spacing(3),
minHeight: '75vh',
minHeight: '60vh',
},
imageWrapper: {
textAlign: 'center',
},
divider: {
marginTop: theme.spacing(5),
},
googlePlayBadge: {
width: '150px',
},
}));
export default Header;

View File

@ -0,0 +1,65 @@
import { useState } from 'react';
import { Maybe, Qualification } from 'libs/graphql';
import { Autocomplete } from '@material-ui/lab';
import { InputAdornment, TextField } from '@material-ui/core';
import { Search as SearchIcon } from '@material-ui/icons';
import TestForm from './TestForm';
import { makeStyles } from '@material-ui/core/styles';
export interface QualificationSelectorProps {
qualifications: Qualification[];
}
const QualificationSelector = ({
qualifications,
}: QualificationSelectorProps) => {
const [selectedQualification, setSelectedQualification] = useState<
Maybe<Qualification>
>(null);
const classes = useStyles();
return (
<div className={classes.container}>
<Autocomplete
getOptionLabel={option => `${option.name} (${option.code})`}
noOptionsText="Nie znaleziono żadnej kwalifikacji"
clearText="Wyczyść"
onChange={(e, value) => {
setSelectedQualification(value);
}}
renderInput={params => {
return (
<TextField
{...params}
fullWidth
label="Wpisz nazwę kwalifikacji lub jej oznaczenie"
placeholder="Na przykład: EE.08"
variant="outlined"
InputProps={{
...params.InputProps,
startAdornment: (
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
),
}}
/>
);
}}
options={qualifications}
/>
{selectedQualification && (
<TestForm qualification={selectedQualification} />
)}
</div>
);
};
const useStyles = makeStyles(theme => ({
container: {
marginTop: theme.spacing(2),
},
}));
export default QualificationSelector;

View File

@ -0,0 +1,77 @@
import { useState } from 'react';
import { polishPlurals } from 'polish-plurals';
import { Qualification } from 'libs/graphql';
import { QUESTIONS } from 'config/app';
import { Route } from 'config/routing';
import { makeStyles } from '@material-ui/core/styles';
import { Button, MenuItem, TextField, Typography } from '@material-ui/core';
import Link from 'common/Link/Link';
export interface TestFormProps {
qualification: Qualification;
}
const TestForm = ({ qualification }: TestFormProps) => {
const classes = useStyles();
const [howManyQuestions, setHowManyQuestions] = useState(QUESTIONS[0]);
return (
<div className={classes.container}>
<Typography className={classes.note}>
Wybrana przez Ciebie kwalifikacja:{' '}
<strong>
{qualification.name} ({qualification.code})
</strong>
</Typography>
<div className={classes.formContainer}>
<TextField
label="Ilość pytań"
value={howManyQuestions}
className={classes.howManyQuestionsInput}
onChange={e => setHowManyQuestions(parseInt(e.target.value))}
variant="outlined"
select
>
{QUESTIONS.map(question => (
<MenuItem key={question} value={question}>
{question}{' '}
{polishPlurals('pytanie', 'pytania', 'pytań', question)}
</MenuItem>
))}
</TextField>
<Link
title="Rozpocznij test"
href={{
pathname: Route.TestPage,
query: { slug: qualification.slug, questions: howManyQuestions },
}}
>
<Button variant="contained" color="secondary">
Rozpocznij test
</Button>
</Link>
</div>
</div>
);
};
const useStyles = makeStyles(theme => ({
container: {
marginTop: theme.spacing(2),
},
note: {
marginBottom: theme.spacing(1.5),
},
formContainer: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
},
howManyQuestionsInput: {
flex: 1,
marginRight: theme.spacing(1),
},
}));
export default TestForm;

View File

@ -0,0 +1,19 @@
import { gql } from 'graphql-request';
export const QUERY_PROFESSIONS = gql`
query professions($sort: [String!]) {
professions(sort: $sort) {
items {
id
slug
name
qualifications {
id
slug
code
name
}
}
}
}
`;

View File

@ -4620,6 +4620,11 @@ pnp-webpack-plugin@1.6.4:
dependencies:
ts-pnp "^1.1.6"
polish-plurals@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/polish-plurals/-/polish-plurals-1.1.0.tgz#c512cc06df8881c7f199dd12aba197552c3dada8"
integrity sha512-Sect6u4dScUC15pUZGhbfr7Q5o6CRAIpBj/KdkYf27EUa5Ls6+MkK5LXUH3PQL5aPAmFGnmJMXhdXzNLGc5V5A==
popper.js@1.16.1-lts:
version "1.16.1-lts"
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1-lts.tgz#cf6847b807da3799d80ee3d6d2f90df8a3f50b05"