app\containers\SampleFirebaseApps\Contact\services\contactApi.js
fetchContacts: builder.query({
queryFn: async () => {
const contactRef = child(dbRef, 'contacts/');
const querySnapshot = await get(contactRef).then((snapshot) => {
if (snapshot.exists()) {
return snapshot.val();
}
return false;
}).catch((error) => error);
const contacts = Object.keys(querySnapshot).map(key => ({
id: key,
...querySnapshot[key]
}));
return { data: contacts.reverse() };
},
providesTags: ['Contact'],
}),
refetchContact: builder.mutation({
queryFn: async () => ({
data: null
}),
invalidatesTags: ['Contact'],
}),
app\containers\SampleFirebaseApps\Contact\reducers\contactSlice.js
fetchData: (state, action) => {
const items = action.payload;
state.contactList = items;
},
\app\containers\SampleFirebaseApps\Contact\index.js
import { useFetchContactsQuery } from './services/contactApi';
import { fetchData } from './reducers/contactSlice';
const dataContact = useSelector(state => state.contactFb.contactList);
const { data, isLoading } = useFetchContactsQuery();
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchData(data));
}, [data]);
return {
<ContactList
addFn
total={dataContact && dataContact.length}
addContact={() => dispatch(add())}
clippedRight
itemSelected={itemSelected}
keyword={keyword}
search={(payload) => dispatch(search(payload))}
dataContact={dataContact}
loading={isLoading}
showDetail={(payload) => dispatch(showDetail(payload))}
/>
}
app\components\Contact\ContactList.js
const getItem = dataArray => dataArray.map(data => {
const index = dataContact.indexOf(data);
if (data.get('name').toLowerCase().indexOf(keyword) === -1) {
return false;
}
return (
<ListItem
button
key={data.id}
className={index === itemSelected ? classes.selected : ''}
onClick={() => showDetail(data)}
>
<Avatar alt={data.name} src={data.avatar} className={classes.avatar} />
<ListItemText primary={data.name} secondary={data.title'} />
</ListItem>
);
});
app\containers\SampleFirebaseApps\Contact\services\contactApi.js
submitContact: builder.mutation({
queryFn: async (payload) => {
const contactId = (+new Date() + Math.floor(Math.random() * 999999)).toString(36);
await set(ref(db, 'contacts/' + contactId), payload)
.then(() => {
console.info('submit success');
})
.catch((error) => {
console.error(error);
});
return { data: null };
},
invalidatesTags: ['Contact'],
}),
app\containers\SampleFirebaseApps\Contact\reducers\contactSlice.js
submit: (state) => {
state.selectedIndex = 0;
state.avatarInit = '';
state.openFrm = false;
},
app\containers\SampleFirebaseApps\Contact\index.js
import { useSubmitContactMutation } from './services/contactApi';
import { submit } from './reducers/contactSlice';
const [submitContact] = useSubmitContactMutation();
const handleSubmit = (item, avatar) => {
let value = {};
setUploadSubmiting(true);
if (item.id === selectedId) { // Update contact
const contact = dataContact[itemSelected];
dispatch(update());
if (typeof avatar === 'object') {
uploadImg(avatar, async (url) => {
value = { ...item, avatar: url || null };
updateContact({ contact, change: value });
setUploadSubmiting(false);
});
} else {
updateContact({ contact, change: item });
setUploadSubmiting(false);
}
} else { // Create new contact
dispatch(submit());
uploadImg(avatar, async (url) => {
value = { ...item, avatar: url || null };
submitContact(value);
setUploadSubmiting(false);
});
}
};
return (
<AddContact
initialValues={initVal}
addContact={() => dispatch(add())}
openForm={open}
closeForm={() => dispatch(closeForm())}
submit={(value, avatar) => handleSubmit(value, avatar)}
avatarInit={avatarInit}
processing={uploadSubmiting}
/>
)
app\components\Contact\AddContactForm.js
const sleep = (ms) => new Promise((r) => { setTimeout(r, ms); });
const formik = useFormik({
initialValues,
enableReinitialize: true,
validationSchema,
onSubmit: async (values) => {
await sleep(500);
sendValues(values);
await sleep(500);
formik.resetForm({
values: initialValues
});
},
});
return (
<form onSubmit={formik.handleSubmit} noValidate>
...
</form>
)
app\containers\SampleFirebaseApps\Contact\services\contactApi.js
updateContact: builder.mutation({
queryFn: async (payload) => {
const { contact, change } = payload;
const updates = {};
updates['/contacts/' + contact.id] = { ...contact, ...change };
await update(ref(db), updates).then(() => {
console.info('update success');
}).catch((error) => {
console.error(error);
});
return { data: null };
},
invalidatesTags: ['Contact'],
}),
app\containers\SampleFirebaseApps\Contact\reducers\contactSlice.js
update: (state) => {
state.avatarInit = '';
state.openFrm = false;
},
app\containers\SampleFirebaseApps\Contact\index.js
import { useUpdateContactMutation } from './services/contactApi';
import { update } from './reducers/contactSlice';
const [updateContact] = useUpdateContactMutation();
const handleSubmit = (item, avatar) => {
let value = {};
setUploadSubmiting(true);
if (item.id === selectedId) { // Update contact
const contact = dataContact[itemSelected];
dispatch(update());
if (typeof avatar === 'object') {
uploadImg(avatar, async (url) => {
value = { ...item, avatar: url || null };
updateContact({ contact, change: value });
setUploadSubmiting(false);
});
} else {
updateContact({ contact, change: item });
setUploadSubmiting(false);
}
} else { // Create new contact
dispatch(submit());
uploadImg(avatar, async (url) => {
value = { ...item, avatar: url || null };
submitContact(value);
setUploadSubmiting(false);
});
}
};
return (
<AddContact
initialValues={initVal}
addContact={() => dispatch(add())}
openForm={open}
closeForm={() => dispatch(closeForm())}
submit={(value, avatar) => handleSubmit(value, avatar)}
avatarInit={avatarInit}
processing={uploadSubmiting}
/>
)
app\components\Contact\AddContactForm.js
const sleep = (ms) => new Promise((r) => { setTimeout(r, ms); });
const formik = useFormik({
initialValues,
enableReinitialize: true,
validationSchema,
onSubmit: async (values) => {
await sleep(500);
sendValues(values);
await sleep(500);
formik.resetForm({
values: initialValues
});
},
});
return (
<form onSubmit={formik.handleSubmit} noValidate>
...
</form>
)
app\containers\SampleFirebaseApps\Contact\services\contactApi.js
removeContact: builder.mutation({
queryFn: async (contact) => {
const contactId = contact.id;
await remove(ref(db, 'contacts/' + contactId))
.then(() => {
console.info('delete success');
}).catch((error) => {
console.error(error);
});
return { data: null };
},
invalidatesTags: ['Contact'],
}),
app\containers\SampleFirebaseApps\Contact\index.js
import { useRemoveContactMutation } from './services/contactApi';
const [removeContact] = useRemoveContactMutation();
const handleRemove = (item) => {
removeContact(item);
setMessage(notif.removed);
};
return (
<ContactDetail
showMobileDetail={showMobileDetail}
hideDetail={() => dispatch(hideDetail())}
dataContact={dataContact}
itemSelected={itemSelected}
edit={(payload) => dispatch(edit(payload))}
remove={(contact) => handleRemove(contact)}
favorite={(contact) => handleFavorite(contact)}
loading={isLoading}
/>
)
app/components/Contact/ContactDetail.js
const deleteContact = (item) => {
remove(item);
setAnchorElOpt(null);
};
return (
<MenuItem onClick={() => deleteContact(dataContact[itemSelected])}>
<FormattedMessage {...messages.delete} />
</MenuItem>
)