Skip to content

Commit

Permalink
add code demos
Browse files Browse the repository at this point in the history
  • Loading branch information
ericwgreene committed Oct 2, 2020
1 parent 6119c6d commit 1717ff6
Show file tree
Hide file tree
Showing 43 changed files with 31,206 additions and 154 deletions.
18 changes: 9 additions & 9 deletions demo-app/src/components/CarForm.test.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React from 'react';
import { render, RenderResult, fireEvent } from '@testing-library/react';

import { NewCar, CarKeys } from '../models/car';
import { NewCar, NewCarKeys } from '../models/car';
import { CarForm } from '../components/CarForm';

describe('CarViewRow testing library', () => {
let car: NewCar;
let textInputKeys: CarKeys[] = ['make', 'model', 'color'];
let numberInputKeys: CarKeys[] = ['year', 'price'];
let textInputKeys: NewCarKeys[] = ['make', 'model', 'color'];
let numberInputKeys: NewCarKeys[] = ['year', 'price'];
let renderResult: RenderResult;
let submitCarSpy: jest.Mock;

Expand All @@ -34,25 +34,25 @@ describe('CarViewRow testing library', () => {

const textboxInputs = getAllByRole('textbox');
expect(textboxInputs.length).toBe(3);
textboxInputs.forEach((input: HTMLInputElement, index: number) => {
textboxInputs.forEach((input: HTMLElement, index: number) => {
const evt = {
target: {
type: input.type,
type: (input as HTMLInputElement).type,
value: car[textInputKeys[index]],
name: input.name,
name: (input as HTMLInputElement).name,
},
};
fireEvent.change(input, evt);
});

const spinbuttonInputs = getAllByRole('spinbutton');
expect(spinbuttonInputs.length).toBe(2);
spinbuttonInputs.forEach((input: HTMLInputElement, index: number) => {
spinbuttonInputs.forEach((input: HTMLElement, index: number) => {
const evt = {
target: {
type: input.type,
type: (input as HTMLInputElement).type,
value: car[numberInputKeys[index]],
name: input.name,
name: (input as HTMLInputElement).name,
},
};
fireEvent.change(input, evt);
Expand Down
4 changes: 3 additions & 1 deletion perf-car-tool-app-starter/src/components/CarForm.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { memo } from 'react';
import { Box, Typography } from '@material-ui/core';

import { CarFormData } from '../models/CarFormData';
Expand Down Expand Up @@ -85,3 +85,5 @@ export function CarForm({
CarForm.defaultProps = {
headerText: 'Car Form',
};

export const CarFormMemo = memo(CarForm);
6 changes: 3 additions & 3 deletions perf-car-tool-app-starter/src/components/CarTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import {
TableRow,
TableCell,
TableBody,
Typography
Typography,
} from '@material-ui/core';

import { Car, CarKeys } from '../models/Car';
import { CarsSort } from '../models/CarsSort';

import { CarEditRow } from './CarEditRow';
import { CarViewRow } from './CarViewRow';
import { ColHeader } from './ColHeader';
import { CarViewRowMemo as CarViewRow } from './CarViewRow';
import { ColHeaderMemo as ColHeader } from './ColHeader';

export type CarTableProps = {
cars: Car[];
Expand Down
2 changes: 1 addition & 1 deletion perf-car-tool-app-starter/src/components/CarTool.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Grid } from '@material-ui/core';
import { CarToolStore } from '../models/CarToolStore';
import { CarToolLayout } from './CarToolLayout';
import { CarTable } from './CarTable';
import { CarForm } from './CarForm';
import { CarFormMemo as CarForm } from './CarForm';
import { CarAddButton } from './buttons';
import { useStyles } from './CarTool.styles';
import { ConfirmDeleteCarDialog } from './ConfirmDeleteCarDialog';
Expand Down
18 changes: 9 additions & 9 deletions perf-car-tool-app-starter/src/components/CarToolLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import React, { ReactNode } from 'react';
import { Grid } from '@material-ui/core';

import { ToolHeader } from './ToolHeader';
import { ToolFooter } from './ToolFooter';
import { ToolHeaderMemo as ToolHeader } from './ToolHeader';
import { ToolFooterMemo as ToolFooter } from './ToolFooter';

export type CarToolLayoutProps = {
children: ReactNode;
};

export function CarToolLayout({ children }: CarToolLayoutProps) {
function CarToolHeader() {
return <ToolHeader headerText="Car Tool" />;
}
function CarToolFooter() {
return <ToolFooter companyName="A Cool Company, Inc." />;
}
function CarToolHeader() {
return <ToolHeader headerText="Car Tool" />;
}
function CarToolFooter() {
return <ToolFooter companyName="A Cool Company, Inc." />;
}

export function CarToolLayout({ children }: CarToolLayoutProps) {
return (
<Grid container direction="column">
<Grid item component={CarToolHeader} />
Expand Down
4 changes: 3 additions & 1 deletion perf-car-tool-app-starter/src/components/CarViewRow.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { memo } from 'react';
import { TableRow, TableCell, Typography } from '@material-ui/core';

import { Car } from '../models/Car';
Expand Down Expand Up @@ -38,3 +38,5 @@ export function CarViewRow({ car, onEditCar, onDeleteCar }: CarViewRowProps) {
</TableRow>
);
}

export const CarViewRowMemo = memo(CarViewRow);
4 changes: 3 additions & 1 deletion perf-car-tool-app-starter/src/components/ColHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { memo } from 'react';
import { TableCell, Box } from '@material-ui/core';
import { ArrowUpward, ArrowDownward } from '@material-ui/icons';

Expand Down Expand Up @@ -28,3 +28,5 @@ export function ColHeader(props: ColHeaderProps) {
</TableCell>
);
}

export const ColHeaderMemo = memo(ColHeader);
9 changes: 6 additions & 3 deletions perf-car-tool-app-starter/src/components/ToolFooter.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { memo } from 'react';
import { Typography } from '@material-ui/core';

import { useStyles } from './ToolFooter.styles';
Expand All @@ -8,12 +8,15 @@ export type ToolFooterProps = {
};

export function ToolFooter({ companyName }: ToolFooterProps) {

const classes = useStyles();

return (
<footer className={classes.footer}>
<Typography component="small" className={classes.text}>&copy; {new Date().getFullYear()} {companyName}</Typography>
<Typography component="small" className={classes.text}>
&copy; {new Date().getFullYear()} {companyName}
</Typography>
</footer>
);
}

export const ToolFooterMemo = memo(ToolFooter);
4 changes: 3 additions & 1 deletion perf-car-tool-app-starter/src/components/ToolHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { memo } from 'react';
import { Typography } from '@material-ui/core';

import { useStyles } from './ToolHeader.styles';
Expand All @@ -18,3 +18,5 @@ export function ToolHeader({ headerText }: ToolHeaderProps) {
</header>
);
}

export const ToolHeaderMemo = memo(ToolHeader);
99 changes: 57 additions & 42 deletions perf-car-tool-app-starter/src/hooks/useCarStore.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState } from 'react';
import { useState, useCallback, useMemo } from 'react';

import { Car } from '../models/Car';
import { CarsSort, SORT_ASC, SORT_DESC } from '../models/CarsSort';
Expand Down Expand Up @@ -41,61 +41,76 @@ export const useCarToolStore: UseCarToolStore = (initialCars) => {
carId: -1,
});

const addCar = (carForm: CarFormData) => {
appendCar(carForm);
setEditCarId(-1);
};
const addCar = useCallback(
(carForm: CarFormData) => {
appendCar(carForm);
setEditCarId(-1);
},
[appendCar],
);

const saveCar = (car: Car) => {
replaceCar(car);
setEditCarId(-1);
};
const saveCar = useCallback(
(car: Car) => {
replaceCar(car);
setEditCarId(-1);
},
[replaceCar],
);

const confirmDeleteCar = (carId: number) => {
const { make, model, year } = cars.find((c) => c.id === carId)!;
const confirmDeleteCar = useCallback(
(carId: number) => {
const { make, model, year } = cars.find((c) => c.id === carId)!;

setConfirmDeleteCarMessage({
message: `Are you sure you want to delete the ${year} ${make} ${model}?`,
carId,
});
};
setConfirmDeleteCarMessage({
message: `Are you sure you want to delete the ${year} ${make} ${model}?`,
carId,
});
},
[cars],
);

const deleteCar = (carId: number) => {
removeCar(carId);
setEditCarId(-1);
setConfirmDeleteCarMessage({
message: '',
carId: -1,
});
};
const deleteCar = useCallback(
(carId: number) => {
removeCar(carId);
setEditCarId(-1);
setConfirmDeleteCarMessage({
message: '',
carId: -1,
});
},
[removeCar],
);

const cancelCar = () => {
const cancelCar = useCallback(() => {
setEditCarId(-1);
};
}, []);

const sortCars = (col: keyof Car) => {
if (col === carsSort.col) {
setCarsSort({
col,
dir: SORT_ASC === carsSort.dir ? SORT_DESC : SORT_ASC,
});
} else {
setCarsSort({
col,
dir: SORT_ASC,
});
}
};
const sortCars = useCallback(
(col: keyof Car) => {
if (col === carsSort.col) {
setCarsSort({
col,
dir: SORT_ASC === carsSort.dir ? SORT_DESC : SORT_ASC,
});
} else {
setCarsSort({
col,
dir: SORT_ASC,
});
}
},
[carsSort],
);

function cancelConfirmDeleteCar() {
const cancelConfirmDeleteCar = useCallback(() => {
setConfirmDeleteCarMessage({
message: '',
carId: -1,
});
}
}, []);

return {
sortedCars: sortedCars(cars, carsSort),
sortedCars: useMemo(() => sortedCars(cars, carsSort), [cars, carsSort]),
editCarId,
carsSort,
confirmDeleteCarMessage,
Expand Down
84 changes: 44 additions & 40 deletions perf-car-tool-app-starter/src/hooks/useList.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,51 @@
import { useState } from 'react';
import { useState, useCallback } from 'react';

import { Item, ItemId } from '../models/Item';

type AppendItem<S> = (item: Omit<S, 'id'>) => void;
type ReplaceItem<S> = (item: S) => void;
type RemoveItem = (itemId: ItemId) => void;

type UseList = <ItemType extends Item>(initialItems: ItemType[]) =>
([
ItemType[],
AppendItem<ItemType>,
ReplaceItem<ItemType>,
RemoveItem,
]);

export const useList: UseList = <ItemType extends Item>(initialItems: ItemType[]) => {

const [ items, setItems ] = useState([ ...initialItems ]);

const addItem: AppendItem<ItemType> = (item) => {

setItems([
...items,
{
...item,
id: Math.max(...items.map(i => i.id), 0) + 1,
} as ItemType,
]);
};

const saveItem: ReplaceItem<ItemType> = (item) => {
const itemIndex = items.findIndex(i => i.id === item.id);
if (itemIndex >= 0) {
const newItems = items.concat();
newItems[itemIndex] = item;
setItems(newItems);
}
};

const deleteItem: RemoveItem = (itemId) => {
setItems(items.filter(i => i.id !== itemId));
};

return [ items, addItem, saveItem, deleteItem ];

};
type UseList = <ItemType extends Item>(
initialItems: ItemType[],
) => [ItemType[], AppendItem<ItemType>, ReplaceItem<ItemType>, RemoveItem];

export const useList: UseList = <ItemType extends Item>(
initialItems: ItemType[],
) => {
const [items, setItems] = useState([...initialItems]);

const addItem: AppendItem<ItemType> = useCallback(
(item) => {
setItems([
...items,
{
...item,
id: Math.max(...items.map((i) => i.id), 0) + 1,
} as ItemType,
]);
},
[items],
);

const saveItem: ReplaceItem<ItemType> = useCallback(
(item) => {
const itemIndex = items.findIndex((i) => i.id === item.id);
if (itemIndex >= 0) {
const newItems = items.concat();
newItems[itemIndex] = item;
setItems(newItems);
}
},
[items],
);

const deleteItem: RemoveItem = useCallback(
(itemId) => {
setItems(items.filter((i) => i.id !== itemId));
},
[items],
);

return [items, addItem, saveItem, deleteItem];
};
Loading

0 comments on commit 1717ff6

Please sign in to comment.