polish up internship proposal preview
This commit is contained in:
		
							parent
							
								
									5316630a29
								
							
						
					
					
						commit
						fb03b892a2
					
				| @ -1,14 +1,8 @@ | |||||||
| import React, { HTMLProps } from "react"; | import React, { HTMLProps } from "react"; | ||||||
| import { makeStyles } from "@material-ui/core/styles"; | import { useHorizontalSpacing } from "@/styles"; | ||||||
| 
 | 
 | ||||||
| export const Actions = (props: HTMLProps<HTMLDivElement>) => { | export const Actions = (props: HTMLProps<HTMLDivElement>) => { | ||||||
|     const classes = makeStyles(theme => ({ |     const classes = useHorizontalSpacing(1); | ||||||
|         root: { |  | ||||||
|             "& > *": { |  | ||||||
|                 marginRight: theme.spacing(1) |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     }))(); |  | ||||||
| 
 | 
 | ||||||
|     return <div className={ classes.root } { ...props }/> |     return <div className={ classes.root } { ...props }/> | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,9 +1,14 @@ | |||||||
| import { Internship } from "@/data"; | import { Internship, internshipTypeLabels } from "@/data"; | ||||||
| import React from "react"; | import React from "react"; | ||||||
| import { Paper, PaperProps, Typography, TypographyProps } from "@material-ui/core"; | import { Button, Paper, PaperProps, Typography, TypographyProps } from "@material-ui/core"; | ||||||
| import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||||
| import { createStyles, makeStyles } from "@material-ui/core/styles"; | import { createStyles, makeStyles } from "@material-ui/core/styles"; | ||||||
| import classNames from "classnames"; | import classNames from "classnames"; | ||||||
|  | import { Link as RouterLink } from "react-router-dom"; | ||||||
|  | import { route } from "@/routing"; | ||||||
|  | import { Actions } from "@/components/actions"; | ||||||
|  | import { useVerticalSpacing } from "@/styles"; | ||||||
|  | import moment from "moment"; | ||||||
| 
 | 
 | ||||||
| export type ProposalPreviewProps = { | export type ProposalPreviewProps = { | ||||||
|     proposal: Internship; |     proposal: Internship; | ||||||
| @ -16,7 +21,6 @@ const Label = ({ children }: TypographyProps) => { | |||||||
| const useSectionStyles = makeStyles(theme => createStyles({ | const useSectionStyles = makeStyles(theme => createStyles({ | ||||||
|     root: { |     root: { | ||||||
|         padding: theme.spacing(2), |         padding: theme.spacing(2), | ||||||
|         marginTop: theme.spacing(3) |  | ||||||
|     } |     } | ||||||
| })) | })) | ||||||
| 
 | 
 | ||||||
| @ -31,30 +35,19 @@ const Section = ({ children, ...props }: PaperProps) => { | |||||||
| export const ProposalPreview = ({ proposal }: ProposalPreviewProps) => { | export const ProposalPreview = ({ proposal }: ProposalPreviewProps) => { | ||||||
|     const { t } = useTranslation(); |     const { t } = useTranslation(); | ||||||
| 
 | 
 | ||||||
|     return <div className="proposal"> |     const classes = useVerticalSpacing(3); | ||||||
|  | 
 | ||||||
|  |     const duration = moment.duration(proposal.endDate.diff(proposal.startDate)); | ||||||
|  | 
 | ||||||
|  |     return <div className={ classNames("proposal", classes.root) }> | ||||||
|  |         <div> | ||||||
|             <Typography className="proposal__primary">{ proposal.intern.name } { proposal.intern.surname }</Typography> |             <Typography className="proposal__primary">{ proposal.intern.name } { proposal.intern.surname }</Typography> | ||||||
|             <Typography className="proposal__secondary"> |             <Typography className="proposal__secondary"> | ||||||
|                 { t('internship.intern.semester', { semester: proposal.intern.semester }) } |                 { t('internship.intern.semester', { semester: proposal.intern.semester }) } | ||||||
|                 { ", " } |                 { ", " } | ||||||
|                 { t('internship.intern.album', { album: proposal.intern.albumNumber }) } |                 { t('internship.intern.album', { album: proposal.intern.albumNumber }) } | ||||||
|             </Typography> |             </Typography> | ||||||
| 
 |         </div> | ||||||
|         <Section> |  | ||||||
|             <Label>{ t('internship.sections.kind') }</Label> |  | ||||||
|             <Typography className="proposal__primary">{ proposal.type }</Typography> |  | ||||||
|         </Section> |  | ||||||
| 
 |  | ||||||
|         <Section> |  | ||||||
|             <Label>{ t('internship.sections.duration') }</Label> |  | ||||||
|             <Typography className="proposal__primary"> |  | ||||||
|                 { t('internship.date-range', { start: proposal.startDate, end: proposal.endDate }) } |  | ||||||
|             </Typography> |  | ||||||
|             <Typography className="proposal__secondary"> |  | ||||||
|                 { t('internship.duration', { duration: 0 })} |  | ||||||
|                 { ", " } |  | ||||||
|                 { t('internship.hours', { hours: proposal.hours })} |  | ||||||
|             </Typography> |  | ||||||
|         </Section> |  | ||||||
| 
 | 
 | ||||||
|         <Section> |         <Section> | ||||||
|             <Label>{ t('internship.sections.place') }</Label> |             <Label>{ t('internship.sections.place') }</Label> | ||||||
| @ -64,12 +57,39 @@ export const ProposalPreview = ({ proposal }: ProposalPreviewProps) => { | |||||||
|             <Typography className="proposal__secondary"> |             <Typography className="proposal__secondary"> | ||||||
|                 NIP: { proposal.company.nip } |                 NIP: { proposal.company.nip } | ||||||
|             </Typography> |             </Typography> | ||||||
|         </Section> |  | ||||||
| 
 | 
 | ||||||
|         <Section> |  | ||||||
|             <Label>{ t('internship.office') }</Label> |             <Label>{ t('internship.office') }</Label> | ||||||
|             <Typography className="proposal__primary">{ t('internship.address.city', proposal.office.address) }</Typography> |             <Typography className="proposal__primary">{ t('internship.address.city', proposal.office.address) }</Typography> | ||||||
|             <Typography className="proposal__secondary">{ t('internship.address.street', proposal.office.address) }</Typography> |             <Typography className="proposal__secondary">{ t('internship.address.street', proposal.office.address) }</Typography> | ||||||
|         </Section> |         </Section> | ||||||
|  | 
 | ||||||
|  |         <Section> | ||||||
|  |             <Label>{ t('internship.sections.kind') }</Label> | ||||||
|  |             <Typography className="proposal__primary">{ internshipTypeLabels[proposal.type].label }</Typography> | ||||||
|  |         </Section> | ||||||
|  | 
 | ||||||
|  |         <Section> | ||||||
|  |             <Label>{ t('internship.sections.duration') }</Label> | ||||||
|  |             <Typography className="proposal__primary"> | ||||||
|  |                 { t('internship.date-range', { start: proposal.startDate, end: proposal.endDate }) } | ||||||
|  |             </Typography> | ||||||
|  |             <Typography className="proposal__secondary"> | ||||||
|  |                 { t('internship.duration', { duration }) } | ||||||
|  |                 { ", " } | ||||||
|  |                 { t('internship.hours', { hours: proposal.hours }) } | ||||||
|  |             </Typography> | ||||||
|  |         </Section> | ||||||
|  | 
 | ||||||
|  |         <Section> | ||||||
|  |             <Label>{ t('internship.sections.mentor') }</Label> | ||||||
|  |             <Typography className="proposal__primary">{ proposal.mentor.name } { proposal.mentor.surname }</Typography> | ||||||
|  |             <Typography className="proposal__secondary">{ proposal.mentor.email }, { proposal.mentor.phone }</Typography> | ||||||
|  |         </Section> | ||||||
|  | 
 | ||||||
|  |         <Actions> | ||||||
|  |             <Button component={ RouterLink } to={ route("home") } variant="contained" color="primary"> | ||||||
|  |                 { t('go-back') } | ||||||
|  |             </Button> | ||||||
|  |         </Actions> | ||||||
|     </div> |     </div> | ||||||
| } | } | ||||||
|  | |||||||
| @ -182,13 +182,13 @@ export const InternshipForm: React.FunctionComponent<InternshipFormProps> = prop | |||||||
| 
 | 
 | ||||||
|     return ( |     return ( | ||||||
|         <div className="internship-form"> |         <div className="internship-form"> | ||||||
|             <Typography variant="h3" className="section-header">{ t('internship.intern-info') }</Typography> |             <Typography variant="h3" className="section-header">{ t('internship.sections.intern-info') }</Typography> | ||||||
|             <StudentForm student={ sampleStudent }/> |             <StudentForm student={ sampleStudent }/> | ||||||
|             <Typography variant="h3" className="section-header">{ t('internship.kind' )}</Typography> |             <Typography variant="h3" className="section-header">{ t('internship.sections.kind' )}</Typography> | ||||||
|             <InternshipProgramForm internship={ internship } onChange={ setInternship }/> |             <InternshipProgramForm internship={ internship } onChange={ setInternship }/> | ||||||
|             <Typography variant="h3" className="section-header">{ t('internship.duration') }</Typography> |             <Typography variant="h3" className="section-header">{ t('internship.sections.duration') }</Typography> | ||||||
|             <InternshipDurationForm internship={ internship } onChange={ setInternship }/> |             <InternshipDurationForm internship={ internship } onChange={ setInternship }/> | ||||||
|             <Typography variant="h3" className="section-header">{ t('internship.place') }</Typography> |             <Typography variant="h3" className="section-header">{ t('internship.sections.place') }</Typography> | ||||||
|             <CompanyForm internship={ internship } onChange={ setInternship }/> |             <CompanyForm internship={ internship } onChange={ setInternship }/> | ||||||
|             <Actions> |             <Actions> | ||||||
|                 <Button variant="contained" color="primary" onClick={ handleSubmitConfirmation }>{ t("confirm") }</Button> |                 <Button variant="contained" color="primary" onClick={ handleSubmitConfirmation }>{ t("confirm") }</Button> | ||||||
|  | |||||||
| @ -1,9 +1,10 @@ | |||||||
| import { Dispatch, SetStateAction, useEffect, useState } from "react"; | import { Dispatch, SetStateAction, useState } from "react"; | ||||||
| 
 | 
 | ||||||
| export function useProxyState<T>(initial: T, setter: (value: T) => void): [T, Dispatch<SetStateAction<T>>] { | export function useProxyState<T>(initial: T, setter: (value: T) => void): [T, Dispatch<SetStateAction<T>>] { | ||||||
|     const [value, proxy] = useState<T>(initial); |     const [value, proxy] = useState<T>(initial); | ||||||
| 
 | 
 | ||||||
|     useEffect(() => setter(value), [ value ]); |     return [value, (newValue: SetStateAction<T>) => { | ||||||
| 
 |         proxy(newValue); | ||||||
|     return [value, proxy]; |         setter(typeof newValue === "function" ? (newValue as any)(value) : newValue); | ||||||
|  |     }]; | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| import { Internship, InternshipType } from "@/data"; | import { Internship, InternshipType } from "@/data"; | ||||||
| import { Serializable, SerializationTransformer } from "@/serialization/types"; | import { Serializable, SerializationTransformer } from "@/serialization/types"; | ||||||
| import { momentSerializationTransformer } from "@/serialization/moment"; | import { momentSerializationTransformer } from "@/serialization/moment"; | ||||||
|  | import { Moment } from "moment"; | ||||||
| 
 | 
 | ||||||
| export const internshipSerializationTransformer: SerializationTransformer<Internship> = { | export const internshipSerializationTransformer: SerializationTransformer<Internship> = { | ||||||
|     transform: (internship: Internship): Serializable<Internship> => ({ |     transform: (internship: Internship): Serializable<Internship> => ({ | ||||||
| @ -10,8 +11,8 @@ export const internshipSerializationTransformer: SerializationTransformer<Intern | |||||||
|     }), |     }), | ||||||
|     reverseTransform: (serialized: Serializable<Internship>): Internship => ({ |     reverseTransform: (serialized: Serializable<Internship>): Internship => ({ | ||||||
|         ...serialized, |         ...serialized, | ||||||
|         startDate: momentSerializationTransformer.reverseTransform(serialized.startDate), |         startDate: momentSerializationTransformer.reverseTransform(serialized.startDate) as Moment, | ||||||
|         endDate: momentSerializationTransformer.reverseTransform(serialized.endDate), |         endDate: momentSerializationTransformer.reverseTransform(serialized.endDate) as Moment, | ||||||
|         type: serialized.type as InternshipType, |         type: serialized.type as InternshipType, | ||||||
|     }), |     }), | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										1
									
								
								src/styles/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/styles/index.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | export * from "./spacing" | ||||||
| @ -16,3 +16,7 @@ | |||||||
| .proposal__primary { | .proposal__primary { | ||||||
|   font-size: 1.675rem; |   font-size: 1.675rem; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | .proposal__header:not(:first-child) { | ||||||
|  |   margin-top: 1rem; | ||||||
|  | } | ||||||
|  | |||||||
							
								
								
									
										19
									
								
								src/styles/spacing.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/styles/spacing.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | import { createStyles, makeStyles } from "@material-ui/core/styles"; | ||||||
|  | 
 | ||||||
|  | const defaultSpacing: number = 3; | ||||||
|  | 
 | ||||||
|  | export const useVerticalSpacing = makeStyles(theme => createStyles({ | ||||||
|  |     root: { | ||||||
|  |         "& > *:not(:last-child)": { | ||||||
|  |             marginBottom: (spacing: number = defaultSpacing) => theme.spacing(spacing) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | })) | ||||||
|  | 
 | ||||||
|  | export const useHorizontalSpacing = makeStyles(theme => createStyles({ | ||||||
|  |     root: { | ||||||
|  |         "& > *:not(:last-child)": { | ||||||
|  |             marginRight: (spacing: number = defaultSpacing) => theme.spacing(spacing) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | })) | ||||||
| @ -57,7 +57,7 @@ internship: | |||||||
|     semester: semestr {{ semester, roman }} |     semester: semestr {{ semester, roman }} | ||||||
|     album: "numer albumu {{ album }}" |     album: "numer albumu {{ album }}" | ||||||
|   date-range: "{{ start, DD MMMM YYYY }} - {{ end, DD MMMM YYYY }}" |   date-range: "{{ start, DD MMMM YYYY }} - {{ end, DD MMMM YYYY }}" | ||||||
|   duration: "{{ duration, humanize }} tygodni" |   duration: "{{ duration, humanize }}" | ||||||
|   hours: "{{ hours }} godzin" |   hours: "{{ hours }} godzin" | ||||||
|   office: "Oddział / adres" |   office: "Oddział / adres" | ||||||
|   address: |   address: | ||||||
| @ -68,6 +68,7 @@ internship: | |||||||
|     duration: "Czas trwania praktyki" |     duration: "Czas trwania praktyki" | ||||||
|     place: "Miejsce odbywania praktyki" |     place: "Miejsce odbywania praktyki" | ||||||
|     kind: "Rodzaj i program praktyki" |     kind: "Rodzaj i program praktyki" | ||||||
|  |     mentor: "Zakładowy opiekun praktyki" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| steps: | steps: | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user