Skip to content

Commit bb3f769

Browse files
reset, default data, update object
1 parent a10720b commit bb3f769

File tree

5 files changed

+159
-91
lines changed

5 files changed

+159
-91
lines changed

src/DataContext.tsx

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { IModalData } from "./components/AddSomethingModal";
66

77
interface IState {
88
dataCollection: null | undefined | any;
9+
updateItem: (itemData: IModalData) => Promise<void>;
910
addItem: (itemData: IModalData) => Promise<void>;
1011
removeItem: (itemData: IModalData) => Promise<void>;
1112
}
@@ -34,6 +35,14 @@ export const DataProvider: React.FC = ({ children }) => {
3435
return thingsRef.doc().set({ ...itemData });
3536
};
3637

38+
/**
39+
*
40+
* @param itemData
41+
*/
42+
const updateItem = (itemData: IModalData) => {
43+
return thingsRef.doc(itemData.id).set({ ...itemData }, { merge: true });
44+
};
45+
3746
/**
3847
*
3948
* @param itemData
@@ -42,15 +51,16 @@ export const DataProvider: React.FC = ({ children }) => {
4251
return thingsRef.doc(itemData.id).delete();
4352
};
4453

45-
// the store object
46-
let state = {
47-
dataCollection: data,
48-
addItem,
49-
removeItem,
50-
};
54+
// the store object
55+
let state = {
56+
dataCollection: data,
57+
addItem,
58+
updateItem,
59+
removeItem,
60+
};
5161

52-
// wrap the application in the provider with the initialized context
53-
return <DataContext.Provider value={state}>{children}</DataContext.Provider>;
62+
// wrap the application in the provider with the initialized context
63+
return <DataContext.Provider value={state}>{children}</DataContext.Provider>;
5464
};
5565

5666
export default DataContext;

src/components/AddSomethingModal.tsx

Lines changed: 58 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -7,82 +7,99 @@ import {
77
IonTitle,
88
IonContent,
99
IonPage,
10+
IonLabel,
11+
IonItem,
12+
IonText,
1013
} from "@ionic/react";
1114

12-
import { useForm } from "react-hook-form";
15+
import { useForm, FormProvider } from "react-hook-form";
1316
import { MyIonTextItem } from "./MyIonTextItem";
1417

1518
const AddSomethingModal: React.FunctionComponent<{
1619
onCloseModal: (data: IModalResponse) => Promise<void>;
17-
}> = ({ onCloseModal }) => {
20+
initialData?: IModalData;
21+
}> = ({ onCloseModal, initialData }) => {
1822
// from react-hook-form
19-
// SEE - https://react-hook-form.com/
20-
const { handleSubmit, control, errors } = useForm();
23+
const methods = useForm({
24+
defaultValues: initialData,
25+
});
2126
/**
2227
* get data from form and pass it back to the parent
2328
* component
2429
*/
2530
const addTheThing = async (data: IModalData) => {
26-
console.log(data);
27-
onCloseModal({ hasData: true, data });
31+
console.log({ ...initialData, ...data });
32+
onCloseModal({ hasData: true, data: { ...initialData, ...data } });
2833
};
2934

