diff --git a/src/components/forms/formGenerator.js b/src/components/forms/formGenerator.js
new file mode 100644
index 0000000..efba6d5
--- /dev/null
+++ b/src/components/forms/formGenerator.js
@@ -0,0 +1,158 @@
+import React from 'react'
+
+/**
+ *
+ * @param { [ {}, {}, ...{} ] } inputList - list of dicts with info about input
+ * @param { [] } refList - react ref objects list for handler validation
+ * @param { } action - fetch method
+ */
+export const FormGenerator = ({
+ inputList, refList,
+ action
+}) => {
+
+ const handler = async (event) => {
+ event.preventDefault()
+ for ( let i = 0; i < refList.length; i++ ) {
+ if (
+ refList[i].current.value === ''
+ && inputList[0].action !== 'Update'
+ || i === 0 && refList.length !== 1
+ ) {
+ refList[i].current.focus()
+ } else if ( i === refList.length - 1 ) {
+ await action( refList )
+ }
+ }
+ }
+
+ let info
+
+ return (
+
+ )
+}
+
+/**
+ * Text input generator, example:
+ * @param {
+ * {
+ * type: 'text',
+ * name: 'name',
+ * ref: React.createRef()
+ * } } input - basic text input
+ * @param {
+ * {
+ * type: 'info',
+ * action: 'Update'
+ * endpoint: 'Album'
+ * } } info - information about form
+ */
+const TextInputGenerator = ({
+ input, info
+}) => {
+ return (
+
+ { input.name + ':' }
+
+
+ )
+}
+
+/**
+ * Upload file input generator, example:
+ * @param {
+ * {
+ * type: 'file',
+ * name: 'name',
+ * endpoint: 'Album',
+ * fileType: 'image' or 'audio',
+ * dropInfo: dropInfo, setDropInfo: setDropInfo(), #useState
+ * file: file, setFile: setFile() #useState
+ * } } input -
+ */
+const UploadInputGenerator = ({
+ input, info
+}) => {
+
+ const onLoadFile = async ( event ) => {
+ event.preventDefault()
+ let data = event.target.files[0]
+ input.setFile( await toBase64( data ) )
+ setDropInfos(data.name, data.size)
+ }
+
+ const onLoadFileDrop = async ( event ) => {
+ event.preventDefault()
+ event.persist()
+ let data = event.dataTransfer.files[0]
+ input.setFile( await toBase64( data ) )
+ setDropInfos(data.name, data.size)
+ }
+
+ const toBase64 = ( file ) => new Promise( (resolve, reject) => {
+ let fileReader = new FileReader()
+ fileReader.readAsDataURL( file )
+ fileReader.onload = () => resolve( fileReader.result )
+ fileReader.onerror = error => reject( error )
+ })
+
+ const setDropInfos = (name, size) => {
+ input.setDropInfo(
+ 'name: "'
+ + name
+ + '"\nsize: '
+ + (Math.round(size / 100 + 'e-2') / 100 )
+ + ' MB'
+ )
+ }
+
+ return (
+ onLoadFileDrop( event ) } >
+
+ { input.dropInfo }
+
+
onLoadFile( event ) }
+ />
+
+ )
+}
+
+export default FormGenerator
\ No newline at end of file
diff --git a/src/components/forms/model_crud/model_get_all.js b/src/components/forms/model_crud/model_get_all.js
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/forms/model_crud/model_get_one_and_download.js b/src/components/forms/model_crud/model_get_one_and_download.js
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/forms/model_crud/model_upload.js b/src/components/forms/model_crud/model_upload.js
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/forms/render_crud/render_get_all.js b/src/components/forms/render_crud/render_get_all.js
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/forms/render_crud/render_get_one_and_download.js b/src/components/forms/render_crud/render_get_one_and_download.js
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/forms/user_auth/user_login.js b/src/components/forms/user_auth/user_login.js
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/forms/user_auth/user_register.js b/src/components/forms/user_auth/user_register.js
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/forms/user_crud/user_update.js b/src/components/forms/user_crud/user_update.js
new file mode 100644
index 0000000..e69de29
diff --git a/src/pages/func_group/rootUtils.js b/src/pages/func_group/rootUtils.js
index d1d3f9a..ad20678 100644
--- a/src/pages/func_group/rootUtils.js
+++ b/src/pages/func_group/rootUtils.js
@@ -60,10 +60,18 @@ const GeneralView = () => {
-
-
-
-
+
+
+
+
>
)
}