firebase-admin-panel
Version:
A customizable React admin panel for managing Firebase collections.
214 lines (213 loc) • 8.66 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _react = _interopRequireWildcard(require("react"));
var _creatable = _interopRequireDefault(require("react-select/creatable"));
var _useFirestore = require("../hooks/useFirestore");
var _useStorage = require("../hooks/useStorage");
var _firestore = require("firebase/firestore");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const DocumentForm = _ref => {
let {
collectionName,
docToEdit,
onSave,
schema,
formClassName = "",
inputClassName = "",
labelClassName = "",
buttonClassName = ""
} = _ref;
const [formData, setFormData] = (0, _react.useState)({});
const [file, setFile] = (0, _react.useState)(null);
const [docRefOptions, setDocRefOptions] = (0, _react.useState)({});
const [errors, setErrors] = (0, _react.useState)({});
(0, _react.useEffect)(() => {
if (docToEdit) {
const initialData = {
...docToEdit
};
Object.keys(initialData).forEach(key => {
if (initialData[key] instanceof _firestore.Timestamp) {
initialData[key] = initialData[key].toDate().toISOString().split("T")[0];
} else if (Array.isArray(initialData[key])) {
initialData[key] = initialData[key].map(value => ({
label: value,
value: value
}));
}
});
setFormData(initialData);
} else {
const initialData = {};
Object.keys(schema).forEach(key => {
initialData[key] = schema[key].type === "array" || schema[key].type === "docRef array" ? [] : "";
});
setFormData(initialData);
}
}, [docToEdit, schema]);
(0, _react.useEffect)(() => {
const fetchDocRefOptions = async () => {
const options = {};
for (const key in schema) {
if (schema[key].type === "docRef" || schema[key].type === "docRef array") {
const docs = await (0, _useFirestore.getCollectionDocuments)(schema[key].collection);
options[key] = docs.map(doc => ({
label: doc.id,
value: doc.id
}));
}
}
setDocRefOptions(options);
};
fetchDocRefOptions();
}, [schema]);
const handleChange = e => {
setFormData({
...formData,
[e.target.name]: e.target.value
});
};
const handleSelectChange = (selectedOptions, key) => {
setFormData({
...formData,
[key]: selectedOptions
});
};
const handleFileChange = e => {
setFile(e.target.files[0]);
};
const validateForm = () => {
const newErrors = {};
Object.keys(schema).forEach(key => {
if ((!formData[key] || formData[key].length === 0) && schema[key] !== "image") {
newErrors[key] = "This field is required";
} else if (schema[key] === "image" && !file && !(docToEdit !== null && docToEdit !== void 0 && docToEdit[key])) {
newErrors[key] = "This field is required";
}
});
if (Object.keys(newErrors).length > 0) {
setErrors(newErrors);
return false;
}
return true;
};
function getKeyByValue(object, value) {
let result = [];
for (let prop in object) {
if (object.hasOwnProperty(prop)) {
if (object[prop] === value) result.push(prop);
}
}
return result;
}
const handleSubmit = async e => {
e.preventDefault();
if (!validateForm()) {
return;
}
let tempDataToSave = {
...formData
};
let dataToSave = tempDataToSave;
let arrayTypes = getKeyByValue(schema, "array");
arrayTypes.forEach(arrayType => {
if (tempDataToSave && arrayType && tempDataToSave[arrayType] && tempDataToSave[arrayType].length > 0) {
var _tempDataToSave$array;
(_tempDataToSave$array = tempDataToSave[arrayType]) === null || _tempDataToSave$array === void 0 || _tempDataToSave$array.forEach((e, index) => {
dataToSave[arrayType][index] = e.value;
});
}
});
if (file) {
const imageUrl = await (0, _useStorage.uploadImage)(file, "".concat(collectionName, "/").concat(file.name));
dataToSave[getKeyByValue(schema, "image")] = imageUrl;
}
Object.keys(dataToSave).forEach(key => {
if (schema[key] && schema[key] === "date" && dataToSave[key]) {
dataToSave[key] = _firestore.Timestamp.fromDate(new Date(dataToSave[key]));
} else if (schema[key] && schema[key] === "array" || schema[key] && schema[key].type === "docRef array") {
dataToSave[key] = dataToSave[key].map(option => {
if (schema[key].type === "docRef array") return option.value;
return option;
});
} else if (schema[key] && schema[key] === "number") {
dataToSave[key] = parseFloat(dataToSave[key]);
}
});
if (docToEdit) {
await (0, _useFirestore.updateDocument)(collectionName, docToEdit.id, dataToSave);
} else {
await (0, _useFirestore.addDocument)(collectionName, dataToSave);
}
onSave();
};
const getInputType = type => {
switch (type) {
case "string":
return "text";
case "number":
return "number";
case "date":
return "date";
case "image":
return "file";
case "docRef":
case "docRef array":
return "select";
default:
return "text";
}
};
return /*#__PURE__*/_react.default.createElement("form", {
onSubmit: handleSubmit,
className: "mt-4 p-4 border border-gray-300 bg-white ".concat(formClassName)
}, Object.keys(schema).map(key => /*#__PURE__*/_react.default.createElement("div", {
key: key,
className: "mb-4"
}, /*#__PURE__*/_react.default.createElement("label", {
className: "block font-bold ".concat(labelClassName)
}, key), schema[key] === "image" ? /*#__PURE__*/_react.default.createElement("input", {
type: "file",
name: key,
onChange: handleFileChange,
className: "w-full p-2 my-2 border border-gray-300 rounded ".concat(inputClassName)
}) : schema[key] === "array" || schema[key].type === "docRef array" ? /*#__PURE__*/_react.default.createElement(_creatable.default, {
isMulti: true,
name: key,
value: formData[key],
onChange: selectedOptions => handleSelectChange(selectedOptions, key),
className: "basic-multi-select",
classNamePrefix: "select",
formatCreateLabel: inputValue => "Add \"".concat(inputValue, "\""),
options: schema[key].type === "docRef array" ? docRefOptions[key] : []
}) : schema[key].type === "docRef" ? /*#__PURE__*/_react.default.createElement("select", {
name: key,
value: formData[key],
onChange: handleChange,
className: "w-full p-2 my-2 border border-gray-300 rounded ".concat(inputClassName)
}, docRefOptions[key] && docRefOptions[key].map(option => /*#__PURE__*/_react.default.createElement("option", {
key: option.value,
value: option.value
}, option.label))) : /*#__PURE__*/_react.default.createElement("input", {
type: getInputType(schema[key]),
name: key,
value: formData[key],
onChange: handleChange,
className: "w-full p-2 my-2 border border-gray-300 rounded ".concat(inputClassName)
}), errors[key] && /*#__PURE__*/_react.default.createElement("p", {
className: "text-red-500"
}, errors[key]))), /*#__PURE__*/_react.default.createElement("button", {
type: "submit",
className: "bg-blue-500 text-white py-2 px-4 rounded text-white border-none cursor-pointer mr-2 ".concat(buttonClassName)
}, docToEdit ? "Update" : "Add", " Document"), /*#__PURE__*/_react.default.createElement("button", {
type: "button",
onClick: onSave,
className: "bg-red-500 text-white py-2 px-4 rounded ml-2 text-white border-none cursor-pointer mr-2 ".concat(buttonClassName)
}, "Cancel"));
};
var _default = exports.default = DocumentForm;