3035
return (
3136
<IonPage>
3237
<IonHeader>
3338
<IonToolbar color="light">
3439
<IonButtons slot="start" />
35-
<IonTitle>Enter Thing Information</IonTitle>
40+
<IonTitle>{initialData ? "Update " : "Create New "} Thing</IonTitle>
3641
</IonToolbar>
3742
</IonHeader>
3843
<IonContent className="ion-padding">
39-
<form onSubmit={handleSubmit(addTheThing)}>
40-
<MyIonTextItem
41-
labelName="Podcast Name"
42-
name="podcastName"
43-
errors={errors}
44-
control={control}
45-
/>
44+
<FormProvider {...methods}>
45+
<form onSubmit={methods.handleSubmit(addTheThing)}>
46+
<MyIonTextItem labelName="Podcast Name" name="podcastName" />
4647

47-
<MyIonTextItem
48-
labelName="Host"
49-
name="podcastHost"
50-
errors={errors}
51-
control={control}
52-
/>
48+
<MyIonTextItem labelName="Host" name="podcastHost" />
5349

54-
<MyIonTextItem
55-
labelName="URL"
56-
name="podcastURL"
57-
errors={errors}
58-
control={control}
59-
/>
50+
<MyIonTextItem labelName="URL" name="podcastURL" />
51+
{initialData && (
52+
<IonItem>
53+
<IonLabel>ID</IonLabel>
54+
<IonText>{initialData.id}</IonText>
55+
</IonItem>
56+
)}
6057

61-
<div className="ion-padding">
62-
<IonButton expand="block" type="submit">
63-
Save Podcast Information
64-
</IonButton>
65-
<IonButton
66-
expand="block"
67-
type="button"
68-
onClick={() => onCloseModal({ hasData: false })}
69-
>
70-
Cancel
71-
</IonButton>
72-
</div>
73-
</form>
58+
<div className="ion-padding">
59+
<IonButton expand="block" type="submit">
60+
{initialData ? "Update " : "Save "} Podcast Information
61+
</IonButton>
62+
{!initialData && (
63+
<IonButton
64+
color="warning"
65+
expand="block"
66+
type="button"
67+
onClick={() =>
68+
methods.reset({
69+
podcastHost: "",
70+
podcastName: "",
71+
podcastURL: "",
72+
})
73+
}
74+
>
75+
Clear Form
76+
</IonButton>
77+
)}
78+
<IonButton
79+
color="danger"
80+
expand="block"
81+
type="button"
82+
onClick={() =>
83+
onCloseModal({ hasData: false, data: undefined })
84+
}
85+
>
86+
Cancel
87+
</IonButton>
88+
</div>
89+
</form>
90+
</FormProvider>
7491
</IonContent>
7592
</IonPage>
7693
);
7794
};
7895

79-
export default AddSomethingModal;
96+
export default React.memo(AddSomethingModal);
8097

8198
export type IModalData = {
8299
podcastName: string;
83100
podcastHost: string;
84101
podcastURL: string;
85-
id? : string;
102+
id?: string;
86103
};
87104

