diff --git a/package.json b/package.json
index d48b98e..83556ed 100644
--- a/package.json
+++ b/package.json
@@ -13,7 +13,6 @@
"@types/node": "^12.0.0",
"@types/react": "^16.9.0",
"@types/react-dom": "^16.9.0",
- "formik": "^2.1.4",
"moment": "^2.26.0",
"react": "^16.13.1",
"react-dom": "^16.13.1",
diff --git a/src/App.tsx b/src/App.tsx
index f6ed80e..1ec6596 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,14 +1,21 @@
import React from 'react';
-import { Container } from "@material-ui/core";
+import { Container, ThemeProvider, Typography } from "@material-ui/core";
import { CompanyForm } from "./forms/company";
+import { studentTheme } from "./ui/theme";
function App() {
return (
-
-
-
-
-
+
+
+
+ Zgłoszenie Praktyki
+ UX Demo
+
+ Miejsce odbywania praktyki
+
+
+
+
);
}
diff --git a/src/data/common.ts b/src/data/common.ts
new file mode 100644
index 0000000..62671b8
--- /dev/null
+++ b/src/data/common.ts
@@ -0,0 +1,3 @@
+export interface Identifiable {
+ id?: string
+}
diff --git a/src/data/company.ts b/src/data/company.ts
index c73333d..5e6f2db 100644
--- a/src/data/company.ts
+++ b/src/data/company.ts
@@ -1,3 +1,5 @@
+import { Identifiable } from "./common";
+
export interface Address {
street: string;
building: string;
@@ -6,14 +8,14 @@ export interface Address {
country: string;
}
-export interface Company {
+export interface Company extends Identifiable {
name: string;
url?: string;
nip: string;
offices: BranchOffice[];
}
-export interface BranchOffice {
+export interface BranchOffice extends Identifiable {
address: Address;
}
@@ -24,4 +26,16 @@ export const emptyCompany: Company = {
nip: "",
}
+export const emptyAddress: Address = {
+ street: "",
+ city: "",
+ country: "",
+ postalCode: "",
+ building: ""
+}
+
+export const emptyBranchOffice: BranchOffice = {
+ address: emptyAddress,
+}
+
export const formatAddress = ({ postalCode, building, street, city, country }: Address): string => `${street} ${building}, ${postalCode} ${city}, ${country}`
diff --git a/src/forms/company.tsx b/src/forms/company.tsx
index 4ff47bf..78729e1 100644
--- a/src/forms/company.tsx
+++ b/src/forms/company.tsx
@@ -1,69 +1,139 @@
-import React, { HTMLProps, useState } from "react";
-import { useFormik } from "formik";
-import { Nullable } from "../helpers";
-import { formatAddress, Company, emptyCompany, BranchOffice } from "../data/company";
+import React, { HTMLProps, useEffect, useMemo, useState } from "react";
+import { BranchOffice, Company, emptyAddress, emptyBranchOffice, emptyCompany, formatAddress } from "../data/company";
import { sampleCompanies } from "../provider/company";
import { Autocomplete } from "@material-ui/lab";
-import { Box, Grid, TextField, Typography } from "@material-ui/core";
+import { Grid, TextField, Typography } from "@material-ui/core";
+import { formFieldProps } from "./helpers";
-export type CompanyFormProps = {
+export type CompanyFormProps = {}
+export type BranchOfficeProps = {
+ company: Company,
+ disabled?: boolean
}
export const CompanyItem = ({ company, ...props }: { company: Company } & HTMLProps) => (
-
+
{ company.name }
NIP: { company.nip }
)
export const OfficeItem = ({ office, ...props }: { office: BranchOffice } & HTMLProps
) => (
-
-
{ office.address.city }, { office.address.street }
+
+
{ office.address.city }
{ formatAddress(office.address) }
)
-export const CompanyForm: React.FunctionComponent
= props => {
- const formik = useFormik>({ onSubmit: values => console.log(values), initialValues: emptyCompany });
+export const BranchForm: React.FC = ({ company, disabled = false }) => {
+ const [office, setOffice] = useState(emptyBranchOffice)
- const formikProps = (prop: keyof Company) => ({ onChange: formik.handleChange, value: formik.values[prop], name: prop })
+ const canEdit = useMemo(() => !office.id && !disabled, [office.id, disabled]);
- const [company, setCompany] = useState(null);
+ const fieldProps = formFieldProps(office.address, address => setOffice({ ...office, address }))
+
+ const handleCityChange = (event: any, value: BranchOffice | string | null) => {
+ if (typeof value === "string") {
+ setOffice({
+ ...emptyBranchOffice,
+ address: {
+ ...emptyAddress,
+ city: value,
+ }
+ });
+ } else if (typeof value === "object" && value !== null) {
+ setOffice(value);
+ } else {
+ setOffice(emptyBranchOffice);
+ }
+ }
+
+ const handleCityInput = (event: any, value: string) => {
+ const base = office.id ? emptyBranchOffice : office;
+ setOffice({
+ ...base,
+ address: {
+ ...base.address,
+ city: value,
+ }
+ })
+ }
+
+ useEffect(() => void (office.id && setOffice(emptyBranchOffice)), [company])
return (
-
-
- option.name }
- renderOption={ company => }
- renderInput={ props => }
- onChange={ (ev, value: Company | null) => {
- setCompany(value)
-
- formik.setFieldValue("name", value?.name || "")
- formik.setFieldValue("url", value?.url || "");
- formik.setFieldValue("nip", value?.nip || "");
- } }
- />
-
-
-
-
-
-
-
-
-
-
+
+
office.address.city }
- renderOption={ office => }
- renderInput={ props => }
+ disabled={ disabled }
+ getOptionLabel={ office => typeof office == "string" ? office : office.address.city }
+ renderOption={ office => }
+ renderInput={ props => }
+ onChange={ handleCityChange }
+ onInputChange={ handleCityInput }
+ inputValue={ office.address.city }
+ value={ office.id ? office : null }
+ freeSolo
/>
+
+
+
+
+
+
+
+
+
+
+
+
)
}
+export const CompanyForm: React.FunctionComponent = props => {
+ const [company, setCompany] = useState(emptyCompany);
+ const canEdit = useMemo(() => !company.id, [company.id]);
+
+ const fieldProps = formFieldProps(company, setCompany)
+
+ const handleCompanyChange = (event: any, value: Company | string | null) => {
+ if (typeof value === "string") {
+ setCompany({
+ ...emptyCompany,
+ name: value,
+ });
+ } else if (typeof value === "object" && value !== null) {
+ setCompany(value);
+ } else {
+ setCompany(emptyCompany);
+ }
+ }
+
+ return (
+ <>
+
+
+ option.name }
+ renderOption={ company => }
+ renderInput={ props => }
+ onChange={ handleCompanyChange }
+ freeSolo
+ />
+
+
+
+
+
+
+
+
+ Oddział
+
+ >
+ )
+}
+
diff --git a/src/forms/helpers.ts b/src/forms/helpers.ts
new file mode 100644
index 0000000..4fafb88
--- /dev/null
+++ b/src/forms/helpers.ts
@@ -0,0 +1,20 @@
+import { DOMEvent } from "../helpers";
+
+type UpdatingEvent = "onBlur" | "onChange" | "onInput";
+type FormFieldHelperOptions = {
+ event: UpdatingEvent
+}
+
+export function formFieldProps(subject: T, update: (value: T) => void, options: Partial> = {}) {
+ const {
+ event = "onChange"
+ } = options;
+
+ return (field: keyof T) => ({
+ value: subject[field],
+ [event]: (event: DOMEvent) => update({
+ ...subject,
+ [field]: event.target.value,
+ } as T)
+ })
+}
diff --git a/src/helpers.ts b/src/helpers.ts
index 157ce58..e128e6c 100644
--- a/src/helpers.ts
+++ b/src/helpers.ts
@@ -1 +1,5 @@
export type Nullable = { [P in keyof T]: T[P] | null }
+
+export interface DOMEvent extends Event {
+ target: TTarget;
+}
diff --git a/src/provider/company.ts b/src/provider/company.ts
index e0379f0..be861f9 100644
--- a/src/provider/company.ts
+++ b/src/provider/company.ts
@@ -1,11 +1,17 @@
import { Company } from "../data/company";
+import { makeIdSequence } from "./helpers";
+
+const companySequence = makeIdSequence();
+const officeSequence = makeIdSequence();
export const sampleCompanies: Company[] = [
{
+ id: companySequence(),
name: "Intel",
url: "https://www.intel.com/content/www/us/en/jobs/locations/poland.html",
nip: "9570752316",
offices: [{
+ id: officeSequence(),
address: {
city: "Gdańsk",
street: "ul. Słowackiego",
@@ -16,10 +22,12 @@ export const sampleCompanies: Company[] = [
}]
},
{
+ id: companySequence(),
name: "IHS Markit",
url: "http://ihsgdansk.com/",
nip: "5842068320",
offices: [{
+ id: officeSequence(),
address: {
city: "Gdańsk",
street: "ul. Marynarki Polskiej",
@@ -30,10 +38,12 @@ export const sampleCompanies: Company[] = [
}]
},
{
+ id: companySequence(),
name: "Asseco Poland",
url: "http://pl.asseco.com/",
nip: "5842068320",
offices: [{
+ id: officeSequence(),
address: {
city: "Gdynia",
street: "ul. Podolska",
@@ -42,6 +52,7 @@ export const sampleCompanies: Company[] = [
country: "Poland"
}
}, {
+ id: officeSequence(),
address: {
city: "Łódź",
street: "al. Marszałka Józefa Piłsudskiego",
@@ -50,6 +61,7 @@ export const sampleCompanies: Company[] = [
country: "Poland"
}
}, {
+ id: officeSequence(),
address: {
city: "Wrocław",
street: "Traugutta",
diff --git a/src/provider/helpers.ts b/src/provider/helpers.ts
new file mode 100644
index 0000000..20b4496
--- /dev/null
+++ b/src/provider/helpers.ts
@@ -0,0 +1,4 @@
+export const makeIdSequence = (start: number = 1) => {
+ let i = start;
+ return () => i++;
+}
diff --git a/src/ui/theme.ts b/src/ui/theme.ts
new file mode 100644
index 0000000..05e110a
--- /dev/null
+++ b/src/ui/theme.ts
@@ -0,0 +1,10 @@
+import { createMuiTheme } from "@material-ui/core";
+
+export const studentTheme = createMuiTheme({
+ props: {
+ MuiGrid: {
+ spacing: 4,
+ xs: 12,
+ }
+ }
+})
diff --git a/yarn.lock b/yarn.lock
index b908545..1489c71 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3672,11 +3672,6 @@ deep-is@~0.1.3:
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
-deepmerge@^2.1.1:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
- integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==
-
default-gateway@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b"
@@ -4751,20 +4746,6 @@ form-data@~2.3.2:
combined-stream "^1.0.6"
mime-types "^2.1.12"
-formik@^2.1.4:
- version "2.1.4"
- resolved "https://registry.yarnpkg.com/formik/-/formik-2.1.4.tgz#8deef07ec845ea98f75e03da4aad7aab4ac46570"
- integrity sha512-oKz8S+yQBzuQVSEoxkqqJrKQS5XJASWGVn6mrs+oTWrBoHgByVwwI1qHiVc9GKDpZBU9vAxXYAKz2BvujlwunA==
- dependencies:
- deepmerge "^2.1.1"
- hoist-non-react-statics "^3.3.0"
- lodash "^4.17.14"
- lodash-es "^4.17.14"
- react-fast-compare "^2.0.1"
- scheduler "^0.18.0"
- tiny-warning "^1.0.2"
- tslib "^1.10.0"
-
forwarded@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
@@ -5121,7 +5102,7 @@ hmac-drbg@^1.0.0:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
-hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
+hoist-non-react-statics@^3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
@@ -6694,11 +6675,6 @@ locate-path@^5.0.0:
dependencies:
p-locate "^4.1.0"
-lodash-es@^4.17.14:
- version "4.17.15"
- resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78"
- integrity sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ==
-
lodash._reinterpolate@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
@@ -8832,11 +8808,6 @@ react-error-overlay@^6.0.7:
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.7.tgz#1dcfb459ab671d53f660a991513cb2f0a0553108"
integrity sha512-TAv1KJFh3RhqxNvhzxj6LeT5NWklP6rDr2a0jaTfsZ5wSZWHOGeqQyejUp3xxLfPt2UpyJEcVQB/zyPcmonNFA==
-react-fast-compare@^2.0.1:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
- integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
-
react-is@^16.12.0, react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1, react-is@^16.8.4:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
@@ -9404,14 +9375,6 @@ saxes@^3.1.9:
dependencies:
xmlchars "^2.1.1"
-scheduler@^0.18.0:
- version "0.18.0"
- resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.18.0.tgz#5901ad6659bc1d8f3fdaf36eb7a67b0d6746b1c4"
- integrity sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ==
- dependencies:
- loose-envify "^1.1.0"
- object-assign "^4.1.1"
-
scheduler@^0.19.1:
version "0.19.1"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196"