Added styles for entrie form view: form submission and list submissions components. Some minor code refactors

This commit is contained in:
Dmitriy Shishkov 2020-11-07 03:33:30 +05:00
parent c94dab4a9b
commit 85d7e48e0d
No known key found for this signature in database
GPG Key ID: D76D70029F55183E
30 changed files with 440 additions and 96 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
public/apple-touch-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

9
public/browserconfig.xml Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png" />
<TileColor>#363645</TileColor>
</tile>
</msapplication>
</browserconfig>

BIN
public/favicon-16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 959 B

BIN
public/favicon-32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -2,15 +2,37 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta <meta
name="description" name="description"
content="QuestionForm is an open source alternative to Google Forms" content="QuestionForm is an open source alternative to Google Forms"
/> />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> <link
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> rel="apple-touch-icon"
sizes="180x180"
href="%PUBLIC_URL%/apple-touch-icon.png"
/>
<link
rel="icon"
type="image/png"
sizes="32x32"
href="%PUBLIC_URL%/favicon-32x32.png"
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href="%PUBLIC_URL%/favicon-16x16.png"
/>
<link rel="manifest" href="%PUBLIC_URL%/site.webmanifest" />
<link
rel="mask-icon"
href="%PUBLIC_URL%/safari-pinned-tab.svg"
color="#6df577"
/>
<meta name="msapplication-TileColor" content="#6df577" />
<meta name="theme-color" content="#363645" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/apple-touch-icon.png" />
<link rel="stylesheet" href="/index.css" /> <link rel="stylesheet" href="/index.css" />
<title>QuestionForm</title> <title>QuestionForm</title>

View File

@ -8,18 +8,18 @@
"type": "image/x-icon" "type": "image/x-icon"
}, },
{ {
"src": "logo192.png", "src": "android-chrome-192x192.png",
"type": "image/png", "type": "image/png",
"sizes": "192x192" "sizes": "192x192"
}, },
{ {
"src": "logo512.png", "src": "android-chrome-512x512.png",
"type": "image/png", "type": "image/png",
"sizes": "512x512" "sizes": "512x512"
} }
], ],
"start_url": ".", "start_url": "/",
"display": "standalone", "display": "standalone",
"theme_color": "#000000", "theme_color": "#6df577",
"background_color": "#ffffff" "background_color": "#363645"
} }

BIN
public/mstile-150x150.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,34 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="512.000000pt" height="512.000000pt" viewBox="0 0 512.000000 512.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.11, written by Peter Selinger 2001-2013
</metadata>
<g transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M2265 5108 c-44 -5 -134 -20 -200 -33 -514 -104 -948 -336 -1315
-705 -370 -371 -602 -803 -705 -1315 -34 -172 -45 -289 -45 -495 0 -206 11
-323 45 -495 103 -512 335 -946 705 -1315 356 -357 770 -584 1263 -694 338
-76 753 -76 1097 0 261 58 590 191 802 325 164 104 314 225 458 369 357 356
584 770 694 1263 56 251 73 597 41 857 -95 768 -529 1449 -1191 1868 -304 192
-708 331 -1076 371 -115 13 -459 12 -573 -1z m690 -902 c173 -37 291 -78 450
-156 311 -154 568 -407 724 -715 137 -272 201 -616 172 -925 -39 -400 -186
-725 -448 -987 l-82 -83 32 -23 c126 -93 243 -139 367 -142 l85 -2 3 -148 3
-148 -103 6 c-216 13 -391 84 -559 228 l-56 48 -29 -20 c-61 -42 -245 -129
-344 -164 -57 -19 -160 -48 -229 -62 -117 -25 -144 -27 -371 -27 -229 -1 -253
1 -371 26 -547 118 -982 448 -1219 925 -230 464 -222 1033 21 1503 226 437
648 751 1155 860 163 34 219 39 454 35 195 -3 241 -7 345 -29z"/>
<path d="M2420 3939 c-634 -61 -1129 -503 -1251 -1119 -26 -133 -35 -315 -20
-436 12 -94 35 -212 44 -220 2 -2 28 4 58 15 80 27 224 59 341 76 136 19 434
19 585 0 436 -56 820 -243 1257 -614 l100 -84 77 81 c175 185 296 418 346 670
24 122 24 394 -1 517 -56 282 -178 513 -374 709 -238 237 -534 372 -889 406
-120 11 -149 11 -273 -1z"/>
<path d="M1715 1973 c-105 -8 -202 -27 -289 -54 -53 -16 -96 -32 -96 -35 0
-12 36 -73 72 -122 175 -237 424 -415 717 -512 160 -54 277 -72 451 -73 251
-1 449 48 648 159 l64 36 -34 29 c-425 370 -784 533 -1248 569 -130 10 -199
10 -285 3z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