88105
export type IModalResponse = {

src/components/MyIonTextItem.tsx

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,36 @@
11
import React from "react";
2-
import {
3-
IonItem,
4-
IonLabel,
5-
IonInput
6-
} from "@ionic/react";
7-
import { Controller } from "react-hook-form";
2+
import { IonItem, IonLabel, IonInput } from "@ionic/react";
3+
import { Controller, useFormContext } from "react-hook-form";
84
import { MyErrorDisplay } from "./MyErrorDisplay";
95
/**
106
* custom component to render the text fields
117
* @param param0
128
*/
139
export const MyIonTextItem: React.FunctionComponent<{
1410
name: string;
15-
errors: any;
16-
render?: any;
17-
control: any;
1811
labelName: string;
19-
}> = ({ name, errors, render, control, labelName }) => {
12+
}> = ({ name, labelName }) => {
13+
const { control, errors, register } = useFormContext();
14+
2015
return (
2116
<>
2217
<IonItem>
2318
<IonLabel>{labelName}</IonLabel>
2419
<Controller
2520
render={({ onChange }) => (
26-
<IonInput type="text" onIonChange={onChange} defaultValue="" />
21+
<IonInput
22+
type="text"
23+
name={name}
24+
ref={register}
25+
onIonChange={onChange}
26+
/>
2727
)}
2828
control={control}
2929
name={name}
3030
rules={{
3131
required: labelName + " is a required field",
32-
}} />
32+
}}
33+
/>
3334
</IonItem>
3435
<MyErrorDisplay errors={errors} elementName={name} />
3536
</>

src/pages/Home.tsx

Lines changed: 49 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@ import {
77
IonToolbar,
88
IonTitle,
99
IonContent,
10-
IonLabel,
1110
IonLoading,
1211
IonList,
13-
IonItem,
1412
IonModal,
1513
IonAlert,
1614
} from "@ionic/react";
@@ -23,6 +21,7 @@ import AddSomethingModal, {
2321
} from "../components/AddSomethingModal";
2422
import { useHistory } from "react-router";
2523
import { useDataProvider } from "../DataContext";
24+
import Line from "./Line";
2625

2726
type IShowAlert = null | {
2827
header: string;
@@ -34,13 +33,14 @@ const Home: React.FunctionComponent = () => {
3433
// reactfire hook to get auth information
3534
const auth = useAuth();
3635
const history = useHistory();
37-
const { addItem, removeItem, dataCollection } = useDataProvider();
36+
const { addItem, removeItem, dataCollection, updateItem } = useDataProvider();
3837

39-
console.log(dataCollection);
40-
41-
// manages the state to determine if we need to open
42-
// the modal or not
43-
const [showModal, setShowModal] = useState(false);
38+
// manages the state to determine if we need to open
39+
// the modal or not
40+
const [showModal, setShowModal] = useState<{
41+
show: boolean;
42+
initialData?: IModalData;
43+
}>({ show: false });
4444

4545
// manages the state to determine if we need to open
4646
// the modal or not
@@ -61,6 +61,13 @@ const Home: React.FunctionComponent = () => {
6161
});
6262
};
6363

64+
/**
65+
* @param item
66+
*/
67+
const editSomething = (item: IModalData) => {
68+
setShowModal({ show: true, initialData: item });
69+
};
70+
6471
/**
6572
*
6673
* @param item IModalData
@@ -78,16 +85,21 @@ const Home: React.FunctionComponent = () => {
7885
* @param response IModalResponse
7986
*/
8087
const addSomething = async (response: IModalResponse) => {
81-
setShowModal(false);
82-
if (response.hasData) {
83-
alert(JSON.stringify(response.data));
84-
addItem(response.data!)
85-
.then(() => showAlert("Success"))
86-
.catch((error: any) => {
87-
showAlert(error.message, true);
88-
});
89-
} else {
88+
setShowModal({ show: false });
89+
if (!response.hasData) {
9090
showAlert("User Cancelled", true);
91+
return;
92+
} else {
93+
try {
94+
if (response.data?.id) {
95+
await updateItem(response.data!);
96+
} else {
97+
await addItem(response.data!);
98+
}
99+
showAlert("Success");
100+
} catch (error) {
101+
showAlert(error.message, true);
102+
}
91103
}
92104
};
93105

@@ -112,7 +124,7 @@ const Home: React.FunctionComponent = () => {
112124
<IonButton
113125
title="Add Something"
114126
fill="outline"
115-
onClick={() => setShowModal(true)}
127+
onClick={() => setShowModal({ show: true })}
116128
>
117129
Add Something
118130
</IonButton>
@@ -129,24 +141,31 @@ const Home: React.FunctionComponent = () => {
129141
/>
130142

131143
{/* ionic modal component */}
132-
<IonModal isOpen={showModal} onDidDismiss={() => setShowModal(false)}>
133-
{/* our custom modal content */}
134-
<AddSomethingModal
135-
onCloseModal={(data: IModalResponse) => addSomething(data)}
136-
/>
137-
</IonModal>
144+
{showModal.show && (
145+
<IonModal
146+
isOpen={showModal.show}
147+
onDidDismiss={() => setShowModal({ show: false })}
148+
>
149+
{/* our custom modal content */}
150+
<AddSomethingModal
151+
initialData={showModal.initialData}
152+
onCloseModal={(data: IModalResponse) => addSomething(data)}
153+
/>
154+
</IonModal>
155+
)}
138156

139157
{/* auth check and loader while in progress */}
140158
<AuthCheck fallback={<IonLoading isOpen={true} />}>
141159
{/* list of items from reactfire */}
142160
<IonList>
143161
{dataCollection.map((e: any) => {
144162
return (
145-
<IonItem key={e.id} onClick={() => removeSomething(e)}>
146-
<IonLabel className="ion-text-wrap">
147-
<pre>{JSON.stringify(e, null, 2)}</pre>
148-
</IonLabel>
149-
</IonItem>
163+
<Line
164+
item={e}
165+
key={e.id}
166+
edit={editSomething}
167+
remove={removeSomething}
168+
/>
150169
);
151170
})}
152171
</IonList>
@@ -155,4 +174,4 @@ const Home: React.FunctionComponent = () => {
155174
</IonPage>
156175
);
157176
};
158-
export default Home;
177+
export default React.memo(Home);

0 commit comments

Comments
 (0)