19
public/site.webmanifest Normal file
View File

@ -0,0 +1,19 @@
{
"name": "",
"short_name": "",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#363645",
"background_color": "#363645",
"display": "standalone"
}

View File

@ -1,5 +1,7 @@
import React from 'react' import React from 'react'
import styles from './main.module.css'
interface IListsProps { interface IListsProps {
variants: { text: string }[] variants: { text: string }[]
name: string name: string
@ -25,6 +27,7 @@ const Lists: React.FC<IListsProps> = ({ variants, name, type, onChange }) => {
type={inputType} type={inputType}
name={name} name={name}
value={el.text} value={el.text}
className={styles.selector}
/> />
{el.text} {el.text}
</label> </label>

View File

@ -0,0 +1,3 @@
.selector {
margin-right: 0.5rem;
}

View File

@ -1,26 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> <svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
<svg xmlns="http://www.w3.org/2000/svg" width="1.70667in" height="1.70667in" viewBox="0 0 512 512"> xmlns:cc="http://creativecommons.org/ns#"
<path id="Selection" fill="#6df577" d="M 240.00,0.21 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
C 240.00,0.21 264.00,0.21 264.00,0.21 xmlns:svg="http://www.w3.org/2000/svg"
264.00,0.21 276.00,0.91 276.00,0.91 xmlns="http://www.w3.org/2000/svg"
300.87,2.65 324.65,8.22 348.00,16.95 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
373.01,26.30 398.45,41.27 419.00,58.25 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
439.59,75.27 457.63,95.40 471.95,118.00 width="512"
534.76,217.17 522.88,344.95 443.09,431.00 height="512"
423.70,451.91 400.58,469.96 375.00,482.75 viewBox="0 0 135.46666 135.46666"
330.78,504.88 295.27,512.57 246.00,512.00 version="1.1"
246.00,512.00 236.00,511.09 236.00,511.09 id="svg8"
215.63,509.66 195.41,505.80 176.00,499.33 inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"
139.83,487.29 108.97,469.02 81.00,443.09 sodipodi:docname="logo.svg">
81.00,443.09 74.17,436.91 74.17,436.91 <defs
31.81,393.29 5.16,336.79 0.91,276.00 id="defs2" />
0.91,276.00 0.00,264.00 0.00,264.00 <sodipodi:namedview
0.00,264.00 0.00,248.00 0.00,248.00 id="base"
0.00,248.00 0.91,236.00 0.91,236.00 pagecolor="#ffffff"
2.95,206.83 10.08,177.63 22.31,151.00 bordercolor="#666666"
51.84,86.67 103.14,38.48 170.00,14.69 borderopacity="1.0"
186.39,8.86 203.75,4.61 221.00,2.28 inkscape:pageopacity="0.0"
221.00,2.28 240.00,0.21 240.00,0.21 Z" /> inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="574.79706"
inkscape:cy="560"
inkscape:document-units="px"
inkscape:current-layer="text845"
inkscape:document-rotation="0"
showgrid="false"
units="px"
inkscape:window-width="1366"
inkscape:window-height="744"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:pagecheckerboard="true"
borderlayer="false" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<circle
style="fill:#6df577;fill-opacity:1;stroke:#000000;stroke-width:0.184432;stroke-miterlimit:4;stroke-dasharray:none"
id="path18"
cx="67.73333"
cy="67.73333"
r="67.641113" />
<g
aria-label="Q"
id="text845"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:116.417px;line-height:1.25;font-family:'URW Gothic';-inkscape-font-specification:'URW Gothic, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583">
<path
d="m 112.61208,104.23006 c -0.6985,0.11642 -1.397,0.11642 -1.74625,0.11642 -3.60893,0 -6.86861,-1.28059 -11.176035,-4.423848 9.313355,-7.916356 14.319295,-19.092388 14.319295,-32.363926 0,-25.495323 -19.55806,-44.354877 -45.984719,-44.354877 -26.659494,0 -46.566801,19.092388 -46.566801,44.587711 0,24.796821 20.605809,44.47129 46.450384,44.47129 9.546194,0 18.510303,-2.56117 25.844574,-7.45068 5.937267,5.47159 10.826782,7.33427 18.859552,7.45068 z M 35.07836,85.603341 c 4.65668,-1.862672 8.032773,-2.444757 13.504372,-2.444757 14.668542,0 25.728157,4.540263 38.184776,15.949129 -5.82085,3.608927 -11.525283,5.238767 -18.859554,5.238767 -8.498442,0 -16.414798,-2.67759 -22.817733,-7.567107 -4.65668,-3.49251 -7.799939,-7.101437 -10.011861,-11.176032 z M 31.469433,78.26907 c -0.931336,-4.307429 -1.280587,-6.519352 -1.280587,-9.779028 0,-21.187894 16.298379,-37.369857 37.602691,-37.369857 21.187894,0 37.486273,15.832712 37.486273,36.438521 0,10.244696 -3.84176,18.859554 -11.758116,26.659493 -4.074596,-3.49251 -7.450688,-6.170101 -10.943198,-8.731275 -9.662611,-6.868603 -20.489392,-10.244696 -32.713178,-10.244696 -6.635768,0 -11.758117,0.814919 -18.393885,3.026842 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:116.417px;font-family:'URW Gothic';-inkscape-font-specification:'URW Gothic, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;stroke-width:0.264583"
id="path1581" />
</g>
</g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -7,6 +7,7 @@ import Lists from '../FormLists'
import { useForm } from './hooks' import { useForm } from './hooks'
import { QuestionT } from '../../types' import { QuestionT } from '../../types'
import { RefetchQuestionsFT, IFormSubmitMutation } from './types' import { RefetchQuestionsFT, IFormSubmitMutation } from './types'
import styles from './main.module.css'
interface IQuestionsFormProps { interface IQuestionsFormProps {
formId: number formId: number
@ -62,52 +63,63 @@ const QuestionsForm: React.FC<IQuestionsFormProps> = ({
{questions.map((el: QuestionT) => { {questions.map((el: QuestionT) => {
if (el.__typename === 'InputQuestion') if (el.__typename === 'InputQuestion')
return ( return (
<li key={el.number}> <li key={el.number} className={styles.question}>
<label> <label
className={styles.questionTitle}
htmlFor={el.title.replace(' ', '_')}
>
{el.title} {el.title}
<input
onChange={(e) =>
changeAnswer(el.number)(e.currentTarget.value)
}
type="text"
/>
</label> </label>
<input
className={styles.textInput}
placeholder="Input"
name={el.title.replace(' ', '_')}
onChange={(e) =>
changeAnswer(el.number)(e.currentTarget.value)
}
type="text"
/>
</li> </li>
) )
if (el.__typename === 'ChoisesQuestion') if (el.__typename === 'ChoisesQuestion')
return ( return (
<li key={el.number}> <li key={el.number} className={styles.question}>
<label> <label className={styles.questionTitle} htmlFor={el.title}>
{el.title} {el.title}
{el.type === 'SELECT' ? (
<select
onChange={(e) => {
const selectValue = el.variants.findIndex(
(val) => val.text === e.currentTarget.value
)
changeAnswer(el.number)(selectValue)
}}
name={el.title}
>
{el.variants.map((option, index) => (
<option key={index}>{option.text}</option>
))}
</select>
) : (
<Lists
variants={el.variants}
onChange={changeAnswer(el.number)}
name={el.title}
type={el.type}
/>
)}
</label> </label>
{el.type === 'SELECT' ? (
<select
className={styles.select}
onChange={(e) => {
const selectValue = el.variants.findIndex(
(val) => val.text === e.currentTarget.value
)
changeAnswer(el.number)(selectValue)
}}
name={el.title.replace(' ', '_')}
>
{el.variants.map((option, index) => (
<option key={index}>{option.text}</option>
))}
</select>
) : (
<Lists
variants={el.variants}
onChange={changeAnswer(el.number)}
name={el.title.replace(' ', '_')}
type={el.type}
/>
)}
</li> </li>
) )
return <li>Unknown question type</li> return <li className={styles.question}>Unknown question type</li>
})} })}
</ul> </ul>
{submitLoading ? <p>Uploading...</p> : <input type="submit" />} {submitLoading ? (
<p>Uploading...</p>
) : (
<input className={styles.button} type="submit" />
)}
</form> </form>
{submitError && <p>{submitError.message}</p>} {submitError && <p>{submitError.message}</p>}
{submitData?.formSubmit.success && <p>Successfully uploaded</p>} {submitData?.formSubmit.success && <p>Successfully uploaded</p>}

View File

@ -0,0 +1,56 @@
.question {
list-style: none;
padding-bottom: 1rem;
}
.questionTitle {
padding-bottom: 0.5rem;
display: block;
font-weight: bold;
font-size: 1.3rem;
}
.textInput {
height: 2.3rem;
border-radius: 100vh;
border: none;
outline: none;
font-size: 1.2rem;
padding: 0 0.7rem;
width: 100%;
border-bottom: 0.15rem var(--containerColor) solid;
transition: border 0.1s;
}
.textInput:focus {
border-bottom-width: 0rem;
border-top: 0.15rem var(--containerColor) solid;
}
.select {
/* -webkit-appearance: none; */
/* -moz-appearance: none; */
/* appearance: none; */
padding: 0.5rem;
background: var(--accentColor);
border-radius: 20px;
color: #ffffff;
}
.button {
height: 2.3rem;
border-radius: 100vh;
border: none;
outline: none;
font-size: 1.2rem;
padding: 0 0.7rem;
width: 100%;
cursor: pointer;
background-color: var(--accentColor);
color: var(--onAccentFontColor);
box-shadow: 0 1px 6px 0 var(--accentShadowColor);
}
.button:active {
box-shadow: none;
}

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 32.055 32.055" xml:space="preserve">
<g>
<path style="fill:#363645" d="M3.968,12.061C1.775,12.061,0,13.835,0,16.027c0,2.192,1.773,3.967,3.968,3.967c2.189,0,3.966-1.772,3.966-3.967
C7.934,13.835,6.157,12.061,3.968,12.061z M16.233,12.061c-2.188,0-3.968,1.773-3.968,3.965c0,2.192,1.778,3.967,3.968,3.967
s3.97-1.772,3.97-3.967C20.201,13.835,18.423,12.061,16.233,12.061z M28.09,12.061c-2.192,0-3.969,1.774-3.969,3.967
c0,2.19,1.774,3.965,3.969,3.965c2.188,0,3.965-1.772,3.965-3.965S30.278,12.061,28.09,12.061z" />
</g>
<g></g>
<g></g>
<g></g>
<g></g>
<g></g>
<g></g>
<g></g>
<g></g>
<g></g>
<g></g>
<g></g>
<g></g>
<g></g>
<g></g>
<g></g>
</svg>

After

Width:  |  Height:  |  Size: 969 B

View File

@ -7,6 +7,9 @@ import {
ChoisesQuestion, ChoisesQuestion,
Question, Question,
} from '../../apollo/typeDefs.gen' } from '../../apollo/typeDefs.gen'
import emptyIcon from './empty.svg'
import styles from './main.module.css'
import { getDateCreated } from '../../utils'
interface ISubmissionListProps { interface ISubmissionListProps {
submissions: FormSubmission[] submissions: FormSubmission[]
@ -20,27 +23,31 @@ const SubmissionList: React.FC<ISubmissionListProps> = ({
return submissions.length > 0 ? ( return submissions.length > 0 ? (
<ul> <ul>
{submissions.map((submission, submissionIndex) => ( {submissions.map((submission, submissionIndex) => (
<li key={submissionIndex}> <li className={styles.listItem} key={submissionIndex}>
<h2> <h2 className={styles.itemHeader}>
User: {submission.user ? submission.user.name : 'No submitter'} {`User ${
submission.user ? submission.user.name : 'No submitter'
} submitted on ${getDateCreated(submission.date)}:`}
</h2> </h2>
<ul> <ul>
{submission.answers.map( {submission.answers.map(
(answer: InputAnswer | ChoiseAnswer, answerIndex) => ( (answer: InputAnswer | ChoiseAnswer, answerIndex) => (
<li key={answerIndex}> <li key={answerIndex}>
<h3>{questions![answerIndex].title}</h3> <div className={styles.question}>
{answer.__typename === 'ChoiseAnswer' && ( <h3>{questions[answerIndex].title}</h3>
<h4> {answer.__typename === 'ChoiseAnswer' && (
{ <p>
(questions![answerIndex] as ChoisesQuestion).variants[ {
answer.userChoise (questions[answerIndex] as ChoisesQuestion).variants[
].text answer.userChoise
} ].text
</h4> }
)} </p>
{answer.__typename === 'InputAnswer' && ( )}
<h4>{answer.userInput}</h4> {answer.__typename === 'InputAnswer' && (
)} <p>{answer.userInput}</p>
)}
</div>
</li> </li>
) )
)} )}
@ -49,7 +56,12 @@ const SubmissionList: React.FC<ISubmissionListProps> = ({
))} ))}
</ul> </ul>
) : ( ) : (
<p>No submissions yet</p> <div className={styles.emptyContainer}>
<div className={styles.emptyIconContainer}>
<img className={styles.emptyIcon} src={emptyIcon} alt="Empty" />
</div>
<h3>No submissions yet :(</h3>
</div>
) )
} }

View File

@ -0,0 +1,42 @@
.listItem {
list-style-type: none;
border: 0.1rem var(--containerColor) solid;
border-radius: 20px;
padding: 2.3rem;
}
.itemHeader {
text-decoration: underline wavy;
text-underline-offset: 0.5rem;
padding-bottom: 2.3rem;
}
.question {
display: flex;
gap: 0.5rem;
padding: 0.5rem 0;
}
.emptyContainer {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
flex-grow: 1;
}
.emptyIconContainer {
height: 3.5rem;
overflow: hidden;
}
.emptyIcon {
height: 7rem;
margin-top: -1.75rem;
}
@media (orientation: portrait) {
.question {
flex-direction: column;
}
}

View File

@ -4,6 +4,7 @@ import {
InputAnswer, InputAnswer,
ChoiseAnswer, ChoiseAnswer,
Form, Form,
User,
} from './apollo/typeDefs.gen' } from './apollo/typeDefs.gen'
export type QuestionT = InputQuestion | ChoisesQuestion export type QuestionT = InputQuestion | ChoisesQuestion
@ -13,3 +14,9 @@ export type AnswerT = InputAnswer | ChoiseAnswer
export interface IFormQuery { export interface IFormQuery {
form: Form form: Form
} }
export type GetDateCreatedFT = (dateString: string) => string
export interface IUserQuery {
user: User
}

View File

@ -9,7 +9,7 @@ import styles from './main.module.css'
import QuestionsForm from '../../components/QuestionsForm' import QuestionsForm from '../../components/QuestionsForm'
import { IFormQuery } from '../../types' import { IFormQuery } from '../../types'
import { useId } from './hooks' import { useId } from './hooks'
import { getDateCreated } from './utils' import { getDateCreated } from '../../utils'
const DoForm: React.FC = () => { const DoForm: React.FC = () => {
const id = useId() const id = useId()
@ -44,7 +44,7 @@ const DoForm: React.FC = () => {
<div className={styles.mainTop}></div> <div className={styles.mainTop}></div>
{form.submissions ? ( {form.submissions ? (
<> <>
<h1>Submissions</h1> <h1 className={styles.mainHeader}>Submissions</h1>
<SubmissionList <SubmissionList
submissions={form.submissions} submissions={form.submissions}
questions={form.questions!} questions={form.questions!}
@ -52,7 +52,7 @@ const DoForm: React.FC = () => {
</> </>
) : ( ) : (
<> <>
<h1>Questions</h1> <h1 className={styles.mainHeader}>Questions</h1>
<QuestionsForm <QuestionsForm
formId={id} formId={id}
questions={data!.form.questions!} questions={data!.form.questions!}

View File

@ -7,6 +7,7 @@
.header { .header {
padding: 2.3rem; padding: 2.3rem;
display: grid; display: grid;
gap: 1rem;
grid-template: grid-template:
'title title' auto 'title title' auto
'date author' auto / auto auto; 'date author' auto / auto auto;
@ -33,6 +34,8 @@
flex-grow: 1; flex-grow: 1;
padding: 2.3rem; padding: 2.3rem;
padding-top: 0; padding-top: 0;
display: flex;
flex-direction: column;
} }
.mainTop { .mainTop {
@ -46,3 +49,7 @@
left: 0rem; left: 0rem;
width: 100vw; width: 100vw;
} }
.mainHeader {
padding-bottom: 2.3rem;
}

View File

@ -1 +0,0 @@
export type GetDateCreatedFT = (dateString: string) => string

View File

@ -1,19 +1,22 @@
import React from 'react' import React from 'react'
import { useQuery } from '@apollo/client' import { useQuery } from '@apollo/client'
import { generateFromString } from 'generate-avatar' import { generateFromString } from 'generate-avatar'
import { Redirect } from 'react-router-dom' import { Redirect, useHistory } from 'react-router-dom'
import Card from '../../components/Card' import Card from '../../components/Card'
import { USER } from '../../apollo' import { USER } from '../../apollo'
import { QueryUserArgs, User } from '../../apollo/typeDefs.gen' import { QueryUserArgs } from '../../apollo/typeDefs.gen'
import styles from './main.module.css' import styles from './main.module.css'
import { IUserQuery } from '../../types'
interface IUserQuery { import { logOut } from './utils'
user: User
}
const Home: React.FC = () => { const Home: React.FC = () => {
let { data, error, loading } = useQuery<IUserQuery, QueryUserArgs>(USER) let { data, error, loading, refetch } = useQuery<IUserQuery, QueryUserArgs>(
USER
)
const history = useHistory()
if (loading) return <p>Loading...</p> if (loading) return <p>Loading...</p>
if (error?.message === 'Authorization required') if (error?.message === 'Authorization required')
@ -35,6 +38,12 @@ const Home: React.FC = () => {
alt="Userpic" alt="Userpic"
/> />
<h1>{user.name}</h1> <h1>{user.name}</h1>
<button
className={styles.button}
onClick={() => logOut(refetch, history)}
>
Log out
</button>
</div> </div>
</div> </div>

View File

@ -64,6 +64,24 @@
width: 100%; width: 100%;
} }
.button {
height: 2.3rem;
border-radius: 100vh;
border: none;
outline: none;
font-size: 1.2rem;
padding: 0 0.7rem;
cursor: pointer;
width: 100%;
background-color: var(--accentColor);
color: var(--onAccentFontColor);
box-shadow: 0 1px 6px 0 var(--accentShadowColor);
}
.button:active {
box-shadow: none;
}
@media (orientation: portrait) { @media (orientation: portrait) {
.container { .container {
grid-template-columns: auto; grid-template-columns: auto;

11
src/views/Home/types.ts Normal file
View File

@ -0,0 +1,11 @@
import { QueryUserArgs } from '../../apollo/typeDefs.gen'
import { ApolloQueryResult } from '@apollo/client'
import { IUserQuery } from '../../types'
import { History } from 'history'
export type LogOutFT = (
refetch: (
variables?: Partial<QueryUserArgs> | undefined
) => Promise<ApolloQueryResult<IUserQuery>>,
history: History
) => void

7
src/views/Home/utils.ts Normal file
View File

@ -0,0 +1,7 @@
import { LogOutFT } from './types'
export const logOut: LogOutFT = (refetch, history) => {
localStorage.removeItem('token')
refetch()
history.push('/')
}

View File

@ -50,13 +50,15 @@
.input { .input {
border-bottom: 0.15rem var(--containerColor) solid !important; border-bottom: 0.15rem var(--containerColor) solid !important;
transition: border-bottom 0.1s; transition: border 0.1s;
} }
.input:focus { .input:focus {
border-bottom-width: 0rem !important; border-bottom-width: 0rem !important;
border-top: 0.15rem var(--containerColor) solid !important;
} }
.button { .button {
cursor: pointer;
background-color: var(--accentColor); background-color: var(--accentColor);
color: var(--onAccentFontColor); color: var(--onAccentFontColor);
box-shadow: 0 1px 6px 0 var(--accentShadowColor); box-shadow: 0 1px 6px 0 var(--accentShadowColor);