(null);
+ const [isModalActive, setIsModalActive] = useState(false);
+ const [showTableView, setShowTableView] = useState(false);
+
+
+ const { currentUser } = useAppSelector((state) => state.auth);
+
+
+ const dispatch = useAppDispatch();
+
+
+ const [filters] = useState([
+ {label: 'YearNumber', title: 'year_number', number: 'true'},{label: 'PeriodNumber', title: 'period_number', number: 'true'},
+
+ {label: 'StartDate', title: 'start_date', date: 'true'},{label: 'EndDate', title: 'end_date', date: 'true'},{label: 'DueDate', title: 'due_date', date: 'true'},
+
+
+ {label: 'Merchant', title: 'merchant'},
+
+
+
+ {label: 'PeriodType', title: 'period_type', type: 'enum', options: ['monthly','quarterly','annual']},{label: 'Status', title: 'status', type: 'enum', options: ['open','in_review','ready_to_file','filed','amended','closed']},
+ ]);
+
+ const hasCreatePermission = currentUser && hasPermission(currentUser, 'CREATE_TAX_PERIODS');
+
+
+ const addFilter = () => {
+ const newItem = {
+ id: uniqueId(),
+ fields: {
+ filterValue: '',
+ filterValueFrom: '',
+ filterValueTo: '',
+ selectedField: '',
+ },
+ };
+ newItem.fields.selectedField = filters[0].title;
+ setFilterItems([...filterItems, newItem]);
+ };
+
+ const getTax_periodsCSV = async () => {
+ const response = await axios({url: '/tax_periods?filetype=csv', method: 'GET',responseType: 'blob'});
+ const type = response.headers['content-type']
+ const blob = new Blob([response.data], { type: type })
+ const link = document.createElement('a')
+ link.href = window.URL.createObjectURL(blob)
+ link.download = 'tax_periodsCSV.csv'
+ link.click()
+ };
+
+ const onModalConfirm = async () => {
+ if (!csvFile) return;
+ await dispatch(uploadCsv(csvFile));
+ dispatch(setRefetch(true));
+ setCsvFile(null);
+ setIsModalActive(false);
+ };
+
+ const onModalCancel = () => {
+ setCsvFile(null);
+ setIsModalActive(false);
+ };
+
+ return (
+ <>
+
+ {getPageTitle('Tax_periods')}
+
+
+
+ {''}
+
+
+
+ {hasCreatePermission && }
+
+
+
+
+ {hasCreatePermission && (
+ setIsModalActive(true)}
+ />
+ )}
+
+
+
+
+
+ Back to
calendar
+
+
+
+
+
+
+
+
+
+
+
+ >
+ )
+}
+
+Tax_periodsTablesPage.getLayout = function getLayout(page: ReactElement) {
+ return (
+
+ {page}
+
+ )
+}
+
+export default Tax_periodsTablesPage
diff --git a/frontend/src/pages/tax_periods/tax_periods-view.tsx b/frontend/src/pages/tax_periods/tax_periods-view.tsx
new file mode 100644
index 0000000..3758389
--- /dev/null
+++ b/frontend/src/pages/tax_periods/tax_periods-view.tsx
@@ -0,0 +1,892 @@
+import React, { ReactElement, useEffect } from 'react';
+import Head from 'next/head'
+import DatePicker from "react-datepicker";
+import "react-datepicker/dist/react-datepicker.css";
+import dayjs from "dayjs";
+import {useAppDispatch, useAppSelector} from "../../stores/hooks";
+import {useRouter} from "next/router";
+import { fetch } from '../../stores/tax_periods/tax_periodsSlice'
+import {saveFile} from "../../helpers/fileSaver";
+import dataFormatter from '../../helpers/dataFormatter';
+import ImageField from "../../components/ImageField";
+import LayoutAuthenticated from "../../layouts/Authenticated";
+import {getPageTitle} from "../../config";
+import SectionTitleLineWithButton from "../../components/SectionTitleLineWithButton";
+import SectionMain from "../../components/SectionMain";
+import CardBox from "../../components/CardBox";
+import BaseButton from "../../components/BaseButton";
+import BaseDivider from "../../components/BaseDivider";
+import {mdiChartTimelineVariant} from "@mdi/js";
+import {SwitchField} from "../../components/SwitchField";
+import FormField from "../../components/FormField";
+
+import {hasPermission} from "../../helpers/userPermissions";
+
+
+const Tax_periodsView = () => {
+ const router = useRouter()
+ const dispatch = useAppDispatch()
+ const { tax_periods } = useAppSelector((state) => state.tax_periods)
+
+ const { currentUser } = useAppSelector((state) => state.auth);
+
+
+ const { id } = router.query;
+
+ function removeLastCharacter(str) {
+ console.log(str,`str`)
+ return str.slice(0, -1);
+ }
+
+ useEffect(() => {
+ dispatch(fetch({ id }));
+ }, [dispatch, id]);
+
+
+ return (
+ <>
+
+ {getPageTitle('View tax_periods')}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Merchant
+
+
+
+
+
+
+
+
+
+
+
+
+
{tax_periods?.merchant?.business_name ?? 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
PeriodType
+
{tax_periods?.period_type ?? 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
YearNumber
+
{tax_periods?.year_number || 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
PeriodNumber
+
{tax_periods?.period_number || 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {tax_periods.start_date ? : No StartDate
}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {tax_periods.end_date ? : No EndDate
}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {tax_periods.due_date ? : No DueDate
}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Status
+
{tax_periods?.status ?? 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
organizations
+
+
+
+
+
+
+
+
+
{tax_periods?.organizations?.name ?? 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <>
+ Vat_declarations TaxPeriod
+
+
+
+
+
+
+
+
+
+
+
+ Status
+
+
+
+ TotalSalesAmount
+
+
+
+ TaxableSalesAmount
+
+
+
+ OutputVATAmount
+
+
+
+ TotalPurchasesAmount
+
+
+
+ InputVATAmount
+
+
+
+ VATPayableAmount
+
+
+
+
+
+ GeneratedAt
+
+
+
+
+
+ ReviewedAt
+
+
+
+ Notes
+
+
+
+
+
+
+
+
+
+
+
+ {tax_periods.vat_declarations_tax_period && Array.isArray(tax_periods.vat_declarations_tax_period) &&
+ tax_periods.vat_declarations_tax_period.map((item: any) => (
+ router.push(`/vat_declarations/vat_declarations-view/?id=${item.id}`)}>
+
+
+
+
+
+
+
+ { item.status }
+
+
+
+
+
+ { item.total_sales_amount }
+
+
+
+
+
+ { item.taxable_sales_amount }
+
+
+
+
+
+ { item.output_vat_amount }
+
+
+
+
+
+ { item.total_purchases_amount }
+
+
+
+
+
+ { item.input_vat_amount }
+
+
+
+
+
+ { item.vat_payable_amount }
+
+
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.generated_at) }
+
+
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.reviewed_at) }
+
+
+
+
+
+ { item.notes }
+
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+ {!tax_periods?.vat_declarations_tax_period?.length && No data
}
+
+ >
+
+
+ <>
+ Tot_declarations TaxPeriod
+
+
+
+
+
+
+
+
+
+
+
+ Status
+
+
+
+ GrossSalesAmount
+
+
+
+ TOTRatePercent
+
+
+
+ TOTPayableAmount
+
+
+
+
+
+ GeneratedAt
+
+
+
+
+
+ ReviewedAt
+
+
+
+ Notes
+
+
+
+
+
+
+
+
+
+
+
+ {tax_periods.tot_declarations_tax_period && Array.isArray(tax_periods.tot_declarations_tax_period) &&
+ tax_periods.tot_declarations_tax_period.map((item: any) => (
+ router.push(`/tot_declarations/tot_declarations-view/?id=${item.id}`)}>
+
+
+
+
+
+
+
+ { item.status }
+
+
+
+
+
+ { item.gross_sales_amount }
+
+
+
+
+
+ { item.tot_rate_percent }
+
+
+
+
+
+ { item.tot_payable_amount }
+
+
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.generated_at) }
+
+
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.reviewed_at) }
+
+
+
+
+
+ { item.notes }
+
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+ {!tax_periods?.tot_declarations_tax_period?.length && No data
}
+
+ >
+
+
+ <>
+ Declaration_submissions TaxPeriod
+
+
+
+
+
+
+
+
+
+
+
+ DeclarationType
+
+
+
+ SubmissionReference
+
+
+
+ SubmittedAt
+
+
+
+
+
+ Status
+
+
+
+ ResponseMessage
+
+
+
+
+
+
+
+ {tax_periods.declaration_submissions_tax_period && Array.isArray(tax_periods.declaration_submissions_tax_period) &&
+ tax_periods.declaration_submissions_tax_period.map((item: any) => (
+ router.push(`/declaration_submissions/declaration_submissions-view/?id=${item.id}`)}>
+
+
+
+
+
+
+
+ { item.declaration_type }
+
+
+
+
+
+ { item.submission_reference }
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.submitted_at) }
+
+
+
+
+
+
+
+ { item.status }
+
+
+
+
+
+ { item.response_message }
+
+
+
+
+
+
+ ))}
+
+
+
+ {!tax_periods?.declaration_submissions_tax_period?.length && No data
}
+
+ >
+
+
+
+
+
+
+
+ router.push('/tax_periods/tax_periods-list')}
+ />
+
+
+ >
+ );
+};
+
+Tax_periodsView.getLayout = function getLayout(page: ReactElement) {
+ return (
+
+ {page}
+
+ )
+}
+
+export default Tax_periodsView;
\ No newline at end of file
diff --git a/frontend/src/pages/terms-of-use.tsx b/frontend/src/pages/terms-of-use.tsx
new file mode 100644
index 0000000..24c73d6
--- /dev/null
+++ b/frontend/src/pages/terms-of-use.tsx
@@ -0,0 +1,206 @@
+import React, { useEffect, useState } from 'react';
+import type { ReactElement } from 'react';
+import Head from 'next/head';
+import LayoutGuest from '../layouts/Guest';
+import { getPageTitle } from '../config';
+
+export default function PrivacyPolicy() {
+ const title = 'SmartHisab';
+ const [projectUrl, setProjectUrl] = useState('');
+
+ useEffect(() => {
+ setProjectUrl(location.origin);
+ }, []);
+
+ const Information = () => {
+ return (
+ <>
+ 1. Acceptance of Terms
+
+
+ By accessing and using our application, you agree to comply with and
+ be bound by these Terms of Use. If you do not agree to these terms,
+ please do not use the application.
+
+
+ >
+ );
+ };
+
+ const ChangesTerms = () => {
+ return (
+ <>
+ 2. Changes to Terms
+
+ We reserve the right to modify these Terms of Use at any time. Any
+ changes will be effective immediately upon posting. Your continued use
+ of the application after any such changes constitutes your acceptance
+ of the new terms.
+
+ >
+ );
+ };
+
+ const UseApplication = () => {
+ return (
+ <>
+ 3. Use of the Application
+
+ You agree to use the application only for lawful purposes and in a way
+ that does not infringe the rights of, restrict, or inhibit anyone
+ else’s use and enjoyment of the application. Prohibited behavior
+ includes harassing or causing distress or inconvenience to any other
+ user, transmitting obscene or offensive content, or disrupting the
+ normal flow of dialogue within the application.
+
+ >
+ );
+ };
+
+ const IntellectualProperty = () => {
+ return (
+ <>
+ 4. Intellectual Property
+
+ All content included on the application, such as text, graphics,
+ logos, images, and software, is the property of {title} or
+ its content suppliers and protected by international copyright laws.
+ Unauthorized use of the content may violate copyright, trademark, and
+ other laws.
+
+ >
+ );
+ };
+
+ const UserContent = () => {
+ return (
+ <>
+ 5. User Content
+
+ You are responsible for any content you upload, post, or otherwise
+ make available through the application. You grant {title}
+ a worldwide, irrevocable, non-exclusive, royalty-free license to use,
+ reproduce, modify, publish, and distribute such content for any
+ purpose.
+
+ >
+ );
+ };
+
+ const Privacy = () => {
+ return (
+ <>
+ 6. Privacy
+
+ Your privacy is important to us. Please review our Privacy Policy to
+ understand our practices regarding the collection, use, and disclosure
+ of your personal information.
+
+ >
+ );
+ };
+
+ const Liability = () => {
+ return (
+ <>
+ 7. Limitation of Liability
+
+ The application is provided “as is” and “as available” without any
+ warranties of any kind, either express or implied. {title}
+ does not warrant that the application will be uninterrupted or
+ error-free. In no event shall {title} be liable for any
+ damages arising out of your use of the application.
+
+ >
+ );
+ };
+
+ const Indemnification = () => {
+ return (
+ <>
+ 8. Indemnification
+
+ You agree to indemnify, defend, and hold harmless {title},
+ its officers, directors, employees, and agents from and against any
+ claims, liabilities, damages, losses, and expenses, including without
+ limitation reasonable legal and accounting fees, arising out of or in
+ any way connected with your access to or use of the application or
+ your violation of these Terms of Use.
+
+ >
+ );
+ };
+
+ const Termination = () => {
+ return (
+ <>
+ 9. Termination
+
+ We reserve the right to terminate or suspend your access to the
+ application at our sole discretion, without notice and without
+ liability, for any reason, including if we believe you have violated
+ these Terms of Use.
+
+ >
+ );
+ };
+
+ const GoverningLaw = () => {
+ return (
+ <>
+ 10. Governing Law
+
+ These Terms of Use are governed by and interpreted in accordance with
+ applicable laws, without regard to any conflict of law principles. You
+ agree to submit to the exclusive jurisdiction of the courts that have
+ authority to resolve any dispute arising from the use of the
+ application.
+
+ >
+ );
+ };
+
+ const ContactUs = () => {
+ return (
+ <>
+ 11. Contact Information
+
+ If you have any questions about these Terms of Use, please contact us
+ at: [support@flatlogic.com]
+
+ >
+ );
+ };
+
+ return (
+
+
+
{getPageTitle('Terms of Use')}
+
+
+
+
+
+
Terms of Use
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+PrivacyPolicy.getLayout = function getLayout(page: ReactElement) {
+ return {page} ;
+};
diff --git a/frontend/src/pages/tot_declarations/[tot_declarationsId].tsx b/frontend/src/pages/tot_declarations/[tot_declarationsId].tsx
new file mode 100644
index 0000000..1c5a5c5
--- /dev/null
+++ b/frontend/src/pages/tot_declarations/[tot_declarationsId].tsx
@@ -0,0 +1,1398 @@
+import { mdiChartTimelineVariant, mdiUpload } from '@mdi/js'
+import Head from 'next/head'
+import React, { ReactElement, useEffect, useState } from 'react'
+import DatePicker from "react-datepicker";
+import "react-datepicker/dist/react-datepicker.css";
+import dayjs from "dayjs";
+
+import CardBox from '../../components/CardBox'
+import LayoutAuthenticated from '../../layouts/Authenticated'
+import SectionMain from '../../components/SectionMain'
+import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'
+import { getPageTitle } from '../../config'
+
+import { Field, Form, Formik } from 'formik'
+import FormField from '../../components/FormField'
+import BaseDivider from '../../components/BaseDivider'
+import BaseButtons from '../../components/BaseButtons'
+import BaseButton from '../../components/BaseButton'
+import FormCheckRadio from '../../components/FormCheckRadio'
+import FormCheckRadioGroup from '../../components/FormCheckRadioGroup'
+import FormFilePicker from '../../components/FormFilePicker'
+import FormImagePicker from '../../components/FormImagePicker'
+import { SelectField } from "../../components/SelectField";
+import { SelectFieldMany } from "../../components/SelectFieldMany";
+import { SwitchField } from '../../components/SwitchField'
+import {RichTextField} from "../../components/RichTextField";
+
+import { update, fetch } from '../../stores/tot_declarations/tot_declarationsSlice'
+import { useAppDispatch, useAppSelector } from '../../stores/hooks'
+import { useRouter } from 'next/router'
+import {saveFile} from "../../helpers/fileSaver";
+import dataFormatter from '../../helpers/dataFormatter';
+import ImageField from "../../components/ImageField";
+
+import {hasPermission} from "../../helpers/userPermissions";
+
+
+
+const EditTot_declarations = () => {
+ const router = useRouter()
+ const dispatch = useAppDispatch()
+ const initVals = {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ merchant: null,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tax_period: null,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ status: '',
+
+
+
+
+
+
+
+
+
+
+
+ 'gross_sales_amount': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'tot_rate_percent': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'tot_payable_amount': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generated_by: null,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generated_at: new Date(),
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ reviewed_by: null,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ reviewed_at: new Date(),
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ notes: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pdf_file: [],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ excel_file: [],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ revenue_office_export_file: [],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ organizations: null,
+
+
+
+
+
+ }
+ const [initialValues, setInitialValues] = useState(initVals)
+
+ const { tot_declarations } = useAppSelector((state) => state.tot_declarations)
+
+ const { currentUser } = useAppSelector((state) => state.auth);
+
+
+ const { tot_declarationsId } = router.query
+
+ useEffect(() => {
+ dispatch(fetch({ id: tot_declarationsId }))
+ }, [tot_declarationsId])
+
+ useEffect(() => {
+ if (typeof tot_declarations === 'object') {
+ setInitialValues(tot_declarations)
+ }
+ }, [tot_declarations])
+
+ useEffect(() => {
+ if (typeof tot_declarations === 'object') {
+
+ const newInitialVal = {...initVals};
+
+ Object.keys(initVals).forEach(el => newInitialVal[el] = (tot_declarations)[el])
+
+ setInitialValues(newInitialVal);
+ }
+ }, [tot_declarations])
+
+ const handleSubmit = async (data) => {
+ await dispatch(update({ id: tot_declarationsId, data }))
+ await router.push('/tot_declarations/tot_declarations-list')
+ }
+
+ return (
+ <>
+
+ {getPageTitle('Edit tot_declarations')}
+
+
+
+ {''}
+
+
+ handleSubmit(values)}
+ >
+
+
+
+
+ >
+ )
+}
+
+EditTot_declarations.getLayout = function getLayout(page: ReactElement) {
+ return (
+
+ {page}
+
+ )
+}
+
+export default EditTot_declarations
diff --git a/frontend/src/pages/tot_declarations/tot_declarations-edit.tsx b/frontend/src/pages/tot_declarations/tot_declarations-edit.tsx
new file mode 100644
index 0000000..15a1778
--- /dev/null
+++ b/frontend/src/pages/tot_declarations/tot_declarations-edit.tsx
@@ -0,0 +1,1395 @@
+import { mdiChartTimelineVariant, mdiUpload } from '@mdi/js'
+import Head from 'next/head'
+import React, { ReactElement, useEffect, useState } from 'react'
+import DatePicker from "react-datepicker";
+import "react-datepicker/dist/react-datepicker.css";
+import dayjs from "dayjs";
+
+import CardBox from '../../components/CardBox'
+import LayoutAuthenticated from '../../layouts/Authenticated'
+import SectionMain from '../../components/SectionMain'
+import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'
+import { getPageTitle } from '../../config'
+
+import { Field, Form, Formik } from 'formik'
+import FormField from '../../components/FormField'
+import BaseDivider from '../../components/BaseDivider'
+import BaseButtons from '../../components/BaseButtons'
+import BaseButton from '../../components/BaseButton'
+import FormCheckRadio from '../../components/FormCheckRadio'
+import FormCheckRadioGroup from '../../components/FormCheckRadioGroup'
+import FormFilePicker from '../../components/FormFilePicker'
+import FormImagePicker from '../../components/FormImagePicker'
+import { SelectField } from "../../components/SelectField";
+import { SelectFieldMany } from "../../components/SelectFieldMany";
+import { SwitchField } from '../../components/SwitchField'
+import {RichTextField} from "../../components/RichTextField";
+
+import { update, fetch } from '../../stores/tot_declarations/tot_declarationsSlice'
+import { useAppDispatch, useAppSelector } from '../../stores/hooks'
+import { useRouter } from 'next/router'
+import {saveFile} from "../../helpers/fileSaver";
+import dataFormatter from '../../helpers/dataFormatter';
+import ImageField from "../../components/ImageField";
+
+import {hasPermission} from "../../helpers/userPermissions";
+
+
+
+const EditTot_declarationsPage = () => {
+ const router = useRouter()
+ const dispatch = useAppDispatch()
+ const initVals = {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ merchant: null,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tax_period: null,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ status: '',
+
+
+
+
+
+
+
+
+
+
+
+ 'gross_sales_amount': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'tot_rate_percent': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'tot_payable_amount': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generated_by: null,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generated_at: new Date(),
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ reviewed_by: null,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ reviewed_at: new Date(),
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ notes: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pdf_file: [],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ excel_file: [],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ revenue_office_export_file: [],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ organizations: null,
+
+
+
+
+
+ }
+ const [initialValues, setInitialValues] = useState(initVals)
+
+ const { tot_declarations } = useAppSelector((state) => state.tot_declarations)
+
+ const { currentUser } = useAppSelector((state) => state.auth);
+
+
+ const { id } = router.query
+
+ useEffect(() => {
+ dispatch(fetch({ id: id }))
+ }, [id])
+
+ useEffect(() => {
+ if (typeof tot_declarations === 'object') {
+ setInitialValues(tot_declarations)
+ }
+ }, [tot_declarations])
+
+ useEffect(() => {
+ if (typeof tot_declarations === 'object') {
+ const newInitialVal = {...initVals};
+ Object.keys(initVals).forEach(el => newInitialVal[el] = (tot_declarations)[el])
+ setInitialValues(newInitialVal);
+ }
+ }, [tot_declarations])
+
+ const handleSubmit = async (data) => {
+ await dispatch(update({ id: id, data }))
+ await router.push('/tot_declarations/tot_declarations-list')
+ }
+
+ return (
+ <>
+
+ {getPageTitle('Edit tot_declarations')}
+
+
+
+ {''}
+
+
+ handleSubmit(values)}
+ >
+
+
+
+
+ >
+ )
+}
+
+EditTot_declarationsPage.getLayout = function getLayout(page: ReactElement) {
+ return (
+
+ {page}
+
+ )
+}
+
+export default EditTot_declarationsPage
diff --git a/frontend/src/pages/tot_declarations/tot_declarations-list.tsx b/frontend/src/pages/tot_declarations/tot_declarations-list.tsx
new file mode 100644
index 0000000..0923980
--- /dev/null
+++ b/frontend/src/pages/tot_declarations/tot_declarations-list.tsx
@@ -0,0 +1,180 @@
+import { mdiChartTimelineVariant } from '@mdi/js'
+import Head from 'next/head'
+import { uniqueId } from 'lodash';
+import React, { ReactElement, useState } from 'react'
+import CardBox from '../../components/CardBox'
+import LayoutAuthenticated from '../../layouts/Authenticated'
+import SectionMain from '../../components/SectionMain'
+import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'
+import { getPageTitle } from '../../config'
+import TableTot_declarations from '../../components/Tot_declarations/TableTot_declarations'
+import BaseButton from '../../components/BaseButton'
+import axios from "axios";
+import Link from "next/link";
+import {useAppDispatch, useAppSelector} from "../../stores/hooks";
+import CardBoxModal from "../../components/CardBoxModal";
+import DragDropFilePicker from "../../components/DragDropFilePicker";
+import {setRefetch, uploadCsv} from '../../stores/tot_declarations/tot_declarationsSlice';
+
+
+import {hasPermission} from "../../helpers/userPermissions";
+
+
+
+const Tot_declarationsTablesPage = () => {
+ const [filterItems, setFilterItems] = useState([]);
+ const [csvFile, setCsvFile] = useState(null);
+ const [isModalActive, setIsModalActive] = useState(false);
+ const [showTableView, setShowTableView] = useState(false);
+
+
+ const { currentUser } = useAppSelector((state) => state.auth);
+
+
+ const dispatch = useAppDispatch();
+
+
+ const [filters] = useState([{label: 'Notes', title: 'notes'},
+
+ {label: 'GrossSalesAmount', title: 'gross_sales_amount', number: 'true'},{label: 'TOTRatePercent', title: 'tot_rate_percent', number: 'true'},{label: 'TOTPayableAmount', title: 'tot_payable_amount', number: 'true'},
+ {label: 'GeneratedAt', title: 'generated_at', date: 'true'},{label: 'ReviewedAt', title: 'reviewed_at', date: 'true'},
+
+
+ {label: 'Merchant', title: 'merchant'},
+
+
+
+ {label: 'TaxPeriod', title: 'tax_period'},
+
+
+
+ {label: 'GeneratedBy', title: 'generated_by'},
+
+
+
+ {label: 'ReviewedBy', title: 'reviewed_by'},
+
+
+
+ {label: 'Status', title: 'status', type: 'enum', options: ['draft','generated','reviewed','submitted','accepted','rejected','amended']},
+ ]);
+
+ const hasCreatePermission = currentUser && hasPermission(currentUser, 'CREATE_TOT_DECLARATIONS');
+
+
+ const addFilter = () => {
+ const newItem = {
+ id: uniqueId(),
+ fields: {
+ filterValue: '',
+ filterValueFrom: '',
+ filterValueTo: '',
+ selectedField: '',
+ },
+ };
+ newItem.fields.selectedField = filters[0].title;
+ setFilterItems([...filterItems, newItem]);
+ };
+
+ const getTot_declarationsCSV = async () => {
+ const response = await axios({url: '/tot_declarations?filetype=csv', method: 'GET',responseType: 'blob'});
+ const type = response.headers['content-type']
+ const blob = new Blob([response.data], { type: type })
+ const link = document.createElement('a')
+ link.href = window.URL.createObjectURL(blob)
+ link.download = 'tot_declarationsCSV.csv'
+ link.click()
+ };
+
+ const onModalConfirm = async () => {
+ if (!csvFile) return;
+ await dispatch(uploadCsv(csvFile));
+ dispatch(setRefetch(true));
+ setCsvFile(null);
+ setIsModalActive(false);
+ };
+
+ const onModalCancel = () => {
+ setCsvFile(null);
+ setIsModalActive(false);
+ };
+
+ return (
+ <>
+
+ {getPageTitle('Tot_declarations')}
+
+
+
+ {''}
+
+
+
+ {hasCreatePermission && }
+
+
+
+
+ {hasCreatePermission && (
+ setIsModalActive(true)}
+ />
+ )}
+
+
+
+
+ Switch to Table
+
+
+
+
+
+
+
+
+
+
+ >
+ )
+}
+
+Tot_declarationsTablesPage.getLayout = function getLayout(page: ReactElement) {
+ return (
+
+ {page}
+
+ )
+}
+
+export default Tot_declarationsTablesPage
diff --git a/frontend/src/pages/tot_declarations/tot_declarations-new.tsx b/frontend/src/pages/tot_declarations/tot_declarations-new.tsx
new file mode 100644
index 0000000..fce3409
--- /dev/null
+++ b/frontend/src/pages/tot_declarations/tot_declarations-new.tsx
@@ -0,0 +1,865 @@
+import { mdiAccount, mdiChartTimelineVariant, mdiMail, mdiUpload } from '@mdi/js'
+import Head from 'next/head'
+import React, { ReactElement } from 'react'
+import CardBox from '../../components/CardBox'
+import LayoutAuthenticated from '../../layouts/Authenticated'
+import SectionMain from '../../components/SectionMain'
+import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'
+import { getPageTitle } from '../../config'
+
+import { Field, Form, Formik } from 'formik'
+import FormField from '../../components/FormField'
+import BaseDivider from '../../components/BaseDivider'
+import BaseButtons from '../../components/BaseButtons'
+import BaseButton from '../../components/BaseButton'
+import FormCheckRadio from '../../components/FormCheckRadio'
+import FormCheckRadioGroup from '../../components/FormCheckRadioGroup'
+import FormFilePicker from '../../components/FormFilePicker'
+import FormImagePicker from '../../components/FormImagePicker'
+import { SwitchField } from '../../components/SwitchField'
+
+import { SelectField } from '../../components/SelectField'
+import { SelectFieldMany } from "../../components/SelectFieldMany";
+import {RichTextField} from "../../components/RichTextField";
+
+import { create } from '../../stores/tot_declarations/tot_declarationsSlice'
+import { useAppDispatch } from '../../stores/hooks'
+import { useRouter } from 'next/router'
+import moment from 'moment';
+
+const initialValues = {
+
+
+
+
+
+
+
+
+
+
+
+
+
+ merchant: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tax_period: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+ status: 'draft',
+
+
+
+
+
+
+
+ gross_sales_amount: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tot_rate_percent: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tot_payable_amount: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generated_by: '',
+
+
+
+
+
+
+
+
+
+ generated_at: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ reviewed_by: '',
+
+
+
+
+
+
+
+
+
+ reviewed_at: '',
+
+
+
+
+
+
+
+
+
+
+
+ notes: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pdf_file: [],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ excel_file: [],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ revenue_office_export_file: [],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ organizations: '',
+
+
+
+}
+
+
+const Tot_declarationsNew = () => {
+ const router = useRouter()
+ const dispatch = useAppDispatch()
+
+
+
+
+ const handleSubmit = async (data) => {
+ await dispatch(create(data))
+ await router.push('/tot_declarations/tot_declarations-list')
+ }
+ return (
+ <>
+
+ {getPageTitle('New Item')}
+
+
+
+ {''}
+
+
+ handleSubmit(values)}
+ >
+
+
+
+
+ >
+ )
+}
+
+Tot_declarationsNew.getLayout = function getLayout(page: ReactElement) {
+ return (
+
+ {page}
+
+ )
+}
+
+export default Tot_declarationsNew
diff --git a/frontend/src/pages/tot_declarations/tot_declarations-table.tsx b/frontend/src/pages/tot_declarations/tot_declarations-table.tsx
new file mode 100644
index 0000000..f19b506
--- /dev/null
+++ b/frontend/src/pages/tot_declarations/tot_declarations-table.tsx
@@ -0,0 +1,180 @@
+import { mdiChartTimelineVariant } from '@mdi/js'
+import Head from 'next/head'
+import { uniqueId } from 'lodash';
+import React, { ReactElement, useState } from 'react'
+import CardBox from '../../components/CardBox'
+import LayoutAuthenticated from '../../layouts/Authenticated'
+import SectionMain from '../../components/SectionMain'
+import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'
+import { getPageTitle } from '../../config'
+import TableTot_declarations from '../../components/Tot_declarations/TableTot_declarations'
+import BaseButton from '../../components/BaseButton'
+import axios from "axios";
+import Link from "next/link";
+import {useAppDispatch, useAppSelector} from "../../stores/hooks";
+import CardBoxModal from "../../components/CardBoxModal";
+import DragDropFilePicker from "../../components/DragDropFilePicker";
+import {setRefetch, uploadCsv} from '../../stores/tot_declarations/tot_declarationsSlice';
+
+
+import {hasPermission} from "../../helpers/userPermissions";
+
+
+
+const Tot_declarationsTablesPage = () => {
+ const [filterItems, setFilterItems] = useState([]);
+ const [csvFile, setCsvFile] = useState(null);
+ const [isModalActive, setIsModalActive] = useState(false);
+ const [showTableView, setShowTableView] = useState(false);
+
+
+ const { currentUser } = useAppSelector((state) => state.auth);
+
+
+ const dispatch = useAppDispatch();
+
+
+ const [filters] = useState([{label: 'Notes', title: 'notes'},
+
+ {label: 'GrossSalesAmount', title: 'gross_sales_amount', number: 'true'},{label: 'TOTRatePercent', title: 'tot_rate_percent', number: 'true'},{label: 'TOTPayableAmount', title: 'tot_payable_amount', number: 'true'},
+ {label: 'GeneratedAt', title: 'generated_at', date: 'true'},{label: 'ReviewedAt', title: 'reviewed_at', date: 'true'},
+
+
+ {label: 'Merchant', title: 'merchant'},
+
+
+
+ {label: 'TaxPeriod', title: 'tax_period'},
+
+
+
+ {label: 'GeneratedBy', title: 'generated_by'},
+
+
+
+ {label: 'ReviewedBy', title: 'reviewed_by'},
+
+
+
+ {label: 'Status', title: 'status', type: 'enum', options: ['draft','generated','reviewed','submitted','accepted','rejected','amended']},
+ ]);
+
+ const hasCreatePermission = currentUser && hasPermission(currentUser, 'CREATE_TOT_DECLARATIONS');
+
+
+ const addFilter = () => {
+ const newItem = {
+ id: uniqueId(),
+ fields: {
+ filterValue: '',
+ filterValueFrom: '',
+ filterValueTo: '',
+ selectedField: '',
+ },
+ };
+ newItem.fields.selectedField = filters[0].title;
+ setFilterItems([...filterItems, newItem]);
+ };
+
+ const getTot_declarationsCSV = async () => {
+ const response = await axios({url: '/tot_declarations?filetype=csv', method: 'GET',responseType: 'blob'});
+ const type = response.headers['content-type']
+ const blob = new Blob([response.data], { type: type })
+ const link = document.createElement('a')
+ link.href = window.URL.createObjectURL(blob)
+ link.download = 'tot_declarationsCSV.csv'
+ link.click()
+ };
+
+ const onModalConfirm = async () => {
+ if (!csvFile) return;
+ await dispatch(uploadCsv(csvFile));
+ dispatch(setRefetch(true));
+ setCsvFile(null);
+ setIsModalActive(false);
+ };
+
+ const onModalCancel = () => {
+ setCsvFile(null);
+ setIsModalActive(false);
+ };
+
+ return (
+ <>
+
+ {getPageTitle('Tot_declarations')}
+
+
+
+ {''}
+
+
+
+ {hasCreatePermission && }
+
+
+
+
+ {hasCreatePermission && (
+ setIsModalActive(true)}
+ />
+ )}
+
+
+
+
+
+ Back to
kanban
+
+
+
+
+
+
+
+
+
+
+
+ >
+ )
+}
+
+Tot_declarationsTablesPage.getLayout = function getLayout(page: ReactElement) {
+ return (
+
+ {page}
+
+ )
+}
+
+export default Tot_declarationsTablesPage
diff --git a/frontend/src/pages/tot_declarations/tot_declarations-view.tsx b/frontend/src/pages/tot_declarations/tot_declarations-view.tsx
new file mode 100644
index 0000000..be023ea
--- /dev/null
+++ b/frontend/src/pages/tot_declarations/tot_declarations-view.tsx
@@ -0,0 +1,873 @@
+import React, { ReactElement, useEffect } from 'react';
+import Head from 'next/head'
+import DatePicker from "react-datepicker";
+import "react-datepicker/dist/react-datepicker.css";
+import dayjs from "dayjs";
+import {useAppDispatch, useAppSelector} from "../../stores/hooks";
+import {useRouter} from "next/router";
+import { fetch } from '../../stores/tot_declarations/tot_declarationsSlice'
+import {saveFile} from "../../helpers/fileSaver";
+import dataFormatter from '../../helpers/dataFormatter';
+import ImageField from "../../components/ImageField";
+import LayoutAuthenticated from "../../layouts/Authenticated";
+import {getPageTitle} from "../../config";
+import SectionTitleLineWithButton from "../../components/SectionTitleLineWithButton";
+import SectionMain from "../../components/SectionMain";
+import CardBox from "../../components/CardBox";
+import BaseButton from "../../components/BaseButton";
+import BaseDivider from "../../components/BaseDivider";
+import {mdiChartTimelineVariant} from "@mdi/js";
+import {SwitchField} from "../../components/SwitchField";
+import FormField from "../../components/FormField";
+
+import {hasPermission} from "../../helpers/userPermissions";
+
+
+const Tot_declarationsView = () => {
+ const router = useRouter()
+ const dispatch = useAppDispatch()
+ const { tot_declarations } = useAppSelector((state) => state.tot_declarations)
+
+ const { currentUser } = useAppSelector((state) => state.auth);
+
+
+ const { id } = router.query;
+
+ function removeLastCharacter(str) {
+ console.log(str,`str`)
+ return str.slice(0, -1);
+ }
+
+ useEffect(() => {
+ dispatch(fetch({ id }));
+ }, [dispatch, id]);
+
+
+ return (
+ <>
+
+ {getPageTitle('View tot_declarations')}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Merchant
+
+
+
+
+
+
+
+
+
+
+
+
+
{tot_declarations?.merchant?.business_name ?? 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
TaxPeriod
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{tot_declarations?.tax_period?.status ?? 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Status
+
{tot_declarations?.status ?? 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
GrossSalesAmount
+
{tot_declarations?.gross_sales_amount || 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
TOTRatePercent
+
{tot_declarations?.tot_rate_percent || 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
TOTPayableAmount
+
{tot_declarations?.tot_payable_amount || 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
GeneratedBy
+
+
+
{tot_declarations?.generated_by?.firstName ?? 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {tot_declarations.generated_at ? : No GeneratedAt
}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ReviewedBy
+
+
+
{tot_declarations?.reviewed_by?.firstName ?? 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {tot_declarations.reviewed_at ? : No ReviewedAt
}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
PDFFile
+ {tot_declarations?.pdf_file?.length
+ ? dataFormatter.filesFormatter(tot_declarations.pdf_file).map(link => (
+
saveFile(e, link.publicUrl, link.name)}
+ >
+ {link.name}
+
+ )) :
No PDFFile
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ExcelFile
+ {tot_declarations?.excel_file?.length
+ ? dataFormatter.filesFormatter(tot_declarations.excel_file).map(link => (
+
saveFile(e, link.publicUrl, link.name)}
+ >
+ {link.name}
+
+ )) :
No ExcelFile
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
RevenueOfficeExportFile
+ {tot_declarations?.revenue_office_export_file?.length
+ ? dataFormatter.filesFormatter(tot_declarations.revenue_office_export_file).map(link => (
+
saveFile(e, link.publicUrl, link.name)}
+ >
+ {link.name}
+
+ )) :
No RevenueOfficeExportFile
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
organizations
+
+
+
+
+
+
+
+
+
{tot_declarations?.organizations?.name ?? 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ router.push('/tot_declarations/tot_declarations-list')}
+ />
+
+
+ >
+ );
+};
+
+Tot_declarationsView.getLayout = function getLayout(page: ReactElement) {
+ return (
+
+ {page}
+
+ )
+}
+
+export default Tot_declarationsView;
\ No newline at end of file
diff --git a/frontend/src/pages/transaction-entry.tsx b/frontend/src/pages/transaction-entry.tsx
new file mode 100644
index 0000000..500439d
--- /dev/null
+++ b/frontend/src/pages/transaction-entry.tsx
@@ -0,0 +1,145 @@
+import * as icon from '@mdi/js';
+import Head from 'next/head';
+import React, { ReactElement } from 'react';
+import LayoutAuthenticated from '../layouts/Authenticated';
+import SectionMain from '../components/SectionMain';
+import BaseIcon from '../components/BaseIcon';
+import BaseButton from '../components/BaseButton';
+import { getPageTitle } from '../config';
+import { useAppSelector } from '../stores/hooks';
+import Link from 'next/link';
+
+const TransactionEntry = () => {
+ const { currentUser } = useAppSelector((state) => state.auth);
+ const organizationName = currentUser?.organization?.name || 'SmartHisab';
+
+ const transactionTypes = [
+ {
+ title: 'Purchase Entry Form',
+ titleAm: 'የግዢ መዝገብ',
+ description: 'Record purchase transactions with VAT and withholding tax calculations',
+ color: 'orange',
+ icon: icon.mdiPackageVariantClosed,
+ href: '/purchase_invoices/purchase_invoices-new',
+ bgColor: 'bg-orange-50',
+ borderColor: 'border-orange-100',
+ iconBg: 'bg-orange-100',
+ iconColor: 'text-orange-600',
+ buttonBg: 'bg-orange-600',
+ dotColor: 'bg-orange-400',
+ },
+ {
+ title: 'Sales Entry Form',
+ titleAm: 'የሽያጭ መዝገብ',
+ description: 'Record sales transactions with VAT calculations',
+ color: 'green',
+ icon: icon.mdiCartOutline,
+ href: '/sales_invoices/sales_invoices-new',
+ bgColor: 'bg-emerald-50',
+ borderColor: 'border-emerald-100',
+ iconBg: 'bg-emerald-100',
+ iconColor: 'text-emerald-600',
+ buttonBg: 'bg-emerald-600',
+ dotColor: 'bg-emerald-400',
+ },
+ {
+ title: 'Expense Entry Form',
+ titleAm: 'ወጪ መዝገብ',
+ description: 'Record business expenses and operating costs',
+ color: 'red',
+ icon: icon.mdiCurrencyUsd,
+ href: '/expenses/expenses-new',
+ bgColor: 'bg-red-50',
+ borderColor: 'border-red-100',
+ iconBg: 'bg-red-100',
+ iconColor: 'text-red-600',
+ buttonBg: 'bg-red-600',
+ dotColor: 'bg-red-400',
+ },
+ {
+ title: 'Inventory Entry Form',
+ titleAm: 'እቃ መዝገብ',
+ description: 'Track inventory purchases and stock additions',
+ color: 'purple',
+ icon: icon.mdiCubeOutline,
+ href: '/products/products-new',
+ bgColor: 'bg-indigo-50',
+ borderColor: 'border-indigo-100',
+ iconBg: 'bg-indigo-100',
+ iconColor: 'text-indigo-600',
+ buttonBg: 'bg-indigo-600',
+ dotColor: 'bg-indigo-400',
+ },
+ {
+ title: 'All Transactions',
+ titleAm: 'ግብይቶች',
+ description: 'View and manage all tax transactions',
+ color: 'teal',
+ icon: icon.mdiViewList,
+ href: '/sales_invoices/sales_invoices-list',
+ bgColor: 'bg-cyan-50',
+ borderColor: 'border-cyan-100',
+ iconBg: 'bg-cyan-100',
+ iconColor: 'text-cyan-600',
+ buttonBg: 'bg-cyan-600',
+ dotColor: 'bg-cyan-400',
+ },
+ ];
+
+ return (
+ <>
+
+ {getPageTitle('Transaction Entry')}
+
+
+
+
የግብይት አይነት ይምረጡ
+
+ Choose the type of transaction you want to record
+
+
+ {organizationName}
+
+
+
+
+ {transactionTypes.map((type, index) => (
+
+
+
+
+
+
+
+
+
{type.titleAm}
+
{type.title}
+
+ {type.description}
+
+
+
+
+
+ Open Form
+
+
+
+
+ ))}
+
+
+ >
+ );
+};
+
+TransactionEntry.getLayout = function getLayout(page: ReactElement) {
+ return {page} ;
+};
+
+export default TransactionEntry;
diff --git a/frontend/src/pages/users/[usersId].tsx b/frontend/src/pages/users/[usersId].tsx
new file mode 100644
index 0000000..a6081ec
--- /dev/null
+++ b/frontend/src/pages/users/[usersId].tsx
@@ -0,0 +1,878 @@
+import { mdiChartTimelineVariant, mdiUpload } from '@mdi/js'
+import Head from 'next/head'
+import React, { ReactElement, useEffect, useState } from 'react'
+import DatePicker from "react-datepicker";
+import "react-datepicker/dist/react-datepicker.css";
+import dayjs from "dayjs";
+
+import CardBox from '../../components/CardBox'
+import LayoutAuthenticated from '../../layouts/Authenticated'
+import SectionMain from '../../components/SectionMain'
+import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'
+import { getPageTitle } from '../../config'
+
+import { Field, Form, Formik } from 'formik'
+import FormField from '../../components/FormField'
+import BaseDivider from '../../components/BaseDivider'
+import BaseButtons from '../../components/BaseButtons'
+import BaseButton from '../../components/BaseButton'
+import FormCheckRadio from '../../components/FormCheckRadio'
+import FormCheckRadioGroup from '../../components/FormCheckRadioGroup'
+import FormFilePicker from '../../components/FormFilePicker'
+import FormImagePicker from '../../components/FormImagePicker'
+import { SelectField } from "../../components/SelectField";
+import { SelectFieldMany } from "../../components/SelectFieldMany";
+import { SwitchField } from '../../components/SwitchField'
+import {RichTextField} from "../../components/RichTextField";
+
+import { update, fetch } from '../../stores/users/usersSlice'
+import { useAppDispatch, useAppSelector } from '../../stores/hooks'
+import { useRouter } from 'next/router'
+import {saveFile} from "../../helpers/fileSaver";
+import dataFormatter from '../../helpers/dataFormatter';
+import ImageField from "../../components/ImageField";
+
+import {hasPermission} from "../../helpers/userPermissions";
+
+
+
+const EditUsers = () => {
+ const router = useRouter()
+ const dispatch = useAppDispatch()
+ const initVals = {
+
+
+ 'firstName': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'lastName': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'phoneNumber': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'email': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ disabled: false,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ avatar: [],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ app_role: null,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ custom_permissions: [],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ organizations: null,
+
+
+
+
+
+ password: ''
+
+ }
+ const [initialValues, setInitialValues] = useState(initVals)
+
+ const { users } = useAppSelector((state) => state.users)
+
+ const { currentUser } = useAppSelector((state) => state.auth);
+
+
+ const { usersId } = router.query
+
+ useEffect(() => {
+ dispatch(fetch({ id: usersId }))
+ }, [usersId])
+
+ useEffect(() => {
+ if (typeof users === 'object') {
+ setInitialValues(users)
+ }
+ }, [users])
+
+ useEffect(() => {
+ if (typeof users === 'object') {
+
+ const newInitialVal = {...initVals};
+
+ Object.keys(initVals).forEach(el => newInitialVal[el] = (users)[el])
+
+ setInitialValues(newInitialVal);
+ }
+ }, [users])
+
+ const handleSubmit = async (data) => {
+ await dispatch(update({ id: usersId, data }))
+ await router.push('/users/users-list')
+ }
+
+ return (
+ <>
+
+ {getPageTitle('Edit users')}
+
+
+
+ {''}
+
+
+ handleSubmit(values)}
+ >
+
+
+
+
+ >
+ )
+}
+
+EditUsers.getLayout = function getLayout(page: ReactElement) {
+ return (
+
+ {page}
+
+ )
+}
+
+export default EditUsers
diff --git a/frontend/src/pages/users/users-edit.tsx b/frontend/src/pages/users/users-edit.tsx
new file mode 100644
index 0000000..c1da7b1
--- /dev/null
+++ b/frontend/src/pages/users/users-edit.tsx
@@ -0,0 +1,875 @@
+import { mdiChartTimelineVariant, mdiUpload } from '@mdi/js'
+import Head from 'next/head'
+import React, { ReactElement, useEffect, useState } from 'react'
+import DatePicker from "react-datepicker";
+import "react-datepicker/dist/react-datepicker.css";
+import dayjs from "dayjs";
+
+import CardBox from '../../components/CardBox'
+import LayoutAuthenticated from '../../layouts/Authenticated'
+import SectionMain from '../../components/SectionMain'
+import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'
+import { getPageTitle } from '../../config'
+
+import { Field, Form, Formik } from 'formik'
+import FormField from '../../components/FormField'
+import BaseDivider from '../../components/BaseDivider'
+import BaseButtons from '../../components/BaseButtons'
+import BaseButton from '../../components/BaseButton'
+import FormCheckRadio from '../../components/FormCheckRadio'
+import FormCheckRadioGroup from '../../components/FormCheckRadioGroup'
+import FormFilePicker from '../../components/FormFilePicker'
+import FormImagePicker from '../../components/FormImagePicker'
+import { SelectField } from "../../components/SelectField";
+import { SelectFieldMany } from "../../components/SelectFieldMany";
+import { SwitchField } from '../../components/SwitchField'
+import {RichTextField} from "../../components/RichTextField";
+
+import { update, fetch } from '../../stores/users/usersSlice'
+import { useAppDispatch, useAppSelector } from '../../stores/hooks'
+import { useRouter } from 'next/router'
+import {saveFile} from "../../helpers/fileSaver";
+import dataFormatter from '../../helpers/dataFormatter';
+import ImageField from "../../components/ImageField";
+
+import {hasPermission} from "../../helpers/userPermissions";
+
+
+
+const EditUsersPage = () => {
+ const router = useRouter()
+ const dispatch = useAppDispatch()
+ const initVals = {
+
+
+ 'firstName': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'lastName': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'phoneNumber': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'email': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ disabled: false,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ avatar: [],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ app_role: null,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ custom_permissions: [],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ organizations: null,
+
+
+
+
+
+ password: ''
+
+ }
+ const [initialValues, setInitialValues] = useState(initVals)
+
+ const { users } = useAppSelector((state) => state.users)
+
+ const { currentUser } = useAppSelector((state) => state.auth);
+
+
+ const { id } = router.query
+
+ useEffect(() => {
+ dispatch(fetch({ id: id }))
+ }, [id])
+
+ useEffect(() => {
+ if (typeof users === 'object') {
+ setInitialValues(users)
+ }
+ }, [users])
+
+ useEffect(() => {
+ if (typeof users === 'object') {
+ const newInitialVal = {...initVals};
+ Object.keys(initVals).forEach(el => newInitialVal[el] = (users)[el])
+ setInitialValues(newInitialVal);
+ }
+ }, [users])
+
+ const handleSubmit = async (data) => {
+ await dispatch(update({ id: id, data }))
+ await router.push('/users/users-list')
+ }
+
+ return (
+ <>
+
+ {getPageTitle('Edit users')}
+
+
+
+ {''}
+
+
+ handleSubmit(values)}
+ >
+
+
+
+
+ >
+ )
+}
+
+EditUsersPage.getLayout = function getLayout(page: ReactElement) {
+ return (
+
+ {page}
+
+ )
+}
+
+export default EditUsersPage
diff --git a/frontend/src/pages/users/users-list.tsx b/frontend/src/pages/users/users-list.tsx
new file mode 100644
index 0000000..a90ec62
--- /dev/null
+++ b/frontend/src/pages/users/users-list.tsx
@@ -0,0 +1,168 @@
+import { mdiChartTimelineVariant } from '@mdi/js'
+import Head from 'next/head'
+import { uniqueId } from 'lodash';
+import React, { ReactElement, useState } from 'react'
+import CardBox from '../../components/CardBox'
+import LayoutAuthenticated from '../../layouts/Authenticated'
+import SectionMain from '../../components/SectionMain'
+import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'
+import { getPageTitle } from '../../config'
+import TableUsers from '../../components/Users/TableUsers'
+import BaseButton from '../../components/BaseButton'
+import axios from "axios";
+import Link from "next/link";
+import {useAppDispatch, useAppSelector} from "../../stores/hooks";
+import CardBoxModal from "../../components/CardBoxModal";
+import DragDropFilePicker from "../../components/DragDropFilePicker";
+import {setRefetch, uploadCsv} from '../../stores/users/usersSlice';
+
+
+import {hasPermission} from "../../helpers/userPermissions";
+
+
+
+const UsersTablesPage = () => {
+ const [filterItems, setFilterItems] = useState([]);
+ const [csvFile, setCsvFile] = useState(null);
+ const [isModalActive, setIsModalActive] = useState(false);
+ const [showTableView, setShowTableView] = useState(false);
+
+
+ const { currentUser } = useAppSelector((state) => state.auth);
+
+
+ const dispatch = useAppDispatch();
+
+
+ const [filters] = useState([{label: 'First Name', title: 'firstName'},{label: 'Last Name', title: 'lastName'},{label: 'Phone Number', title: 'phoneNumber'},{label: 'E-Mail', title: 'email'},
+
+
+
+
+
+ {label: 'App Role', title: 'app_role'},
+
+
+
+
+ {label: 'Custom Permissions', title: 'custom_permissions'},
+
+ ]);
+
+ const hasCreatePermission = currentUser && hasPermission(currentUser, 'CREATE_USERS');
+
+
+ const addFilter = () => {
+ const newItem = {
+ id: uniqueId(),
+ fields: {
+ filterValue: '',
+ filterValueFrom: '',
+ filterValueTo: '',
+ selectedField: '',
+ },
+ };
+ newItem.fields.selectedField = filters[0].title;
+ setFilterItems([...filterItems, newItem]);
+ };
+
+ const getUsersCSV = async () => {
+ const response = await axios({url: '/users?filetype=csv', method: 'GET',responseType: 'blob'});
+ const type = response.headers['content-type']
+ const blob = new Blob([response.data], { type: type })
+ const link = document.createElement('a')
+ link.href = window.URL.createObjectURL(blob)
+ link.download = 'usersCSV.csv'
+ link.click()
+ };
+
+ const onModalConfirm = async () => {
+ if (!csvFile) return;
+ await dispatch(uploadCsv(csvFile));
+ dispatch(setRefetch(true));
+ setCsvFile(null);
+ setIsModalActive(false);
+ };
+
+ const onModalCancel = () => {
+ setCsvFile(null);
+ setIsModalActive(false);
+ };
+
+ return (
+ <>
+
+ {getPageTitle('Users')}
+
+
+
+ {''}
+
+
+
+ {hasCreatePermission && }
+
+
+
+
+ {hasCreatePermission && (
+ setIsModalActive(true)}
+ />
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ )
+}
+
+UsersTablesPage.getLayout = function getLayout(page: ReactElement) {
+ return (
+
+ {page}
+
+ )
+}
+
+export default UsersTablesPage
diff --git a/frontend/src/pages/users/users-new.tsx b/frontend/src/pages/users/users-new.tsx
new file mode 100644
index 0000000..e23b7d4
--- /dev/null
+++ b/frontend/src/pages/users/users-new.tsx
@@ -0,0 +1,548 @@
+import { mdiAccount, mdiChartTimelineVariant, mdiMail, mdiUpload } from '@mdi/js'
+import Head from 'next/head'
+import React, { ReactElement } from 'react'
+import CardBox from '../../components/CardBox'
+import LayoutAuthenticated from '../../layouts/Authenticated'
+import SectionMain from '../../components/SectionMain'
+import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'
+import { getPageTitle } from '../../config'
+
+import { Field, Form, Formik } from 'formik'
+import FormField from '../../components/FormField'
+import BaseDivider from '../../components/BaseDivider'
+import BaseButtons from '../../components/BaseButtons'
+import BaseButton from '../../components/BaseButton'
+import FormCheckRadio from '../../components/FormCheckRadio'
+import FormCheckRadioGroup from '../../components/FormCheckRadioGroup'
+import FormFilePicker from '../../components/FormFilePicker'
+import FormImagePicker from '../../components/FormImagePicker'
+import { SwitchField } from '../../components/SwitchField'
+
+import { SelectField } from '../../components/SelectField'
+import { SelectFieldMany } from "../../components/SelectFieldMany";
+import {RichTextField} from "../../components/RichTextField";
+
+import { create } from '../../stores/users/usersSlice'
+import { useAppDispatch } from '../../stores/hooks'
+import { useRouter } from 'next/router'
+import moment from 'moment';
+
+const initialValues = {
+
+
+ firstName: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lastName: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ phoneNumber: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ email: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ disabled: false,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ avatar: [],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ app_role: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ custom_permissions: [],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ organizations: '',
+
+
+
+}
+
+
+const UsersNew = () => {
+ const router = useRouter()
+ const dispatch = useAppDispatch()
+
+
+
+
+ const handleSubmit = async (data) => {
+ await dispatch(create(data))
+ await router.push('/users/users-list')
+ }
+ return (
+ <>
+
+ {getPageTitle('New Item')}
+
+
+
+ {''}
+
+
+ handleSubmit(values)}
+ >
+
+
+
+
+ >
+ )
+}
+
+UsersNew.getLayout = function getLayout(page: ReactElement) {
+ return (
+
+ {page}
+
+ )
+}
+
+export default UsersNew
diff --git a/frontend/src/pages/users/users-table.tsx b/frontend/src/pages/users/users-table.tsx
new file mode 100644
index 0000000..88caea1
--- /dev/null
+++ b/frontend/src/pages/users/users-table.tsx
@@ -0,0 +1,166 @@
+import { mdiChartTimelineVariant } from '@mdi/js'
+import Head from 'next/head'
+import { uniqueId } from 'lodash';
+import React, { ReactElement, useState } from 'react'
+import CardBox from '../../components/CardBox'
+import LayoutAuthenticated from '../../layouts/Authenticated'
+import SectionMain from '../../components/SectionMain'
+import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'
+import { getPageTitle } from '../../config'
+import TableUsers from '../../components/Users/TableUsers'
+import BaseButton from '../../components/BaseButton'
+import axios from "axios";
+import Link from "next/link";
+import {useAppDispatch, useAppSelector} from "../../stores/hooks";
+import CardBoxModal from "../../components/CardBoxModal";
+import DragDropFilePicker from "../../components/DragDropFilePicker";
+import {setRefetch, uploadCsv} from '../../stores/users/usersSlice';
+
+
+import {hasPermission} from "../../helpers/userPermissions";
+
+
+
+const UsersTablesPage = () => {
+ const [filterItems, setFilterItems] = useState([]);
+ const [csvFile, setCsvFile] = useState(null);
+ const [isModalActive, setIsModalActive] = useState(false);
+ const [showTableView, setShowTableView] = useState(false);
+
+
+ const { currentUser } = useAppSelector((state) => state.auth);
+
+
+ const dispatch = useAppDispatch();
+
+
+ const [filters] = useState([{label: 'First Name', title: 'firstName'},{label: 'Last Name', title: 'lastName'},{label: 'Phone Number', title: 'phoneNumber'},{label: 'E-Mail', title: 'email'},
+
+
+
+
+
+ {label: 'App Role', title: 'app_role'},
+
+
+
+
+ {label: 'Custom Permissions', title: 'custom_permissions'},
+
+ ]);
+
+ const hasCreatePermission = currentUser && hasPermission(currentUser, 'CREATE_USERS');
+
+
+ const addFilter = () => {
+ const newItem = {
+ id: uniqueId(),
+ fields: {
+ filterValue: '',
+ filterValueFrom: '',
+ filterValueTo: '',
+ selectedField: '',
+ },
+ };
+ newItem.fields.selectedField = filters[0].title;
+ setFilterItems([...filterItems, newItem]);
+ };
+
+ const getUsersCSV = async () => {
+ const response = await axios({url: '/users?filetype=csv', method: 'GET',responseType: 'blob'});
+ const type = response.headers['content-type']
+ const blob = new Blob([response.data], { type: type })
+ const link = document.createElement('a')
+ link.href = window.URL.createObjectURL(blob)
+ link.download = 'usersCSV.csv'
+ link.click()
+ };
+
+ const onModalConfirm = async () => {
+ if (!csvFile) return;
+ await dispatch(uploadCsv(csvFile));
+ dispatch(setRefetch(true));
+ setCsvFile(null);
+ setIsModalActive(false);
+ };
+
+ const onModalCancel = () => {
+ setCsvFile(null);
+ setIsModalActive(false);
+ };
+
+ return (
+ <>
+
+ {getPageTitle('Users')}
+
+
+
+ {''}
+
+
+
+ {hasCreatePermission && }
+
+
+
+
+ {hasCreatePermission && (
+ setIsModalActive(true)}
+ />
+ )}
+
+
+
+
+
+
+
+
+
+
+ >
+ )
+}
+
+UsersTablesPage.getLayout = function getLayout(page: ReactElement) {
+ return (
+
+ {page}
+
+ )
+}
+
+export default UsersTablesPage
diff --git a/frontend/src/pages/users/users-view.tsx b/frontend/src/pages/users/users-view.tsx
new file mode 100644
index 0000000..935d323
--- /dev/null
+++ b/frontend/src/pages/users/users-view.tsx
@@ -0,0 +1,2624 @@
+import React, { ReactElement, useEffect } from 'react';
+import Head from 'next/head'
+import DatePicker from "react-datepicker";
+import "react-datepicker/dist/react-datepicker.css";
+import dayjs from "dayjs";
+import {useAppDispatch, useAppSelector} from "../../stores/hooks";
+import {useRouter} from "next/router";
+import { fetch } from '../../stores/users/usersSlice'
+import {saveFile} from "../../helpers/fileSaver";
+import dataFormatter from '../../helpers/dataFormatter';
+import ImageField from "../../components/ImageField";
+import LayoutAuthenticated from "../../layouts/Authenticated";
+import {getPageTitle} from "../../config";
+import SectionTitleLineWithButton from "../../components/SectionTitleLineWithButton";
+import SectionMain from "../../components/SectionMain";
+import CardBox from "../../components/CardBox";
+import BaseButton from "../../components/BaseButton";
+import BaseDivider from "../../components/BaseDivider";
+import {mdiChartTimelineVariant} from "@mdi/js";
+import {SwitchField} from "../../components/SwitchField";
+import FormField from "../../components/FormField";
+
+import {hasPermission} from "../../helpers/userPermissions";
+
+
+const UsersView = () => {
+ const router = useRouter()
+ const dispatch = useAppDispatch()
+ const { users } = useAppSelector((state) => state.users)
+
+ const { currentUser } = useAppSelector((state) => state.auth);
+
+
+ const { id } = router.query;
+
+ function removeLastCharacter(str) {
+ console.log(str,`str`)
+ return str.slice(0, -1);
+ }
+
+ useEffect(() => {
+ dispatch(fetch({ id }));
+ }, [dispatch, id]);
+
+
+ return (
+ <>
+
+ {getPageTitle('View users')}
+
+
+
+
+
+
+
+
+
+
+
First Name
+
{users?.firstName}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Last Name
+
{users?.lastName}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Phone Number
+
{users?.phoneNumber}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
E-Mail
+
{users?.email}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ null}}
+ disabled
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Avatar
+ {users?.avatar?.length
+ ? (
+
+ ) :
No Avatar
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
App Role
+
+
+
+
+
{users?.app_role?.name ?? 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <>
+ Custom Permissions
+
+
+
+
+
+
+
+
+
+
+ Name
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {users.custom_permissions && Array.isArray(users.custom_permissions) &&
+ users.custom_permissions.map((item: any) => (
+ router.push(`/permissions/permissions-view/?id=${item.id}`)}>
+
+
+
+
+
+
+ { item.name }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+ {!users?.custom_permissions?.length && No data
}
+
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Organizations
+
+
+
+
+
+
+
+
+
{users?.organizations?.name ?? 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <>
+ Merchants AssignedAccountant
+
+
+
+
+
+
+
+
+
+ BusinessName
+
+
+
+ LegalName
+
+
+
+ TINNumber
+
+
+
+ VATRegistrationNumber
+
+
+
+ TaxpayerType
+
+
+
+ Industry
+
+
+
+ City
+
+
+
+ Address
+
+
+
+ ContactName
+
+
+
+ ContactPhone
+
+
+
+ ContactEmail
+
+
+
+
+
+ IsActive
+
+
+
+ OnboardedAt
+
+
+
+
+
+ {users.merchants_assigned_accountant && Array.isArray(users.merchants_assigned_accountant) &&
+ users.merchants_assigned_accountant.map((item: any) => (
+ router.push(`/merchants/merchants-view/?id=${item.id}`)}>
+
+
+
+
+
+ { item.business_name }
+
+
+
+
+
+ { item.legal_name }
+
+
+
+
+
+ { item.tin_number }
+
+
+
+
+
+ { item.vat_registration_number }
+
+
+
+
+
+ { item.taxpayer_type }
+
+
+
+
+
+ { item.industry }
+
+
+
+
+
+ { item.city }
+
+
+
+
+
+ { item.address }
+
+
+
+
+
+ { item.contact_name }
+
+
+
+
+
+ { item.contact_phone }
+
+
+
+
+
+ { item.contact_email }
+
+
+
+
+
+
+
+ { dataFormatter.booleanFormatter(item.is_active) }
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.onboarded_at) }
+
+
+
+
+ ))}
+
+
+
+ {!users?.merchants_assigned_accountant?.length && No data
}
+
+ >
+
+
+
+
+
+ <>
+ Receipts UploadedBy
+
+
+
+
+
+
+
+
+
+
+
+ ReceiptKind
+
+
+
+
+
+
+
+ SourceChannel
+
+
+
+ CapturedAt
+
+
+
+ OCRStatus
+
+
+
+ OCRConfidence
+
+
+
+ NeedsReview
+
+
+
+ Notes
+
+
+
+
+
+ {users.receipts_uploaded_by && Array.isArray(users.receipts_uploaded_by) &&
+ users.receipts_uploaded_by.map((item: any) => (
+ router.push(`/receipts/receipts-view/?id=${item.id}`)}>
+
+
+
+
+
+
+
+ { item.receipt_kind }
+
+
+
+
+
+
+
+
+
+ { item.source_channel }
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.captured_at) }
+
+
+
+
+
+ { item.ocr_status }
+
+
+
+
+
+ { item.ocr_confidence }
+
+
+
+
+
+ { dataFormatter.booleanFormatter(item.needs_review) }
+
+
+
+
+
+ { item.notes }
+
+
+
+
+ ))}
+
+
+
+ {!users?.receipts_uploaded_by?.length && No data
}
+
+ >
+
+
+
+ <>
+ Sales_invoices EnteredBy
+
+
+
+
+
+
+
+
+
+
+
+
+
+ InvoiceNumber
+
+
+
+ InvoiceDate
+
+
+
+ Status
+
+
+
+ VATTreatment
+
+
+
+ SubtotalAmount
+
+
+
+ VATAmount
+
+
+
+ TotalAmount
+
+
+
+
+
+
+
+ ReviewedAt
+
+
+
+ ReviewNotes
+
+
+
+
+
+ {users.sales_invoices_entered_by && Array.isArray(users.sales_invoices_entered_by) &&
+ users.sales_invoices_entered_by.map((item: any) => (
+ router.push(`/sales_invoices/sales_invoices-view/?id=${item.id}`)}>
+
+
+
+
+
+
+
+
+
+ { item.invoice_number }
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.invoice_date) }
+
+
+
+
+
+ { item.status }
+
+
+
+
+
+ { item.vat_treatment }
+
+
+
+
+
+ { item.subtotal_amount }
+
+
+
+
+
+ { item.vat_amount }
+
+
+
+
+
+ { item.total_amount }
+
+
+
+
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.reviewed_at) }
+
+
+
+
+
+ { item.review_notes }
+
+
+
+
+ ))}
+
+
+
+ {!users?.sales_invoices_entered_by?.length && No data
}
+
+ >
+
+ <>
+ Sales_invoices ReviewedBy
+
+
+
+
+
+
+
+
+
+
+
+
+
+ InvoiceNumber
+
+
+
+ InvoiceDate
+
+
+
+ Status
+
+
+
+ VATTreatment
+
+
+
+ SubtotalAmount
+
+
+
+ VATAmount
+
+
+
+ TotalAmount
+
+
+
+
+
+
+
+ ReviewedAt
+
+
+
+ ReviewNotes
+
+
+
+
+
+ {users.sales_invoices_reviewed_by && Array.isArray(users.sales_invoices_reviewed_by) &&
+ users.sales_invoices_reviewed_by.map((item: any) => (
+ router.push(`/sales_invoices/sales_invoices-view/?id=${item.id}`)}>
+
+
+
+
+
+
+
+
+
+ { item.invoice_number }
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.invoice_date) }
+
+
+
+
+
+ { item.status }
+
+
+
+
+
+ { item.vat_treatment }
+
+
+
+
+
+ { item.subtotal_amount }
+
+
+
+
+
+ { item.vat_amount }
+
+
+
+
+
+ { item.total_amount }
+
+
+
+
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.reviewed_at) }
+
+
+
+
+
+ { item.review_notes }
+
+
+
+
+ ))}
+
+
+
+ {!users?.sales_invoices_reviewed_by?.length && No data
}
+
+ >
+
+
+
+ <>
+ Purchase_invoices EnteredBy
+
+
+
+
+
+
+
+
+
+
+
+
+
+ InvoiceNumber
+
+
+
+ InvoiceDate
+
+
+
+ Status
+
+
+
+ VATTreatment
+
+
+
+ SubtotalAmount
+
+
+
+ VATAmount
+
+
+
+ WithholdingTaxAmount
+
+
+
+ TotalAmount
+
+
+
+
+
+
+
+ ReviewedAt
+
+
+
+ ReviewNotes
+
+
+
+
+
+ {users.purchase_invoices_entered_by && Array.isArray(users.purchase_invoices_entered_by) &&
+ users.purchase_invoices_entered_by.map((item: any) => (
+ router.push(`/purchase_invoices/purchase_invoices-view/?id=${item.id}`)}>
+
+
+
+
+
+
+
+
+
+ { item.invoice_number }
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.invoice_date) }
+
+
+
+
+
+ { item.status }
+
+
+
+
+
+ { item.vat_treatment }
+
+
+
+
+
+ { item.subtotal_amount }
+
+
+
+
+
+ { item.vat_amount }
+
+
+
+
+
+ { item.withholding_tax_amount }
+
+
+
+
+
+ { item.total_amount }
+
+
+
+
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.reviewed_at) }
+
+
+
+
+
+ { item.review_notes }
+
+
+
+
+ ))}
+
+
+
+ {!users?.purchase_invoices_entered_by?.length && No data
}
+
+ >
+
+ <>
+ Purchase_invoices ReviewedBy
+
+
+
+
+
+
+
+
+
+
+
+
+
+ InvoiceNumber
+
+
+
+ InvoiceDate
+
+
+
+ Status
+
+
+
+ VATTreatment
+
+
+
+ SubtotalAmount
+
+
+
+ VATAmount
+
+
+
+ WithholdingTaxAmount
+
+
+
+ TotalAmount
+
+
+
+
+
+
+
+ ReviewedAt
+
+
+
+ ReviewNotes
+
+
+
+
+
+ {users.purchase_invoices_reviewed_by && Array.isArray(users.purchase_invoices_reviewed_by) &&
+ users.purchase_invoices_reviewed_by.map((item: any) => (
+ router.push(`/purchase_invoices/purchase_invoices-view/?id=${item.id}`)}>
+
+
+
+
+
+
+
+
+
+ { item.invoice_number }
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.invoice_date) }
+
+
+
+
+
+ { item.status }
+
+
+
+
+
+ { item.vat_treatment }
+
+
+
+
+
+ { item.subtotal_amount }
+
+
+
+
+
+ { item.vat_amount }
+
+
+
+
+
+ { item.withholding_tax_amount }
+
+
+
+
+
+ { item.total_amount }
+
+
+
+
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.reviewed_at) }
+
+
+
+
+
+ { item.review_notes }
+
+
+
+
+ ))}
+
+
+
+ {!users?.purchase_invoices_reviewed_by?.length && No data
}
+
+ >
+
+
+
+ <>
+ Expenses EnteredBy
+
+
+
+
+
+
+
+
+
+
+
+ Category
+
+
+
+ Description
+
+
+
+ ExpenseDate
+
+
+
+ Amount
+
+
+
+ TaxTreatment
+
+
+
+ Status
+
+
+
+
+
+
+
+ ReviewedAt
+
+
+
+ ReviewNotes
+
+
+
+
+
+ {users.expenses_entered_by && Array.isArray(users.expenses_entered_by) &&
+ users.expenses_entered_by.map((item: any) => (
+ router.push(`/expenses/expenses-view/?id=${item.id}`)}>
+
+
+
+
+
+
+
+ { item.category }
+
+
+
+
+
+ { item.description }
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.expense_date) }
+
+
+
+
+
+ { item.amount }
+
+
+
+
+
+ { item.tax_treatment }
+
+
+
+
+
+ { item.status }
+
+
+
+
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.reviewed_at) }
+
+
+
+
+
+ { item.review_notes }
+
+
+
+
+ ))}
+
+
+
+ {!users?.expenses_entered_by?.length && No data
}
+
+ >
+
+ <>
+ Expenses ReviewedBy
+
+
+
+
+
+
+
+
+
+
+
+ Category
+
+
+
+ Description
+
+
+
+ ExpenseDate
+
+
+
+ Amount
+
+
+
+ TaxTreatment
+
+
+
+ Status
+
+
+
+
+
+
+
+ ReviewedAt
+
+
+
+ ReviewNotes
+
+
+
+
+
+ {users.expenses_reviewed_by && Array.isArray(users.expenses_reviewed_by) &&
+ users.expenses_reviewed_by.map((item: any) => (
+ router.push(`/expenses/expenses-view/?id=${item.id}`)}>
+
+
+
+
+
+
+
+ { item.category }
+
+
+
+
+
+ { item.description }
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.expense_date) }
+
+
+
+
+
+ { item.amount }
+
+
+
+
+
+ { item.tax_treatment }
+
+
+
+
+
+ { item.status }
+
+
+
+
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.reviewed_at) }
+
+
+
+
+
+ { item.review_notes }
+
+
+
+
+ ))}
+
+
+
+ {!users?.expenses_reviewed_by?.length && No data
}
+
+ >
+
+
+
+ <>
+ Vat_declarations GeneratedBy
+
+
+
+
+
+
+
+
+
+
+
+ Status
+
+
+
+ TotalSalesAmount
+
+
+
+ TaxableSalesAmount
+
+
+
+ OutputVATAmount
+
+
+
+ TotalPurchasesAmount
+
+
+
+ InputVATAmount
+
+
+
+ VATPayableAmount
+
+
+
+
+
+ GeneratedAt
+
+
+
+
+
+ ReviewedAt
+
+
+
+ Notes
+
+
+
+
+
+
+
+
+
+
+
+ {users.vat_declarations_generated_by && Array.isArray(users.vat_declarations_generated_by) &&
+ users.vat_declarations_generated_by.map((item: any) => (
+ router.push(`/vat_declarations/vat_declarations-view/?id=${item.id}`)}>
+
+
+
+
+
+
+
+ { item.status }
+
+
+
+
+
+ { item.total_sales_amount }
+
+
+
+
+
+ { item.taxable_sales_amount }
+
+
+
+
+
+ { item.output_vat_amount }
+
+
+
+
+
+ { item.total_purchases_amount }
+
+
+
+
+
+ { item.input_vat_amount }
+
+
+
+
+
+ { item.vat_payable_amount }
+
+
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.generated_at) }
+
+
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.reviewed_at) }
+
+
+
+
+
+ { item.notes }
+
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+ {!users?.vat_declarations_generated_by?.length && No data
}
+
+ >
+
+ <>
+ Vat_declarations ReviewedBy
+
+
+
+
+
+
+
+
+
+
+
+ Status
+
+
+
+ TotalSalesAmount
+
+
+
+ TaxableSalesAmount
+
+
+
+ OutputVATAmount
+
+
+
+ TotalPurchasesAmount
+
+
+
+ InputVATAmount
+
+
+
+ VATPayableAmount
+
+
+
+
+
+ GeneratedAt
+
+
+
+
+
+ ReviewedAt
+
+
+
+ Notes
+
+
+
+
+
+
+
+
+
+
+
+ {users.vat_declarations_reviewed_by && Array.isArray(users.vat_declarations_reviewed_by) &&
+ users.vat_declarations_reviewed_by.map((item: any) => (
+ router.push(`/vat_declarations/vat_declarations-view/?id=${item.id}`)}>
+
+
+
+
+
+
+
+ { item.status }
+
+
+
+
+
+ { item.total_sales_amount }
+
+
+
+
+
+ { item.taxable_sales_amount }
+
+
+
+
+
+ { item.output_vat_amount }
+
+
+
+
+
+ { item.total_purchases_amount }
+
+
+
+
+
+ { item.input_vat_amount }
+
+
+
+
+
+ { item.vat_payable_amount }
+
+
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.generated_at) }
+
+
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.reviewed_at) }
+
+
+
+
+
+ { item.notes }
+
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+ {!users?.vat_declarations_reviewed_by?.length && No data
}
+
+ >
+
+
+ <>
+ Tot_declarations GeneratedBy
+
+
+
+
+
+
+
+
+
+
+
+ Status
+
+
+
+ GrossSalesAmount
+
+
+
+ TOTRatePercent
+
+
+
+ TOTPayableAmount
+
+
+
+
+
+ GeneratedAt
+
+
+
+
+
+ ReviewedAt
+
+
+
+ Notes
+
+
+
+
+
+
+
+
+
+
+
+ {users.tot_declarations_generated_by && Array.isArray(users.tot_declarations_generated_by) &&
+ users.tot_declarations_generated_by.map((item: any) => (
+ router.push(`/tot_declarations/tot_declarations-view/?id=${item.id}`)}>
+
+
+
+
+
+
+
+ { item.status }
+
+
+
+
+
+ { item.gross_sales_amount }
+
+
+
+
+
+ { item.tot_rate_percent }
+
+
+
+
+
+ { item.tot_payable_amount }
+
+
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.generated_at) }
+
+
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.reviewed_at) }
+
+
+
+
+
+ { item.notes }
+
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+ {!users?.tot_declarations_generated_by?.length && No data
}
+
+ >
+
+ <>
+ Tot_declarations ReviewedBy
+
+
+
+
+
+
+
+
+
+
+
+ Status
+
+
+
+ GrossSalesAmount
+
+
+
+ TOTRatePercent
+
+
+
+ TOTPayableAmount
+
+
+
+
+
+ GeneratedAt
+
+
+
+
+
+ ReviewedAt
+
+
+
+ Notes
+
+
+
+
+
+
+
+
+
+
+
+ {users.tot_declarations_reviewed_by && Array.isArray(users.tot_declarations_reviewed_by) &&
+ users.tot_declarations_reviewed_by.map((item: any) => (
+ router.push(`/tot_declarations/tot_declarations-view/?id=${item.id}`)}>
+
+
+
+
+
+
+
+ { item.status }
+
+
+
+
+
+ { item.gross_sales_amount }
+
+
+
+
+
+ { item.tot_rate_percent }
+
+
+
+
+
+ { item.tot_payable_amount }
+
+
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.generated_at) }
+
+
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.reviewed_at) }
+
+
+
+
+
+ { item.notes }
+
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+ {!users?.tot_declarations_reviewed_by?.length && No data
}
+
+ >
+
+
+ <>
+ Declaration_submissions SubmittedBy
+
+
+
+
+
+
+
+
+
+
+
+ DeclarationType
+
+
+
+ SubmissionReference
+
+
+
+ SubmittedAt
+
+
+
+
+
+ Status
+
+
+
+ ResponseMessage
+
+
+
+
+
+
+
+ {users.declaration_submissions_submitted_by && Array.isArray(users.declaration_submissions_submitted_by) &&
+ users.declaration_submissions_submitted_by.map((item: any) => (
+ router.push(`/declaration_submissions/declaration_submissions-view/?id=${item.id}`)}>
+
+
+
+
+
+
+
+ { item.declaration_type }
+
+
+
+
+
+ { item.submission_reference }
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.submitted_at) }
+
+
+
+
+
+
+
+ { item.status }
+
+
+
+
+
+ { item.response_message }
+
+
+
+
+
+
+ ))}
+
+
+
+ {!users?.declaration_submissions_submitted_by?.length && No data
}
+
+ >
+
+
+ <>
+ Messages Sender
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Channel
+
+
+
+ Subject
+
+
+
+ Body
+
+
+
+ Status
+
+
+
+ SentAt
+
+
+
+
+
+
+
+ {users.messages_sender && Array.isArray(users.messages_sender) &&
+ users.messages_sender.map((item: any) => (
+ router.push(`/messages/messages-view/?id=${item.id}`)}>
+
+
+
+
+
+
+
+
+
+
+
+ { item.channel }
+
+
+
+
+
+ { item.subject }
+
+
+
+
+
+ { item.body }
+
+
+
+
+
+ { item.status }
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.sent_at) }
+
+
+
+
+
+
+ ))}
+
+
+
+ {!users?.messages_sender?.length && No data
}
+
+ >
+
+ <>
+ Messages Recipient
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Channel
+
+
+
+ Subject
+
+
+
+ Body
+
+
+
+ Status
+
+
+
+ SentAt
+
+
+
+
+
+
+
+ {users.messages_recipient && Array.isArray(users.messages_recipient) &&
+ users.messages_recipient.map((item: any) => (
+ router.push(`/messages/messages-view/?id=${item.id}`)}>
+
+
+
+
+
+
+
+
+
+
+
+ { item.channel }
+
+
+
+
+
+ { item.subject }
+
+
+
+
+
+ { item.body }
+
+
+
+
+
+ { item.status }
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.sent_at) }
+
+
+
+
+
+
+ ))}
+
+
+
+ {!users?.messages_recipient?.length && No data
}
+
+ >
+
+
+ <>
+ Audit_events Actor
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Action
+
+
+
+ EntityName
+
+
+
+ RecordKey
+
+
+
+ OccurredAt
+
+
+
+ Details
+
+
+
+ IPAddress
+
+
+
+
+
+ {users.audit_events_actor && Array.isArray(users.audit_events_actor) &&
+ users.audit_events_actor.map((item: any) => (
+ router.push(`/audit_events/audit_events-view/?id=${item.id}`)}>
+
+
+
+
+
+
+
+
+
+ { item.action }
+
+
+
+
+
+ { item.entity_name }
+
+
+
+
+
+ { item.record_key }
+
+
+
+
+
+ { dataFormatter.dateTimeFormatter(item.occurred_at) }
+
+
+
+
+
+ { item.details }
+
+
+
+
+
+ { item.ip_address }
+
+
+
+
+ ))}
+
+
+
+ {!users?.audit_events_actor?.length && No data
}
+
+ >
+
+
+
+
+
+ router.push('/users/users-list')}
+ />
+
+
+ >
+ );
+};
+
+UsersView.getLayout = function getLayout(page: ReactElement) {
+ return (
+
+ {page}
+
+ )
+}
+
+export default UsersView;
\ No newline at end of file
diff --git a/frontend/src/pages/vat_declarations/[vat_declarationsId].tsx b/frontend/src/pages/vat_declarations/[vat_declarationsId].tsx
new file mode 100644
index 0000000..d9d3f00
--- /dev/null
+++ b/frontend/src/pages/vat_declarations/[vat_declarationsId].tsx
@@ -0,0 +1,1596 @@
+import { mdiChartTimelineVariant, mdiUpload } from '@mdi/js'
+import Head from 'next/head'
+import React, { ReactElement, useEffect, useState } from 'react'
+import DatePicker from "react-datepicker";
+import "react-datepicker/dist/react-datepicker.css";
+import dayjs from "dayjs";
+
+import CardBox from '../../components/CardBox'
+import LayoutAuthenticated from '../../layouts/Authenticated'
+import SectionMain from '../../components/SectionMain'
+import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'
+import { getPageTitle } from '../../config'
+
+import { Field, Form, Formik } from 'formik'
+import FormField from '../../components/FormField'
+import BaseDivider from '../../components/BaseDivider'
+import BaseButtons from '../../components/BaseButtons'
+import BaseButton from '../../components/BaseButton'
+import FormCheckRadio from '../../components/FormCheckRadio'
+import FormCheckRadioGroup from '../../components/FormCheckRadioGroup'
+import FormFilePicker from '../../components/FormFilePicker'
+import FormImagePicker from '../../components/FormImagePicker'
+import { SelectField } from "../../components/SelectField";
+import { SelectFieldMany } from "../../components/SelectFieldMany";
+import { SwitchField } from '../../components/SwitchField'
+import {RichTextField} from "../../components/RichTextField";
+
+import { update, fetch } from '../../stores/vat_declarations/vat_declarationsSlice'
+import { useAppDispatch, useAppSelector } from '../../stores/hooks'
+import { useRouter } from 'next/router'
+import {saveFile} from "../../helpers/fileSaver";
+import dataFormatter from '../../helpers/dataFormatter';
+import ImageField from "../../components/ImageField";
+
+import {hasPermission} from "../../helpers/userPermissions";
+
+
+
+const EditVat_declarations = () => {
+ const router = useRouter()
+ const dispatch = useAppDispatch()
+ const initVals = {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ merchant: null,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tax_period: null,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ status: '',
+
+
+
+
+
+
+
+
+
+
+
+ 'total_sales_amount': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'taxable_sales_amount': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'output_vat_amount': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'total_purchases_amount': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'input_vat_amount': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'vat_payable_amount': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generated_by: null,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generated_at: new Date(),
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ reviewed_by: null,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ reviewed_at: new Date(),
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ notes: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pdf_file: [],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ excel_file: [],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ revenue_office_export_file: [],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ organizations: null,
+
+
+
+
+
+ }
+ const [initialValues, setInitialValues] = useState(initVals)
+
+ const { vat_declarations } = useAppSelector((state) => state.vat_declarations)
+
+ const { currentUser } = useAppSelector((state) => state.auth);
+
+
+ const { vat_declarationsId } = router.query
+
+ useEffect(() => {
+ dispatch(fetch({ id: vat_declarationsId }))
+ }, [vat_declarationsId])
+
+ useEffect(() => {
+ if (typeof vat_declarations === 'object') {
+ setInitialValues(vat_declarations)
+ }
+ }, [vat_declarations])
+
+ useEffect(() => {
+ if (typeof vat_declarations === 'object') {
+
+ const newInitialVal = {...initVals};
+
+ Object.keys(initVals).forEach(el => newInitialVal[el] = (vat_declarations)[el])
+
+ setInitialValues(newInitialVal);
+ }
+ }, [vat_declarations])
+
+ const handleSubmit = async (data) => {
+ await dispatch(update({ id: vat_declarationsId, data }))
+ await router.push('/vat_declarations/vat_declarations-list')
+ }
+
+ return (
+ <>
+
+ {getPageTitle('Edit vat_declarations')}
+
+
+
+ {''}
+
+
+ handleSubmit(values)}
+ >
+
+
+
+
+ >
+ )
+}
+
+EditVat_declarations.getLayout = function getLayout(page: ReactElement) {
+ return (
+
+ {page}
+
+ )
+}
+
+export default EditVat_declarations
diff --git a/frontend/src/pages/vat_declarations/vat_declarations-edit.tsx b/frontend/src/pages/vat_declarations/vat_declarations-edit.tsx
new file mode 100644
index 0000000..f3ba65e
--- /dev/null
+++ b/frontend/src/pages/vat_declarations/vat_declarations-edit.tsx
@@ -0,0 +1,1593 @@
+import { mdiChartTimelineVariant, mdiUpload } from '@mdi/js'
+import Head from 'next/head'
+import React, { ReactElement, useEffect, useState } from 'react'
+import DatePicker from "react-datepicker";
+import "react-datepicker/dist/react-datepicker.css";
+import dayjs from "dayjs";
+
+import CardBox from '../../components/CardBox'
+import LayoutAuthenticated from '../../layouts/Authenticated'
+import SectionMain from '../../components/SectionMain'
+import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'
+import { getPageTitle } from '../../config'
+
+import { Field, Form, Formik } from 'formik'
+import FormField from '../../components/FormField'
+import BaseDivider from '../../components/BaseDivider'
+import BaseButtons from '../../components/BaseButtons'
+import BaseButton from '../../components/BaseButton'
+import FormCheckRadio from '../../components/FormCheckRadio'
+import FormCheckRadioGroup from '../../components/FormCheckRadioGroup'
+import FormFilePicker from '../../components/FormFilePicker'
+import FormImagePicker from '../../components/FormImagePicker'
+import { SelectField } from "../../components/SelectField";
+import { SelectFieldMany } from "../../components/SelectFieldMany";
+import { SwitchField } from '../../components/SwitchField'
+import {RichTextField} from "../../components/RichTextField";
+
+import { update, fetch } from '../../stores/vat_declarations/vat_declarationsSlice'
+import { useAppDispatch, useAppSelector } from '../../stores/hooks'
+import { useRouter } from 'next/router'
+import {saveFile} from "../../helpers/fileSaver";
+import dataFormatter from '../../helpers/dataFormatter';
+import ImageField from "../../components/ImageField";
+
+import {hasPermission} from "../../helpers/userPermissions";
+
+
+
+const EditVat_declarationsPage = () => {
+ const router = useRouter()
+ const dispatch = useAppDispatch()
+ const initVals = {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ merchant: null,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tax_period: null,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ status: '',
+
+
+
+
+
+
+
+
+
+
+
+ 'total_sales_amount': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'taxable_sales_amount': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'output_vat_amount': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'total_purchases_amount': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'input_vat_amount': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'vat_payable_amount': '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generated_by: null,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generated_at: new Date(),
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ reviewed_by: null,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ reviewed_at: new Date(),
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ notes: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pdf_file: [],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ excel_file: [],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ revenue_office_export_file: [],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ organizations: null,
+
+
+
+
+
+ }
+ const [initialValues, setInitialValues] = useState(initVals)
+
+ const { vat_declarations } = useAppSelector((state) => state.vat_declarations)
+
+ const { currentUser } = useAppSelector((state) => state.auth);
+
+
+ const { id } = router.query
+
+ useEffect(() => {
+ dispatch(fetch({ id: id }))
+ }, [id])
+
+ useEffect(() => {
+ if (typeof vat_declarations === 'object') {
+ setInitialValues(vat_declarations)
+ }
+ }, [vat_declarations])
+
+ useEffect(() => {
+ if (typeof vat_declarations === 'object') {
+ const newInitialVal = {...initVals};
+ Object.keys(initVals).forEach(el => newInitialVal[el] = (vat_declarations)[el])
+ setInitialValues(newInitialVal);
+ }
+ }, [vat_declarations])
+
+ const handleSubmit = async (data) => {
+ await dispatch(update({ id: id, data }))
+ await router.push('/vat_declarations/vat_declarations-list')
+ }
+
+ return (
+ <>
+
+ {getPageTitle('Edit vat_declarations')}
+
+
+
+ {''}
+
+
+ handleSubmit(values)}
+ >
+
+
+
+
+ >
+ )
+}
+
+EditVat_declarationsPage.getLayout = function getLayout(page: ReactElement) {
+ return (
+
+ {page}
+
+ )
+}
+
+export default EditVat_declarationsPage
diff --git a/frontend/src/pages/vat_declarations/vat_declarations-list.tsx b/frontend/src/pages/vat_declarations/vat_declarations-list.tsx
new file mode 100644
index 0000000..44fab52
--- /dev/null
+++ b/frontend/src/pages/vat_declarations/vat_declarations-list.tsx
@@ -0,0 +1,180 @@
+import { mdiChartTimelineVariant } from '@mdi/js'
+import Head from 'next/head'
+import { uniqueId } from 'lodash';
+import React, { ReactElement, useState } from 'react'
+import CardBox from '../../components/CardBox'
+import LayoutAuthenticated from '../../layouts/Authenticated'
+import SectionMain from '../../components/SectionMain'
+import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'
+import { getPageTitle } from '../../config'
+import TableVat_declarations from '../../components/Vat_declarations/TableVat_declarations'
+import BaseButton from '../../components/BaseButton'
+import axios from "axios";
+import Link from "next/link";
+import {useAppDispatch, useAppSelector} from "../../stores/hooks";
+import CardBoxModal from "../../components/CardBoxModal";
+import DragDropFilePicker from "../../components/DragDropFilePicker";
+import {setRefetch, uploadCsv} from '../../stores/vat_declarations/vat_declarationsSlice';
+
+
+import {hasPermission} from "../../helpers/userPermissions";
+
+
+
+const Vat_declarationsTablesPage = () => {
+ const [filterItems, setFilterItems] = useState([]);
+ const [csvFile, setCsvFile] = useState(null);
+ const [isModalActive, setIsModalActive] = useState(false);
+ const [showTableView, setShowTableView] = useState(false);
+
+
+ const { currentUser } = useAppSelector((state) => state.auth);
+
+
+ const dispatch = useAppDispatch();
+
+
+ const [filters] = useState([{label: 'Notes', title: 'notes'},
+
+ {label: 'TotalSalesAmount', title: 'total_sales_amount', number: 'true'},{label: 'TaxableSalesAmount', title: 'taxable_sales_amount', number: 'true'},{label: 'OutputVATAmount', title: 'output_vat_amount', number: 'true'},{label: 'TotalPurchasesAmount', title: 'total_purchases_amount', number: 'true'},{label: 'InputVATAmount', title: 'input_vat_amount', number: 'true'},{label: 'VATPayableAmount', title: 'vat_payable_amount', number: 'true'},
+ {label: 'GeneratedAt', title: 'generated_at', date: 'true'},{label: 'ReviewedAt', title: 'reviewed_at', date: 'true'},
+
+
+ {label: 'Merchant', title: 'merchant'},
+
+
+
+ {label: 'TaxPeriod', title: 'tax_period'},
+
+
+
+ {label: 'GeneratedBy', title: 'generated_by'},
+
+
+
+ {label: 'ReviewedBy', title: 'reviewed_by'},
+
+
+
+ {label: 'Status', title: 'status', type: 'enum', options: ['draft','generated','reviewed','submitted','accepted','rejected','amended']},
+ ]);
+
+ const hasCreatePermission = currentUser && hasPermission(currentUser, 'CREATE_VAT_DECLARATIONS');
+
+
+ const addFilter = () => {
+ const newItem = {
+ id: uniqueId(),
+ fields: {
+ filterValue: '',
+ filterValueFrom: '',
+ filterValueTo: '',
+ selectedField: '',
+ },
+ };
+ newItem.fields.selectedField = filters[0].title;
+ setFilterItems([...filterItems, newItem]);
+ };
+
+ const getVat_declarationsCSV = async () => {
+ const response = await axios({url: '/vat_declarations?filetype=csv', method: 'GET',responseType: 'blob'});
+ const type = response.headers['content-type']
+ const blob = new Blob([response.data], { type: type })
+ const link = document.createElement('a')
+ link.href = window.URL.createObjectURL(blob)
+ link.download = 'vat_declarationsCSV.csv'
+ link.click()
+ };
+
+ const onModalConfirm = async () => {
+ if (!csvFile) return;
+ await dispatch(uploadCsv(csvFile));
+ dispatch(setRefetch(true));
+ setCsvFile(null);
+ setIsModalActive(false);
+ };
+
+ const onModalCancel = () => {
+ setCsvFile(null);
+ setIsModalActive(false);
+ };
+
+ return (
+ <>
+
+ {getPageTitle('Vat_declarations')}
+
+
+
+ {''}
+
+
+
+ {hasCreatePermission && }
+
+
+
+
+ {hasCreatePermission && (
+ setIsModalActive(true)}
+ />
+ )}
+
+
+
+
+ Switch to Table
+
+
+
+
+
+
+
+
+
+
+ >
+ )
+}
+
+Vat_declarationsTablesPage.getLayout = function getLayout(page: ReactElement) {
+ return (
+
+ {page}
+
+ )
+}
+
+export default Vat_declarationsTablesPage
diff --git a/frontend/src/pages/vat_declarations/vat_declarations-new.tsx b/frontend/src/pages/vat_declarations/vat_declarations-new.tsx
new file mode 100644
index 0000000..7c9bed9
--- /dev/null
+++ b/frontend/src/pages/vat_declarations/vat_declarations-new.tsx
@@ -0,0 +1,1021 @@
+import { mdiAccount, mdiChartTimelineVariant, mdiMail, mdiUpload } from '@mdi/js'
+import Head from 'next/head'
+import React, { ReactElement } from 'react'
+import CardBox from '../../components/CardBox'
+import LayoutAuthenticated from '../../layouts/Authenticated'
+import SectionMain from '../../components/SectionMain'
+import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'
+import { getPageTitle } from '../../config'
+
+import { Field, Form, Formik } from 'formik'
+import FormField from '../../components/FormField'
+import BaseDivider from '../../components/BaseDivider'
+import BaseButtons from '../../components/BaseButtons'
+import BaseButton from '../../components/BaseButton'
+import FormCheckRadio from '../../components/FormCheckRadio'
+import FormCheckRadioGroup from '../../components/FormCheckRadioGroup'
+import FormFilePicker from '../../components/FormFilePicker'
+import FormImagePicker from '../../components/FormImagePicker'
+import { SwitchField } from '../../components/SwitchField'
+
+import { SelectField } from '../../components/SelectField'
+import { SelectFieldMany } from "../../components/SelectFieldMany";
+import {RichTextField} from "../../components/RichTextField";
+
+import { create } from '../../stores/vat_declarations/vat_declarationsSlice'
+import { useAppDispatch } from '../../stores/hooks'
+import { useRouter } from 'next/router'
+import moment from 'moment';
+
+const initialValues = {
+
+
+
+
+
+
+
+
+
+
+
+
+
+ merchant: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tax_period: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+ status: 'draft',
+
+
+
+
+
+
+
+ total_sales_amount: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ taxable_sales_amount: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ output_vat_amount: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ total_purchases_amount: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ input_vat_amount: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ vat_payable_amount: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generated_by: '',
+
+
+
+
+
+
+
+
+
+ generated_at: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ reviewed_by: '',
+
+
+
+
+
+
+
+
+
+ reviewed_at: '',
+
+
+
+
+
+
+
+
+
+
+
+ notes: '',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pdf_file: [],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ excel_file: [],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ revenue_office_export_file: [],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ organizations: '',
+
+
+
+}
+
+
+const Vat_declarationsNew = () => {
+ const router = useRouter()
+ const dispatch = useAppDispatch()
+
+
+
+
+ const handleSubmit = async (data) => {
+ await dispatch(create(data))
+ await router.push('/vat_declarations/vat_declarations-list')
+ }
+ return (
+ <>
+
+ {getPageTitle('New Item')}
+
+
+
+ {''}
+
+
+ handleSubmit(values)}
+ >
+
+
+
+
+ >
+ )
+}
+
+Vat_declarationsNew.getLayout = function getLayout(page: ReactElement) {
+ return (
+
+ {page}
+
+ )
+}
+
+export default Vat_declarationsNew
diff --git a/frontend/src/pages/vat_declarations/vat_declarations-table.tsx b/frontend/src/pages/vat_declarations/vat_declarations-table.tsx
new file mode 100644
index 0000000..e3c749b
--- /dev/null
+++ b/frontend/src/pages/vat_declarations/vat_declarations-table.tsx
@@ -0,0 +1,180 @@
+import { mdiChartTimelineVariant } from '@mdi/js'
+import Head from 'next/head'
+import { uniqueId } from 'lodash';
+import React, { ReactElement, useState } from 'react'
+import CardBox from '../../components/CardBox'
+import LayoutAuthenticated from '../../layouts/Authenticated'
+import SectionMain from '../../components/SectionMain'
+import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'
+import { getPageTitle } from '../../config'
+import TableVat_declarations from '../../components/Vat_declarations/TableVat_declarations'
+import BaseButton from '../../components/BaseButton'
+import axios from "axios";
+import Link from "next/link";
+import {useAppDispatch, useAppSelector} from "../../stores/hooks";
+import CardBoxModal from "../../components/CardBoxModal";
+import DragDropFilePicker from "../../components/DragDropFilePicker";
+import {setRefetch, uploadCsv} from '../../stores/vat_declarations/vat_declarationsSlice';
+
+
+import {hasPermission} from "../../helpers/userPermissions";
+
+
+
+const Vat_declarationsTablesPage = () => {
+ const [filterItems, setFilterItems] = useState([]);
+ const [csvFile, setCsvFile] = useState(null);
+ const [isModalActive, setIsModalActive] = useState(false);
+ const [showTableView, setShowTableView] = useState(false);
+
+
+ const { currentUser } = useAppSelector((state) => state.auth);
+
+
+ const dispatch = useAppDispatch();
+
+
+ const [filters] = useState([{label: 'Notes', title: 'notes'},
+
+ {label: 'TotalSalesAmount', title: 'total_sales_amount', number: 'true'},{label: 'TaxableSalesAmount', title: 'taxable_sales_amount', number: 'true'},{label: 'OutputVATAmount', title: 'output_vat_amount', number: 'true'},{label: 'TotalPurchasesAmount', title: 'total_purchases_amount', number: 'true'},{label: 'InputVATAmount', title: 'input_vat_amount', number: 'true'},{label: 'VATPayableAmount', title: 'vat_payable_amount', number: 'true'},
+ {label: 'GeneratedAt', title: 'generated_at', date: 'true'},{label: 'ReviewedAt', title: 'reviewed_at', date: 'true'},
+
+
+ {label: 'Merchant', title: 'merchant'},
+
+
+
+ {label: 'TaxPeriod', title: 'tax_period'},
+
+
+
+ {label: 'GeneratedBy', title: 'generated_by'},
+
+
+
+ {label: 'ReviewedBy', title: 'reviewed_by'},
+
+
+
+ {label: 'Status', title: 'status', type: 'enum', options: ['draft','generated','reviewed','submitted','accepted','rejected','amended']},
+ ]);
+
+ const hasCreatePermission = currentUser && hasPermission(currentUser, 'CREATE_VAT_DECLARATIONS');
+
+
+ const addFilter = () => {
+ const newItem = {
+ id: uniqueId(),
+ fields: {
+ filterValue: '',
+ filterValueFrom: '',
+ filterValueTo: '',
+ selectedField: '',
+ },
+ };
+ newItem.fields.selectedField = filters[0].title;
+ setFilterItems([...filterItems, newItem]);
+ };
+
+ const getVat_declarationsCSV = async () => {
+ const response = await axios({url: '/vat_declarations?filetype=csv', method: 'GET',responseType: 'blob'});
+ const type = response.headers['content-type']
+ const blob = new Blob([response.data], { type: type })
+ const link = document.createElement('a')
+ link.href = window.URL.createObjectURL(blob)
+ link.download = 'vat_declarationsCSV.csv'
+ link.click()
+ };
+
+ const onModalConfirm = async () => {
+ if (!csvFile) return;
+ await dispatch(uploadCsv(csvFile));
+ dispatch(setRefetch(true));
+ setCsvFile(null);
+ setIsModalActive(false);
+ };
+
+ const onModalCancel = () => {
+ setCsvFile(null);
+ setIsModalActive(false);
+ };
+
+ return (
+ <>
+
+ {getPageTitle('Vat_declarations')}
+
+
+
+ {''}
+
+
+
+ {hasCreatePermission && }
+
+
+
+
+ {hasCreatePermission && (
+ setIsModalActive(true)}
+ />
+ )}
+
+
+
+
+
+ Back to
kanban
+
+
+
+
+
+
+
+
+
+
+
+ >
+ )
+}
+
+Vat_declarationsTablesPage.getLayout = function getLayout(page: ReactElement) {
+ return (
+
+ {page}
+
+ )
+}
+
+export default Vat_declarationsTablesPage
diff --git a/frontend/src/pages/vat_declarations/vat_declarations-view.tsx b/frontend/src/pages/vat_declarations/vat_declarations-view.tsx
new file mode 100644
index 0000000..022ab1e
--- /dev/null
+++ b/frontend/src/pages/vat_declarations/vat_declarations-view.tsx
@@ -0,0 +1,969 @@
+import React, { ReactElement, useEffect } from 'react';
+import Head from 'next/head'
+import DatePicker from "react-datepicker";
+import "react-datepicker/dist/react-datepicker.css";
+import dayjs from "dayjs";
+import {useAppDispatch, useAppSelector} from "../../stores/hooks";
+import {useRouter} from "next/router";
+import { fetch } from '../../stores/vat_declarations/vat_declarationsSlice'
+import {saveFile} from "../../helpers/fileSaver";
+import dataFormatter from '../../helpers/dataFormatter';
+import ImageField from "../../components/ImageField";
+import LayoutAuthenticated from "../../layouts/Authenticated";
+import {getPageTitle} from "../../config";
+import SectionTitleLineWithButton from "../../components/SectionTitleLineWithButton";
+import SectionMain from "../../components/SectionMain";
+import CardBox from "../../components/CardBox";
+import BaseButton from "../../components/BaseButton";
+import BaseDivider from "../../components/BaseDivider";
+import {mdiChartTimelineVariant} from "@mdi/js";
+import {SwitchField} from "../../components/SwitchField";
+import FormField from "../../components/FormField";
+
+import {hasPermission} from "../../helpers/userPermissions";
+
+
+const Vat_declarationsView = () => {
+ const router = useRouter()
+ const dispatch = useAppDispatch()
+ const { vat_declarations } = useAppSelector((state) => state.vat_declarations)
+
+ const { currentUser } = useAppSelector((state) => state.auth);
+
+
+ const { id } = router.query;
+
+ function removeLastCharacter(str) {
+ console.log(str,`str`)
+ return str.slice(0, -1);
+ }
+
+ useEffect(() => {
+ dispatch(fetch({ id }));
+ }, [dispatch, id]);
+
+
+ return (
+ <>
+
+ {getPageTitle('View vat_declarations')}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Merchant
+
+
+
+
+
+
+
+
+
+
+
+
+
{vat_declarations?.merchant?.business_name ?? 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
TaxPeriod
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{vat_declarations?.tax_period?.status ?? 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Status
+
{vat_declarations?.status ?? 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
TotalSalesAmount
+
{vat_declarations?.total_sales_amount || 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
TaxableSalesAmount
+
{vat_declarations?.taxable_sales_amount || 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
OutputVATAmount
+
{vat_declarations?.output_vat_amount || 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
TotalPurchasesAmount
+
{vat_declarations?.total_purchases_amount || 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
InputVATAmount
+
{vat_declarations?.input_vat_amount || 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
VATPayableAmount
+
{vat_declarations?.vat_payable_amount || 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
GeneratedBy
+
+
+
{vat_declarations?.generated_by?.firstName ?? 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {vat_declarations.generated_at ? : No GeneratedAt
}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ReviewedBy
+
+
+
{vat_declarations?.reviewed_by?.firstName ?? 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {vat_declarations.reviewed_at ? : No ReviewedAt
}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
PDFFile
+ {vat_declarations?.pdf_file?.length
+ ? dataFormatter.filesFormatter(vat_declarations.pdf_file).map(link => (
+
saveFile(e, link.publicUrl, link.name)}
+ >
+ {link.name}
+
+ )) :
No PDFFile
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ExcelFile
+ {vat_declarations?.excel_file?.length
+ ? dataFormatter.filesFormatter(vat_declarations.excel_file).map(link => (
+
saveFile(e, link.publicUrl, link.name)}
+ >
+ {link.name}
+
+ )) :
No ExcelFile
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
RevenueOfficeExportFile
+ {vat_declarations?.revenue_office_export_file?.length
+ ? dataFormatter.filesFormatter(vat_declarations.revenue_office_export_file).map(link => (
+
saveFile(e, link.publicUrl, link.name)}
+ >
+ {link.name}
+
+ )) :
No RevenueOfficeExportFile
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
organizations
+
+
+
+
+
+
+
+
+
{vat_declarations?.organizations?.name ?? 'No data'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ router.push('/vat_declarations/vat_declarations-list')}
+ />
+
+
+ >
+ );
+};
+
+Vat_declarationsView.getLayout = function getLayout(page: ReactElement) {
+ return (
+
+ {page}
+
+ )
+}
+
+export default Vat_declarationsView;
\ No newline at end of file
diff --git a/frontend/src/pages/verify-email.tsx b/frontend/src/pages/verify-email.tsx
new file mode 100644
index 0000000..6cf0340
--- /dev/null
+++ b/frontend/src/pages/verify-email.tsx
@@ -0,0 +1,62 @@
+import React from 'react';
+import type { ReactElement } from 'react';
+import { ToastContainer, toast } from 'react-toastify';
+import Head from 'next/head';
+import CardBox from '../components/CardBox';
+import SectionFullScreen from '../components/SectionFullScreen';
+import LayoutGuest from '../layouts/Guest';
+import { useRouter } from 'next/router';
+import { getPageTitle } from '../config';
+import axios from 'axios';
+
+export default function Verify() {
+ const [loading, setLoading] = React.useState(false);
+ const router = useRouter();
+ const { token } = router.query;
+ const notify = (type, msg) => toast(msg, { type });
+
+ React.useEffect(() => {
+ if (!token) {
+ router.push('/login');
+ return;
+ }
+ const handleSubmit = async () => {
+
+ setLoading(true);
+ await axios.put('/auth/verify-email', {
+ token,
+ }).then(verified => {
+ if (verified) {
+ setLoading(false);
+ notify('success', 'Your email was verified');
+ }
+ }).catch(error => {
+ setLoading(false);
+ console.log('error: ', error);
+ notify('error', error.response);
+ }).finally(async () => {
+ await router.push('/login');
+ });
+ };
+ handleSubmit().then();
+ }, [token]);
+
+ return (
+ <>
+
+ {getPageTitle('Verify Email')}
+
+
+
+ {loading ? 'Loading...' : ''}
+
+
+
+
+ >
+ );
+}
+
+Verify.getLayout = function getLayout(page: ReactElement) {
+ return {page} ;
+};
diff --git a/frontend/src/stores/audit_events/audit_eventsSlice.ts b/frontend/src/stores/audit_events/audit_eventsSlice.ts
new file mode 100644
index 0000000..52450be
--- /dev/null
+++ b/frontend/src/stores/audit_events/audit_eventsSlice.ts
@@ -0,0 +1,231 @@
+import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
+import axios from 'axios'
+import {fulfilledNotify, rejectNotify, resetNotify} from "../../helpers/notifyStateHandler";
+
+interface MainState {
+ audit_events: any
+ loading: boolean
+ count: number
+ refetch: boolean;
+ rolesWidgets: any[];
+ notify: {
+ showNotification: boolean
+ textNotification: string
+ typeNotification: string
+ }
+}
+
+const initialState: MainState = {
+ audit_events: [],
+ loading: false,
+ count: 0,
+ refetch: false,
+ rolesWidgets: [],
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+}
+
+export const fetch = createAsyncThunk('audit_events/fetch', async (data: any) => {
+ const { id, query } = data
+ const result = await axios.get(
+ `audit_events${
+ query || (id ? `/${id}` : '')
+ }`
+ )
+ return id ? result.data : {rows: result.data.rows, count: result.data.count};
+})
+
+export const deleteItemsByIds = createAsyncThunk(
+ 'audit_events/deleteByIds',
+ async (data: any, { rejectWithValue }) => {
+ try {
+ await axios.post('audit_events/deleteByIds', { data });
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const deleteItem = createAsyncThunk('audit_events/deleteAudit_events', async (id: string, { rejectWithValue }) => {
+ try {
+ await axios.delete(`audit_events/${id}`)
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const create = createAsyncThunk('audit_events/createAudit_events', async (data: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.post(
+ 'audit_events',
+ { data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const uploadCsv = createAsyncThunk(
+ 'audit_events/uploadCsv',
+ async (file: File, { rejectWithValue }) => {
+ try {
+ const data = new FormData();
+ data.append('file', file);
+ data.append('filename', file.name);
+
+ const result = await axios.post('audit_events/bulk-import', data, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ });
+
+ return result.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const update = createAsyncThunk('audit_events/updateAudit_events', async (payload: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.put(
+ `audit_events/${payload.id}`,
+ { id: payload.id, data: payload.data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+
+export const audit_eventsSlice = createSlice({
+ name: 'audit_events',
+ initialState,
+ reducers: {
+ setRefetch: (state, action: PayloadAction) => {
+ state.refetch = action.payload;
+ },
+ },
+ extraReducers: (builder) => {
+ builder.addCase(fetch.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(fetch.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(fetch.fulfilled, (state, action) => {
+ if (action.payload.rows && action.payload.count >= 0) {
+ state.audit_events = action.payload.rows;
+ state.count = action.payload.count;
+ } else {
+ state.audit_events = action.payload;
+ }
+ state.loading = false
+ })
+
+ builder.addCase(deleteItemsByIds.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ });
+
+ builder.addCase(deleteItemsByIds.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Audit_events has been deleted');
+ });
+
+ builder.addCase(deleteItemsByIds.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ });
+
+ builder.addCase(deleteItem.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+
+ builder.addCase(deleteItem.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Audit_events'.slice(0, -1)} has been deleted`);
+ })
+
+ builder.addCase(deleteItem.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(create.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Audit_events'.slice(0, -1)} has been created`);
+ })
+
+ builder.addCase(update.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(update.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Audit_events'.slice(0, -1)} has been updated`);
+ })
+ builder.addCase(update.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(uploadCsv.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ })
+ builder.addCase(uploadCsv.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Audit_events has been uploaded');
+ })
+ builder.addCase(uploadCsv.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ })
+
+
+ },
+})
+
+// Action creators are generated for each case reducer function
+ export const { setRefetch } = audit_eventsSlice.actions
+
+export default audit_eventsSlice.reducer
diff --git a/frontend/src/stores/authSlice.ts b/frontend/src/stores/authSlice.ts
new file mode 100644
index 0000000..2eaa1f2
--- /dev/null
+++ b/frontend/src/stores/authSlice.ts
@@ -0,0 +1,124 @@
+import { createSlice, createAsyncThunk, createAction } from '@reduxjs/toolkit';
+import axios from 'axios';
+import jwt from 'jsonwebtoken';
+
+interface MainState {
+ isFetching: boolean;
+ errorMessage: string;
+ currentUser: any;
+ notify: any;
+ token: string;
+}
+
+const initialState: MainState = {
+ /* User */
+ isFetching: false,
+ errorMessage: '',
+ currentUser: null,
+ token: '',
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+};
+
+export const resetAction = createAction('auth/passwordReset/reset')
+
+export const loginUser = createAsyncThunk(
+ 'auth/loginUser',
+ async (creds: Record, { rejectWithValue }) => {
+ try {
+ const response = await axios.post('auth/signin/local', creds);
+ return response.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+ return rejectWithValue(error.response.data);
+ }
+ }
+);
+
+export const passwordReset = createAsyncThunk(
+ 'auth/passwordReset',
+ async (value: Record, { rejectWithValue }) => {
+ try {
+ const { data: response } = await axios.put('/auth/password-reset', {
+ token: value.token,
+ password: value.password,
+ type: value.type,
+ });
+
+ return response.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const findMe = createAsyncThunk('auth/findMe', async () => {
+ const response = await axios.get('auth/me');
+ return response.data;
+});
+
+export const authSlice = createSlice({
+ name: 'auth',
+ initialState,
+ reducers: {
+ logoutUser: (state) => {
+ localStorage.removeItem('token');
+ localStorage.removeItem('user');
+ axios.defaults.headers.common['Authorization'] = '';
+ state.currentUser = null;
+ state.token = '';
+ },
+ },
+ extraReducers: (builder) => {
+ builder.addCase(loginUser.pending, (state) => {
+ state.isFetching = true;
+ });
+ builder.addCase(loginUser.fulfilled, (state, action) => {
+ const token = action.payload;
+ const user = jwt.decode(token);
+
+ state.errorMessage = '';
+ state.token = token;
+ localStorage.setItem('token', token);
+ localStorage.setItem('user', JSON.stringify(user));
+ axios.defaults.headers.common['Authorization'] = 'Bearer ' + token;
+ });
+
+ builder.addCase(loginUser.rejected, (state, action) => {
+ state.errorMessage = String(action.payload) || 'Something went wrong. Try again';
+ state.isFetching = false;
+ });
+ builder.addCase(findMe.pending, () => {
+ console.log('Pending findMe');
+ });
+ builder.addCase(findMe.fulfilled, (state, action) => {
+ state.currentUser = action.payload;
+ state.isFetching = false;
+ });
+
+ builder.addCase(passwordReset.fulfilled, (state, action) => {
+ state.notify.showNotification = true;
+ state.notify.textNotification = 'Password has been reset successfully';
+ });
+
+ builder.addCase(resetAction, (state) => initialState);
+
+ builder.addCase(passwordReset.rejected, (state) => {
+ state.errorMessage = 'Something was wrong. Try again';
+ });
+ },
+});
+
+// Action creators are generated for each case reducer function
+export const { logoutUser } = authSlice.actions;
+
+export default authSlice.reducer;
diff --git a/frontend/src/stores/customers/customersSlice.ts b/frontend/src/stores/customers/customersSlice.ts
new file mode 100644
index 0000000..d18b551
--- /dev/null
+++ b/frontend/src/stores/customers/customersSlice.ts
@@ -0,0 +1,231 @@
+import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
+import axios from 'axios'
+import {fulfilledNotify, rejectNotify, resetNotify} from "../../helpers/notifyStateHandler";
+
+interface MainState {
+ customers: any
+ loading: boolean
+ count: number
+ refetch: boolean;
+ rolesWidgets: any[];
+ notify: {
+ showNotification: boolean
+ textNotification: string
+ typeNotification: string
+ }
+}
+
+const initialState: MainState = {
+ customers: [],
+ loading: false,
+ count: 0,
+ refetch: false,
+ rolesWidgets: [],
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+}
+
+export const fetch = createAsyncThunk('customers/fetch', async (data: any) => {
+ const { id, query } = data
+ const result = await axios.get(
+ `customers${
+ query || (id ? `/${id}` : '')
+ }`
+ )
+ return id ? result.data : {rows: result.data.rows, count: result.data.count};
+})
+
+export const deleteItemsByIds = createAsyncThunk(
+ 'customers/deleteByIds',
+ async (data: any, { rejectWithValue }) => {
+ try {
+ await axios.post('customers/deleteByIds', { data });
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const deleteItem = createAsyncThunk('customers/deleteCustomers', async (id: string, { rejectWithValue }) => {
+ try {
+ await axios.delete(`customers/${id}`)
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const create = createAsyncThunk('customers/createCustomers', async (data: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.post(
+ 'customers',
+ { data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const uploadCsv = createAsyncThunk(
+ 'customers/uploadCsv',
+ async (file: File, { rejectWithValue }) => {
+ try {
+ const data = new FormData();
+ data.append('file', file);
+ data.append('filename', file.name);
+
+ const result = await axios.post('customers/bulk-import', data, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ });
+
+ return result.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const update = createAsyncThunk('customers/updateCustomers', async (payload: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.put(
+ `customers/${payload.id}`,
+ { id: payload.id, data: payload.data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+
+export const customersSlice = createSlice({
+ name: 'customers',
+ initialState,
+ reducers: {
+ setRefetch: (state, action: PayloadAction) => {
+ state.refetch = action.payload;
+ },
+ },
+ extraReducers: (builder) => {
+ builder.addCase(fetch.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(fetch.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(fetch.fulfilled, (state, action) => {
+ if (action.payload.rows && action.payload.count >= 0) {
+ state.customers = action.payload.rows;
+ state.count = action.payload.count;
+ } else {
+ state.customers = action.payload;
+ }
+ state.loading = false
+ })
+
+ builder.addCase(deleteItemsByIds.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ });
+
+ builder.addCase(deleteItemsByIds.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Customers has been deleted');
+ });
+
+ builder.addCase(deleteItemsByIds.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ });
+
+ builder.addCase(deleteItem.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+
+ builder.addCase(deleteItem.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Customers'.slice(0, -1)} has been deleted`);
+ })
+
+ builder.addCase(deleteItem.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(create.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Customers'.slice(0, -1)} has been created`);
+ })
+
+ builder.addCase(update.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(update.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Customers'.slice(0, -1)} has been updated`);
+ })
+ builder.addCase(update.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(uploadCsv.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ })
+ builder.addCase(uploadCsv.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Customers has been uploaded');
+ })
+ builder.addCase(uploadCsv.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ })
+
+
+ },
+})
+
+// Action creators are generated for each case reducer function
+ export const { setRefetch } = customersSlice.actions
+
+export default customersSlice.reducer
diff --git a/frontend/src/stores/declaration_submissions/declaration_submissionsSlice.ts b/frontend/src/stores/declaration_submissions/declaration_submissionsSlice.ts
new file mode 100644
index 0000000..8d62473
--- /dev/null
+++ b/frontend/src/stores/declaration_submissions/declaration_submissionsSlice.ts
@@ -0,0 +1,231 @@
+import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
+import axios from 'axios'
+import {fulfilledNotify, rejectNotify, resetNotify} from "../../helpers/notifyStateHandler";
+
+interface MainState {
+ declaration_submissions: any
+ loading: boolean
+ count: number
+ refetch: boolean;
+ rolesWidgets: any[];
+ notify: {
+ showNotification: boolean
+ textNotification: string
+ typeNotification: string
+ }
+}
+
+const initialState: MainState = {
+ declaration_submissions: [],
+ loading: false,
+ count: 0,
+ refetch: false,
+ rolesWidgets: [],
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+}
+
+export const fetch = createAsyncThunk('declaration_submissions/fetch', async (data: any) => {
+ const { id, query } = data
+ const result = await axios.get(
+ `declaration_submissions${
+ query || (id ? `/${id}` : '')
+ }`
+ )
+ return id ? result.data : {rows: result.data.rows, count: result.data.count};
+})
+
+export const deleteItemsByIds = createAsyncThunk(
+ 'declaration_submissions/deleteByIds',
+ async (data: any, { rejectWithValue }) => {
+ try {
+ await axios.post('declaration_submissions/deleteByIds', { data });
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const deleteItem = createAsyncThunk('declaration_submissions/deleteDeclaration_submissions', async (id: string, { rejectWithValue }) => {
+ try {
+ await axios.delete(`declaration_submissions/${id}`)
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const create = createAsyncThunk('declaration_submissions/createDeclaration_submissions', async (data: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.post(
+ 'declaration_submissions',
+ { data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const uploadCsv = createAsyncThunk(
+ 'declaration_submissions/uploadCsv',
+ async (file: File, { rejectWithValue }) => {
+ try {
+ const data = new FormData();
+ data.append('file', file);
+ data.append('filename', file.name);
+
+ const result = await axios.post('declaration_submissions/bulk-import', data, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ });
+
+ return result.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const update = createAsyncThunk('declaration_submissions/updateDeclaration_submissions', async (payload: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.put(
+ `declaration_submissions/${payload.id}`,
+ { id: payload.id, data: payload.data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+
+export const declaration_submissionsSlice = createSlice({
+ name: 'declaration_submissions',
+ initialState,
+ reducers: {
+ setRefetch: (state, action: PayloadAction) => {
+ state.refetch = action.payload;
+ },
+ },
+ extraReducers: (builder) => {
+ builder.addCase(fetch.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(fetch.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(fetch.fulfilled, (state, action) => {
+ if (action.payload.rows && action.payload.count >= 0) {
+ state.declaration_submissions = action.payload.rows;
+ state.count = action.payload.count;
+ } else {
+ state.declaration_submissions = action.payload;
+ }
+ state.loading = false
+ })
+
+ builder.addCase(deleteItemsByIds.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ });
+
+ builder.addCase(deleteItemsByIds.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Declaration_submissions has been deleted');
+ });
+
+ builder.addCase(deleteItemsByIds.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ });
+
+ builder.addCase(deleteItem.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+
+ builder.addCase(deleteItem.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Declaration_submissions'.slice(0, -1)} has been deleted`);
+ })
+
+ builder.addCase(deleteItem.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(create.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Declaration_submissions'.slice(0, -1)} has been created`);
+ })
+
+ builder.addCase(update.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(update.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Declaration_submissions'.slice(0, -1)} has been updated`);
+ })
+ builder.addCase(update.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(uploadCsv.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ })
+ builder.addCase(uploadCsv.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Declaration_submissions has been uploaded');
+ })
+ builder.addCase(uploadCsv.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ })
+
+
+ },
+})
+
+// Action creators are generated for each case reducer function
+ export const { setRefetch } = declaration_submissionsSlice.actions
+
+export default declaration_submissionsSlice.reducer
diff --git a/frontend/src/stores/expenses/expensesSlice.ts b/frontend/src/stores/expenses/expensesSlice.ts
new file mode 100644
index 0000000..e1bd27c
--- /dev/null
+++ b/frontend/src/stores/expenses/expensesSlice.ts
@@ -0,0 +1,231 @@
+import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
+import axios from 'axios'
+import {fulfilledNotify, rejectNotify, resetNotify} from "../../helpers/notifyStateHandler";
+
+interface MainState {
+ expenses: any
+ loading: boolean
+ count: number
+ refetch: boolean;
+ rolesWidgets: any[];
+ notify: {
+ showNotification: boolean
+ textNotification: string
+ typeNotification: string
+ }
+}
+
+const initialState: MainState = {
+ expenses: [],
+ loading: false,
+ count: 0,
+ refetch: false,
+ rolesWidgets: [],
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+}
+
+export const fetch = createAsyncThunk('expenses/fetch', async (data: any) => {
+ const { id, query } = data
+ const result = await axios.get(
+ `expenses${
+ query || (id ? `/${id}` : '')
+ }`
+ )
+ return id ? result.data : {rows: result.data.rows, count: result.data.count};
+})
+
+export const deleteItemsByIds = createAsyncThunk(
+ 'expenses/deleteByIds',
+ async (data: any, { rejectWithValue }) => {
+ try {
+ await axios.post('expenses/deleteByIds', { data });
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const deleteItem = createAsyncThunk('expenses/deleteExpenses', async (id: string, { rejectWithValue }) => {
+ try {
+ await axios.delete(`expenses/${id}`)
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const create = createAsyncThunk('expenses/createExpenses', async (data: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.post(
+ 'expenses',
+ { data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const uploadCsv = createAsyncThunk(
+ 'expenses/uploadCsv',
+ async (file: File, { rejectWithValue }) => {
+ try {
+ const data = new FormData();
+ data.append('file', file);
+ data.append('filename', file.name);
+
+ const result = await axios.post('expenses/bulk-import', data, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ });
+
+ return result.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const update = createAsyncThunk('expenses/updateExpenses', async (payload: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.put(
+ `expenses/${payload.id}`,
+ { id: payload.id, data: payload.data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+
+export const expensesSlice = createSlice({
+ name: 'expenses',
+ initialState,
+ reducers: {
+ setRefetch: (state, action: PayloadAction) => {
+ state.refetch = action.payload;
+ },
+ },
+ extraReducers: (builder) => {
+ builder.addCase(fetch.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(fetch.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(fetch.fulfilled, (state, action) => {
+ if (action.payload.rows && action.payload.count >= 0) {
+ state.expenses = action.payload.rows;
+ state.count = action.payload.count;
+ } else {
+ state.expenses = action.payload;
+ }
+ state.loading = false
+ })
+
+ builder.addCase(deleteItemsByIds.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ });
+
+ builder.addCase(deleteItemsByIds.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Expenses has been deleted');
+ });
+
+ builder.addCase(deleteItemsByIds.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ });
+
+ builder.addCase(deleteItem.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+
+ builder.addCase(deleteItem.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Expenses'.slice(0, -1)} has been deleted`);
+ })
+
+ builder.addCase(deleteItem.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(create.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Expenses'.slice(0, -1)} has been created`);
+ })
+
+ builder.addCase(update.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(update.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Expenses'.slice(0, -1)} has been updated`);
+ })
+ builder.addCase(update.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(uploadCsv.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ })
+ builder.addCase(uploadCsv.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Expenses has been uploaded');
+ })
+ builder.addCase(uploadCsv.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ })
+
+
+ },
+})
+
+// Action creators are generated for each case reducer function
+ export const { setRefetch } = expensesSlice.actions
+
+export default expensesSlice.reducer
diff --git a/frontend/src/stores/firms/firmsSlice.ts b/frontend/src/stores/firms/firmsSlice.ts
new file mode 100644
index 0000000..c995a8b
--- /dev/null
+++ b/frontend/src/stores/firms/firmsSlice.ts
@@ -0,0 +1,231 @@
+import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
+import axios from 'axios'
+import {fulfilledNotify, rejectNotify, resetNotify} from "../../helpers/notifyStateHandler";
+
+interface MainState {
+ firms: any
+ loading: boolean
+ count: number
+ refetch: boolean;
+ rolesWidgets: any[];
+ notify: {
+ showNotification: boolean
+ textNotification: string
+ typeNotification: string
+ }
+}
+
+const initialState: MainState = {
+ firms: [],
+ loading: false,
+ count: 0,
+ refetch: false,
+ rolesWidgets: [],
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+}
+
+export const fetch = createAsyncThunk('firms/fetch', async (data: any) => {
+ const { id, query } = data
+ const result = await axios.get(
+ `firms${
+ query || (id ? `/${id}` : '')
+ }`
+ )
+ return id ? result.data : {rows: result.data.rows, count: result.data.count};
+})
+
+export const deleteItemsByIds = createAsyncThunk(
+ 'firms/deleteByIds',
+ async (data: any, { rejectWithValue }) => {
+ try {
+ await axios.post('firms/deleteByIds', { data });
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const deleteItem = createAsyncThunk('firms/deleteFirms', async (id: string, { rejectWithValue }) => {
+ try {
+ await axios.delete(`firms/${id}`)
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const create = createAsyncThunk('firms/createFirms', async (data: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.post(
+ 'firms',
+ { data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const uploadCsv = createAsyncThunk(
+ 'firms/uploadCsv',
+ async (file: File, { rejectWithValue }) => {
+ try {
+ const data = new FormData();
+ data.append('file', file);
+ data.append('filename', file.name);
+
+ const result = await axios.post('firms/bulk-import', data, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ });
+
+ return result.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const update = createAsyncThunk('firms/updateFirms', async (payload: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.put(
+ `firms/${payload.id}`,
+ { id: payload.id, data: payload.data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+
+export const firmsSlice = createSlice({
+ name: 'firms',
+ initialState,
+ reducers: {
+ setRefetch: (state, action: PayloadAction) => {
+ state.refetch = action.payload;
+ },
+ },
+ extraReducers: (builder) => {
+ builder.addCase(fetch.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(fetch.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(fetch.fulfilled, (state, action) => {
+ if (action.payload.rows && action.payload.count >= 0) {
+ state.firms = action.payload.rows;
+ state.count = action.payload.count;
+ } else {
+ state.firms = action.payload;
+ }
+ state.loading = false
+ })
+
+ builder.addCase(deleteItemsByIds.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ });
+
+ builder.addCase(deleteItemsByIds.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Firms has been deleted');
+ });
+
+ builder.addCase(deleteItemsByIds.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ });
+
+ builder.addCase(deleteItem.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+
+ builder.addCase(deleteItem.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Firms'.slice(0, -1)} has been deleted`);
+ })
+
+ builder.addCase(deleteItem.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(create.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Firms'.slice(0, -1)} has been created`);
+ })
+
+ builder.addCase(update.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(update.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Firms'.slice(0, -1)} has been updated`);
+ })
+ builder.addCase(update.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(uploadCsv.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ })
+ builder.addCase(uploadCsv.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Firms has been uploaded');
+ })
+ builder.addCase(uploadCsv.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ })
+
+
+ },
+})
+
+// Action creators are generated for each case reducer function
+ export const { setRefetch } = firmsSlice.actions
+
+export default firmsSlice.reducer
diff --git a/frontend/src/stores/hooks.ts b/frontend/src/stores/hooks.ts
new file mode 100644
index 0000000..60a4163
--- /dev/null
+++ b/frontend/src/stores/hooks.ts
@@ -0,0 +1,6 @@
+import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
+import type { RootState, AppDispatch } from './store'
+
+// Use throughout your app instead of plain `useDispatch` and `useSelector`
+export const useAppDispatch: () => AppDispatch = useDispatch
+export const useAppSelector: TypedUseSelectorHook = useSelector
diff --git a/frontend/src/stores/introSteps.ts b/frontend/src/stores/introSteps.ts
new file mode 100644
index 0000000..6867f44
--- /dev/null
+++ b/frontend/src/stores/introSteps.ts
@@ -0,0 +1,139 @@
+interface Step {
+ element: string;
+ intro: string;
+ position?: string;
+ tooltipClass?: string;
+ highlightClass?: string;
+ disableInteraction?: boolean;
+}
+
+interface Hint {
+ element: string;
+ hint: string;
+ hintPosition?: string;
+}
+
+export const loginSteps: Step[] = [
+
+ {
+ element: '#elementId1',
+ intro: `
+
+
+
Welcome to our app tutorial! Get a sneak peek into the key functionalities and learn how to navigate seamlessly. Here's a quick overview to get you started.
+
+ `,
+ position: 'auto',
+ tooltipClass: ' good-img',
+ },
+ {
+ element: '#loginRoles',
+ intro:
+ 'Choose your login role to proceed. Experience the app as a Super Admin, Admin, or User, or create your own account to get started.',
+ position: 'auto',
+ },
+];
+
+export const appSteps: Step[] = [
+ {
+ element: '#profilEdit',
+ intro:
+ "Update your profile information, including name, email, and password. Don't forget to save your changes to keep your profile current.",
+ position: 'auto',
+ disableInteraction: true,
+ },
+ {
+ element: '#themeToggle',
+ intro: 'Switch between light and dark modes to suit your preference.',
+ position: 'auto',
+ disableInteraction: true,
+ },
+ {
+ element: '#logout',
+ intro:
+ 'Log out or switch users/roles with ease to manage your access.',
+ position: 'auto',
+ disableInteraction: true,
+ },
+ {
+ element: '#search',
+ intro:
+ 'Quickly find specific data or items by entering your query in the search field. Navigate directly to the desired element.',
+ position: 'auto',
+ disableInteraction: true,
+ },
+ {
+ element: '#widgetCreator',
+ intro:
+ 'Use Text-to-Chart and Text-to-Widget to create charts or widgets from text descriptions. Type what you need, like "Orders by Month," and customize your dashboard.',
+ position: 'auto',
+ disableInteraction: true,
+ },
+ {
+ element: '#dashboard',
+ intro:
+ 'View all the entities available to your role, offering insights into the data categories and total items in each.',
+ position: 'auto',
+ disableInteraction: true,
+ },
+ {
+ element: '#asideMenu',
+ intro:
+ 'Access various entities and manage your data. Find links to Swagger API documentation for more information.',
+ position: 'auto',
+ disableInteraction: true,
+ },
+ {
+ element: '#asideMenu',
+ intro: "Let's explore the User entity.",
+ position: 'auto',
+ disableInteraction: true,
+ },
+];
+
+export const usersSteps: Step[] = [
+ {
+ element: '#usersList',
+ intro:
+ 'Invite new users, filter data, and work with CSV files in this section.',
+ position: 'auto',
+ disableInteraction: true,
+ },
+ {
+ element: '#usersTable',
+ intro:
+ 'View, modify, or delete items with the necessary permissions. Inline editing is available within the table.',
+ position: 'auto',
+ disableInteraction: true,
+ },
+ {
+ element: '#asideMenu',
+ intro: "Let's explore the Roles entity.",
+ position: 'auto',
+ disableInteraction: true,
+ },
+
+];
+
+export const rolesSteps: Step[] = [
+ {
+ element: '#rolesTable',
+ intro:
+ 'Super Admin can manage roles and permissions. Adjust access levels and permissions for each role or user in the Roles and Permissions sections.',
+ position: 'auto',
+ disableInteraction: true,
+ },
+ {
+ element: '#feedbackSection',
+ intro: `
+
+
+
Thank you for completing the tour! We hope you now have a better understanding of the app.
+
If you have any questions, feel free to reach out to us at support@flatlogic.com .
+
+ `,
+ position: 'auto',
+ tooltipClass: 'end-img',
+ },
+];
+
diff --git a/frontend/src/stores/mainSlice.ts b/frontend/src/stores/mainSlice.ts
new file mode 100644
index 0000000..4e026b8
--- /dev/null
+++ b/frontend/src/stores/mainSlice.ts
@@ -0,0 +1,36 @@
+import { createSlice, PayloadAction } from '@reduxjs/toolkit'
+import { UserPayloadObject } from '../interfaces'
+
+interface MainState {
+ userName: string
+ userEmail: null | string
+ userAvatar: null | string
+ isFieldFocusRegistered: boolean
+}
+
+const initialState: MainState = {
+ /* User */
+ userName: '',
+ userEmail: null,
+ userAvatar: null,
+
+ /* Field focus with ctrl+k (to register only once) */
+ isFieldFocusRegistered: false,
+}
+
+export const mainSlice = createSlice({
+ name: 'main',
+ initialState,
+ reducers: {
+ setUser: (state, action: PayloadAction) => {
+ state.userName = action.payload.name
+ state.userEmail = action.payload.email
+ state.userAvatar = action.payload.avatar
+ },
+ },
+})
+
+// Action creators are generated for each case reducer function
+export const { setUser } = mainSlice.actions
+
+export default mainSlice.reducer
diff --git a/frontend/src/stores/merchants/merchantsSlice.ts b/frontend/src/stores/merchants/merchantsSlice.ts
new file mode 100644
index 0000000..0ce686b
--- /dev/null
+++ b/frontend/src/stores/merchants/merchantsSlice.ts
@@ -0,0 +1,231 @@
+import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
+import axios from 'axios'
+import {fulfilledNotify, rejectNotify, resetNotify} from "../../helpers/notifyStateHandler";
+
+interface MainState {
+ merchants: any
+ loading: boolean
+ count: number
+ refetch: boolean;
+ rolesWidgets: any[];
+ notify: {
+ showNotification: boolean
+ textNotification: string
+ typeNotification: string
+ }
+}
+
+const initialState: MainState = {
+ merchants: [],
+ loading: false,
+ count: 0,
+ refetch: false,
+ rolesWidgets: [],
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+}
+
+export const fetch = createAsyncThunk('merchants/fetch', async (data: any) => {
+ const { id, query } = data
+ const result = await axios.get(
+ `merchants${
+ query || (id ? `/${id}` : '')
+ }`
+ )
+ return id ? result.data : {rows: result.data.rows, count: result.data.count};
+})
+
+export const deleteItemsByIds = createAsyncThunk(
+ 'merchants/deleteByIds',
+ async (data: any, { rejectWithValue }) => {
+ try {
+ await axios.post('merchants/deleteByIds', { data });
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const deleteItem = createAsyncThunk('merchants/deleteMerchants', async (id: string, { rejectWithValue }) => {
+ try {
+ await axios.delete(`merchants/${id}`)
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const create = createAsyncThunk('merchants/createMerchants', async (data: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.post(
+ 'merchants',
+ { data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const uploadCsv = createAsyncThunk(
+ 'merchants/uploadCsv',
+ async (file: File, { rejectWithValue }) => {
+ try {
+ const data = new FormData();
+ data.append('file', file);
+ data.append('filename', file.name);
+
+ const result = await axios.post('merchants/bulk-import', data, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ });
+
+ return result.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const update = createAsyncThunk('merchants/updateMerchants', async (payload: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.put(
+ `merchants/${payload.id}`,
+ { id: payload.id, data: payload.data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+
+export const merchantsSlice = createSlice({
+ name: 'merchants',
+ initialState,
+ reducers: {
+ setRefetch: (state, action: PayloadAction) => {
+ state.refetch = action.payload;
+ },
+ },
+ extraReducers: (builder) => {
+ builder.addCase(fetch.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(fetch.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(fetch.fulfilled, (state, action) => {
+ if (action.payload.rows && action.payload.count >= 0) {
+ state.merchants = action.payload.rows;
+ state.count = action.payload.count;
+ } else {
+ state.merchants = action.payload;
+ }
+ state.loading = false
+ })
+
+ builder.addCase(deleteItemsByIds.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ });
+
+ builder.addCase(deleteItemsByIds.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Merchants has been deleted');
+ });
+
+ builder.addCase(deleteItemsByIds.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ });
+
+ builder.addCase(deleteItem.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+
+ builder.addCase(deleteItem.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Merchants'.slice(0, -1)} has been deleted`);
+ })
+
+ builder.addCase(deleteItem.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(create.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Merchants'.slice(0, -1)} has been created`);
+ })
+
+ builder.addCase(update.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(update.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Merchants'.slice(0, -1)} has been updated`);
+ })
+ builder.addCase(update.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(uploadCsv.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ })
+ builder.addCase(uploadCsv.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Merchants has been uploaded');
+ })
+ builder.addCase(uploadCsv.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ })
+
+
+ },
+})
+
+// Action creators are generated for each case reducer function
+ export const { setRefetch } = merchantsSlice.actions
+
+export default merchantsSlice.reducer
diff --git a/frontend/src/stores/messages/messagesSlice.ts b/frontend/src/stores/messages/messagesSlice.ts
new file mode 100644
index 0000000..7e7c20b
--- /dev/null
+++ b/frontend/src/stores/messages/messagesSlice.ts
@@ -0,0 +1,231 @@
+import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
+import axios from 'axios'
+import {fulfilledNotify, rejectNotify, resetNotify} from "../../helpers/notifyStateHandler";
+
+interface MainState {
+ messages: any
+ loading: boolean
+ count: number
+ refetch: boolean;
+ rolesWidgets: any[];
+ notify: {
+ showNotification: boolean
+ textNotification: string
+ typeNotification: string
+ }
+}
+
+const initialState: MainState = {
+ messages: [],
+ loading: false,
+ count: 0,
+ refetch: false,
+ rolesWidgets: [],
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+}
+
+export const fetch = createAsyncThunk('messages/fetch', async (data: any) => {
+ const { id, query } = data
+ const result = await axios.get(
+ `messages${
+ query || (id ? `/${id}` : '')
+ }`
+ )
+ return id ? result.data : {rows: result.data.rows, count: result.data.count};
+})
+
+export const deleteItemsByIds = createAsyncThunk(
+ 'messages/deleteByIds',
+ async (data: any, { rejectWithValue }) => {
+ try {
+ await axios.post('messages/deleteByIds', { data });
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const deleteItem = createAsyncThunk('messages/deleteMessages', async (id: string, { rejectWithValue }) => {
+ try {
+ await axios.delete(`messages/${id}`)
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const create = createAsyncThunk('messages/createMessages', async (data: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.post(
+ 'messages',
+ { data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const uploadCsv = createAsyncThunk(
+ 'messages/uploadCsv',
+ async (file: File, { rejectWithValue }) => {
+ try {
+ const data = new FormData();
+ data.append('file', file);
+ data.append('filename', file.name);
+
+ const result = await axios.post('messages/bulk-import', data, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ });
+
+ return result.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const update = createAsyncThunk('messages/updateMessages', async (payload: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.put(
+ `messages/${payload.id}`,
+ { id: payload.id, data: payload.data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+
+export const messagesSlice = createSlice({
+ name: 'messages',
+ initialState,
+ reducers: {
+ setRefetch: (state, action: PayloadAction) => {
+ state.refetch = action.payload;
+ },
+ },
+ extraReducers: (builder) => {
+ builder.addCase(fetch.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(fetch.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(fetch.fulfilled, (state, action) => {
+ if (action.payload.rows && action.payload.count >= 0) {
+ state.messages = action.payload.rows;
+ state.count = action.payload.count;
+ } else {
+ state.messages = action.payload;
+ }
+ state.loading = false
+ })
+
+ builder.addCase(deleteItemsByIds.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ });
+
+ builder.addCase(deleteItemsByIds.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Messages has been deleted');
+ });
+
+ builder.addCase(deleteItemsByIds.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ });
+
+ builder.addCase(deleteItem.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+
+ builder.addCase(deleteItem.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Messages'.slice(0, -1)} has been deleted`);
+ })
+
+ builder.addCase(deleteItem.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(create.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Messages'.slice(0, -1)} has been created`);
+ })
+
+ builder.addCase(update.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(update.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Messages'.slice(0, -1)} has been updated`);
+ })
+ builder.addCase(update.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(uploadCsv.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ })
+ builder.addCase(uploadCsv.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Messages has been uploaded');
+ })
+ builder.addCase(uploadCsv.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ })
+
+
+ },
+})
+
+// Action creators are generated for each case reducer function
+ export const { setRefetch } = messagesSlice.actions
+
+export default messagesSlice.reducer
diff --git a/frontend/src/stores/ocr_extractions/ocr_extractionsSlice.ts b/frontend/src/stores/ocr_extractions/ocr_extractionsSlice.ts
new file mode 100644
index 0000000..c3da661
--- /dev/null
+++ b/frontend/src/stores/ocr_extractions/ocr_extractionsSlice.ts
@@ -0,0 +1,231 @@
+import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
+import axios from 'axios'
+import {fulfilledNotify, rejectNotify, resetNotify} from "../../helpers/notifyStateHandler";
+
+interface MainState {
+ ocr_extractions: any
+ loading: boolean
+ count: number
+ refetch: boolean;
+ rolesWidgets: any[];
+ notify: {
+ showNotification: boolean
+ textNotification: string
+ typeNotification: string
+ }
+}
+
+const initialState: MainState = {
+ ocr_extractions: [],
+ loading: false,
+ count: 0,
+ refetch: false,
+ rolesWidgets: [],
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+}
+
+export const fetch = createAsyncThunk('ocr_extractions/fetch', async (data: any) => {
+ const { id, query } = data
+ const result = await axios.get(
+ `ocr_extractions${
+ query || (id ? `/${id}` : '')
+ }`
+ )
+ return id ? result.data : {rows: result.data.rows, count: result.data.count};
+})
+
+export const deleteItemsByIds = createAsyncThunk(
+ 'ocr_extractions/deleteByIds',
+ async (data: any, { rejectWithValue }) => {
+ try {
+ await axios.post('ocr_extractions/deleteByIds', { data });
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const deleteItem = createAsyncThunk('ocr_extractions/deleteOcr_extractions', async (id: string, { rejectWithValue }) => {
+ try {
+ await axios.delete(`ocr_extractions/${id}`)
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const create = createAsyncThunk('ocr_extractions/createOcr_extractions', async (data: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.post(
+ 'ocr_extractions',
+ { data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const uploadCsv = createAsyncThunk(
+ 'ocr_extractions/uploadCsv',
+ async (file: File, { rejectWithValue }) => {
+ try {
+ const data = new FormData();
+ data.append('file', file);
+ data.append('filename', file.name);
+
+ const result = await axios.post('ocr_extractions/bulk-import', data, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ });
+
+ return result.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const update = createAsyncThunk('ocr_extractions/updateOcr_extractions', async (payload: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.put(
+ `ocr_extractions/${payload.id}`,
+ { id: payload.id, data: payload.data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+
+export const ocr_extractionsSlice = createSlice({
+ name: 'ocr_extractions',
+ initialState,
+ reducers: {
+ setRefetch: (state, action: PayloadAction) => {
+ state.refetch = action.payload;
+ },
+ },
+ extraReducers: (builder) => {
+ builder.addCase(fetch.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(fetch.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(fetch.fulfilled, (state, action) => {
+ if (action.payload.rows && action.payload.count >= 0) {
+ state.ocr_extractions = action.payload.rows;
+ state.count = action.payload.count;
+ } else {
+ state.ocr_extractions = action.payload;
+ }
+ state.loading = false
+ })
+
+ builder.addCase(deleteItemsByIds.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ });
+
+ builder.addCase(deleteItemsByIds.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Ocr_extractions has been deleted');
+ });
+
+ builder.addCase(deleteItemsByIds.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ });
+
+ builder.addCase(deleteItem.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+
+ builder.addCase(deleteItem.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Ocr_extractions'.slice(0, -1)} has been deleted`);
+ })
+
+ builder.addCase(deleteItem.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(create.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Ocr_extractions'.slice(0, -1)} has been created`);
+ })
+
+ builder.addCase(update.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(update.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Ocr_extractions'.slice(0, -1)} has been updated`);
+ })
+ builder.addCase(update.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(uploadCsv.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ })
+ builder.addCase(uploadCsv.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Ocr_extractions has been uploaded');
+ })
+ builder.addCase(uploadCsv.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ })
+
+
+ },
+})
+
+// Action creators are generated for each case reducer function
+ export const { setRefetch } = ocr_extractionsSlice.actions
+
+export default ocr_extractionsSlice.reducer
diff --git a/frontend/src/stores/openAiSlice.ts b/frontend/src/stores/openAiSlice.ts
new file mode 100644
index 0000000..1328235
--- /dev/null
+++ b/frontend/src/stores/openAiSlice.ts
@@ -0,0 +1,151 @@
+import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
+import axios from 'axios';
+
+interface MainState {
+ isFetchingQuery: boolean;
+ errorMessage: string;
+ smartWidgets: any[];
+ gptResponse: string | null;
+ aiResponse: any | null;
+ isAskingQuestion: boolean;
+ isAskingResponse: boolean;
+ notify: {
+ showNotification: boolean;
+ textNotification: string;
+ typeNotification: string;
+ };
+}
+const initialState: MainState = {
+ isFetchingQuery: false,
+ errorMessage: '',
+ smartWidgets: [],
+ gptResponse: null,
+ aiResponse: null,
+ isAskingQuestion: false,
+ isAskingResponse: false,
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+};
+
+const fulfilledNotify = (state, msg, type?: string) => {
+ state.notify.textNotification = msg;
+ state.notify.typeNotification = type || 'success';
+ state.notify.showNotification = true;
+};
+
+export const aiPrompt = createAsyncThunk(
+ 'openai/aiPrompt',
+ async (data: any, { rejectWithValue }) => {
+ try {
+ return await axios.post('/openai/create_widget', data);
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const askGpt = createAsyncThunk(
+ 'openai/askGpt',
+ async (prompt: string, { rejectWithValue }) => {
+ try {
+ const response = await axios.post('/openai/ask-gpt', { prompt });
+ return response.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const aiResponse = createAsyncThunk(
+ 'openai/aiResponse',
+ async (payload: { input: Array<{ role: string; content: string }>; options?: Record }, { rejectWithValue }) => {
+ try {
+ const response = await axios.post('/ai/response', payload);
+ return response.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const openAiSlice = createSlice({
+ name: 'openAiSlice',
+ initialState,
+ reducers: {
+ resetNotify: (state) => {
+ state.notify.showNotification = false;
+ state.notify.typeNotification = '';
+ state.notify.textNotification = '';
+ },
+ setErrorNotification: (state, action) => {
+ fulfilledNotify(state, action.payload, 'error');
+ },
+ },
+ extraReducers: (builder) => {
+ builder.addCase(aiPrompt.pending, (state) => {
+ state.isFetchingQuery = true;
+ });
+ builder.addCase(aiPrompt.fulfilled, (state, action: Record) => {
+ state.isFetchingQuery = false;
+ state.errorMessage = '';
+ state.smartWidgets.unshift(action.payload.data);
+ });
+
+ builder.addCase(aiPrompt.rejected, (state) => {
+ state.errorMessage = 'Something was wrong. Try again';
+ state.isFetchingQuery = false;
+ state.smartWidgets = null;
+ });
+
+ builder.addCase(askGpt.pending, (state) => {
+ state.isAskingQuestion = true;
+ state.gptResponse = null;
+ state.errorMessage = '';
+ });
+ builder.addCase(askGpt.fulfilled, (state, action) => {
+ state.isAskingQuestion = false;
+ state.gptResponse = action.payload.data;
+ state.errorMessage = '';
+ });
+ builder.addCase(askGpt.rejected, (state) => {
+ state.isAskingQuestion = false;
+ state.gptResponse = null;
+ state.errorMessage = 'Failed to get response from ChatGPT. Please try again.';
+ fulfilledNotify(state, 'Failed to get response from ChatGPT', 'error');
+ });
+
+ builder.addCase(aiResponse.pending, (state) => {
+ state.isAskingResponse = true;
+ state.aiResponse = null;
+ state.errorMessage = '';
+ });
+ builder.addCase(aiResponse.fulfilled, (state, action) => {
+ state.isAskingResponse = false;
+ state.aiResponse = action.payload;
+ state.errorMessage = '';
+ });
+ builder.addCase(aiResponse.rejected, (state) => {
+ state.isAskingResponse = false;
+ state.aiResponse = null;
+ state.errorMessage = 'Failed to get response from AI proxy. Please try again.';
+ fulfilledNotify(state, 'Failed to get response from AI proxy', 'error');
+ });
+ },
+});
+
+// Action creators are generated for each case reducer function
+export const { resetNotify, setErrorNotification } = openAiSlice.actions;
+
+export default openAiSlice.reducer;
diff --git a/frontend/src/stores/organizations/organizationsSlice.ts b/frontend/src/stores/organizations/organizationsSlice.ts
new file mode 100644
index 0000000..9167a7e
--- /dev/null
+++ b/frontend/src/stores/organizations/organizationsSlice.ts
@@ -0,0 +1,231 @@
+import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
+import axios from 'axios'
+import {fulfilledNotify, rejectNotify, resetNotify} from "../../helpers/notifyStateHandler";
+
+interface MainState {
+ organizations: any
+ loading: boolean
+ count: number
+ refetch: boolean;
+ rolesWidgets: any[];
+ notify: {
+ showNotification: boolean
+ textNotification: string
+ typeNotification: string
+ }
+}
+
+const initialState: MainState = {
+ organizations: [],
+ loading: false,
+ count: 0,
+ refetch: false,
+ rolesWidgets: [],
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+}
+
+export const fetch = createAsyncThunk('organizations/fetch', async (data: any) => {
+ const { id, query } = data
+ const result = await axios.get(
+ `organizations${
+ query || (id ? `/${id}` : '')
+ }`
+ )
+ return id ? result.data : {rows: result.data.rows, count: result.data.count};
+})
+
+export const deleteItemsByIds = createAsyncThunk(
+ 'organizations/deleteByIds',
+ async (data: any, { rejectWithValue }) => {
+ try {
+ await axios.post('organizations/deleteByIds', { data });
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const deleteItem = createAsyncThunk('organizations/deleteOrganizations', async (id: string, { rejectWithValue }) => {
+ try {
+ await axios.delete(`organizations/${id}`)
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const create = createAsyncThunk('organizations/createOrganizations', async (data: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.post(
+ 'organizations',
+ { data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const uploadCsv = createAsyncThunk(
+ 'organizations/uploadCsv',
+ async (file: File, { rejectWithValue }) => {
+ try {
+ const data = new FormData();
+ data.append('file', file);
+ data.append('filename', file.name);
+
+ const result = await axios.post('organizations/bulk-import', data, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ });
+
+ return result.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const update = createAsyncThunk('organizations/updateOrganizations', async (payload: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.put(
+ `organizations/${payload.id}`,
+ { id: payload.id, data: payload.data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+
+export const organizationsSlice = createSlice({
+ name: 'organizations',
+ initialState,
+ reducers: {
+ setRefetch: (state, action: PayloadAction) => {
+ state.refetch = action.payload;
+ },
+ },
+ extraReducers: (builder) => {
+ builder.addCase(fetch.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(fetch.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(fetch.fulfilled, (state, action) => {
+ if (action.payload.rows && action.payload.count >= 0) {
+ state.organizations = action.payload.rows;
+ state.count = action.payload.count;
+ } else {
+ state.organizations = action.payload;
+ }
+ state.loading = false
+ })
+
+ builder.addCase(deleteItemsByIds.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ });
+
+ builder.addCase(deleteItemsByIds.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Organizations has been deleted');
+ });
+
+ builder.addCase(deleteItemsByIds.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ });
+
+ builder.addCase(deleteItem.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+
+ builder.addCase(deleteItem.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Organizations'.slice(0, -1)} has been deleted`);
+ })
+
+ builder.addCase(deleteItem.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(create.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Organizations'.slice(0, -1)} has been created`);
+ })
+
+ builder.addCase(update.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(update.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Organizations'.slice(0, -1)} has been updated`);
+ })
+ builder.addCase(update.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(uploadCsv.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ })
+ builder.addCase(uploadCsv.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Organizations has been uploaded');
+ })
+ builder.addCase(uploadCsv.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ })
+
+
+ },
+})
+
+// Action creators are generated for each case reducer function
+ export const { setRefetch } = organizationsSlice.actions
+
+export default organizationsSlice.reducer
diff --git a/frontend/src/stores/permissions/permissionsSlice.ts b/frontend/src/stores/permissions/permissionsSlice.ts
new file mode 100644
index 0000000..ad3648d
--- /dev/null
+++ b/frontend/src/stores/permissions/permissionsSlice.ts
@@ -0,0 +1,231 @@
+import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
+import axios from 'axios'
+import {fulfilledNotify, rejectNotify, resetNotify} from "../../helpers/notifyStateHandler";
+
+interface MainState {
+ permissions: any
+ loading: boolean
+ count: number
+ refetch: boolean;
+ rolesWidgets: any[];
+ notify: {
+ showNotification: boolean
+ textNotification: string
+ typeNotification: string
+ }
+}
+
+const initialState: MainState = {
+ permissions: [],
+ loading: false,
+ count: 0,
+ refetch: false,
+ rolesWidgets: [],
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+}
+
+export const fetch = createAsyncThunk('permissions/fetch', async (data: any) => {
+ const { id, query } = data
+ const result = await axios.get(
+ `permissions${
+ query || (id ? `/${id}` : '')
+ }`
+ )
+ return id ? result.data : {rows: result.data.rows, count: result.data.count};
+})
+
+export const deleteItemsByIds = createAsyncThunk(
+ 'permissions/deleteByIds',
+ async (data: any, { rejectWithValue }) => {
+ try {
+ await axios.post('permissions/deleteByIds', { data });
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const deleteItem = createAsyncThunk('permissions/deletePermissions', async (id: string, { rejectWithValue }) => {
+ try {
+ await axios.delete(`permissions/${id}`)
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const create = createAsyncThunk('permissions/createPermissions', async (data: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.post(
+ 'permissions',
+ { data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const uploadCsv = createAsyncThunk(
+ 'permissions/uploadCsv',
+ async (file: File, { rejectWithValue }) => {
+ try {
+ const data = new FormData();
+ data.append('file', file);
+ data.append('filename', file.name);
+
+ const result = await axios.post('permissions/bulk-import', data, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ });
+
+ return result.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const update = createAsyncThunk('permissions/updatePermissions', async (payload: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.put(
+ `permissions/${payload.id}`,
+ { id: payload.id, data: payload.data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+
+export const permissionsSlice = createSlice({
+ name: 'permissions',
+ initialState,
+ reducers: {
+ setRefetch: (state, action: PayloadAction) => {
+ state.refetch = action.payload;
+ },
+ },
+ extraReducers: (builder) => {
+ builder.addCase(fetch.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(fetch.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(fetch.fulfilled, (state, action) => {
+ if (action.payload.rows && action.payload.count >= 0) {
+ state.permissions = action.payload.rows;
+ state.count = action.payload.count;
+ } else {
+ state.permissions = action.payload;
+ }
+ state.loading = false
+ })
+
+ builder.addCase(deleteItemsByIds.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ });
+
+ builder.addCase(deleteItemsByIds.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Permissions has been deleted');
+ });
+
+ builder.addCase(deleteItemsByIds.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ });
+
+ builder.addCase(deleteItem.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+
+ builder.addCase(deleteItem.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Permissions'.slice(0, -1)} has been deleted`);
+ })
+
+ builder.addCase(deleteItem.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(create.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Permissions'.slice(0, -1)} has been created`);
+ })
+
+ builder.addCase(update.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(update.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Permissions'.slice(0, -1)} has been updated`);
+ })
+ builder.addCase(update.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(uploadCsv.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ })
+ builder.addCase(uploadCsv.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Permissions has been uploaded');
+ })
+ builder.addCase(uploadCsv.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ })
+
+
+ },
+})
+
+// Action creators are generated for each case reducer function
+ export const { setRefetch } = permissionsSlice.actions
+
+export default permissionsSlice.reducer
diff --git a/frontend/src/stores/products/productsSlice.ts b/frontend/src/stores/products/productsSlice.ts
new file mode 100644
index 0000000..04a9df2
--- /dev/null
+++ b/frontend/src/stores/products/productsSlice.ts
@@ -0,0 +1,231 @@
+import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
+import axios from 'axios'
+import {fulfilledNotify, rejectNotify, resetNotify} from "../../helpers/notifyStateHandler";
+
+interface MainState {
+ products: any
+ loading: boolean
+ count: number
+ refetch: boolean;
+ rolesWidgets: any[];
+ notify: {
+ showNotification: boolean
+ textNotification: string
+ typeNotification: string
+ }
+}
+
+const initialState: MainState = {
+ products: [],
+ loading: false,
+ count: 0,
+ refetch: false,
+ rolesWidgets: [],
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+}
+
+export const fetch = createAsyncThunk('products/fetch', async (data: any) => {
+ const { id, query } = data
+ const result = await axios.get(
+ `products${
+ query || (id ? `/${id}` : '')
+ }`
+ )
+ return id ? result.data : {rows: result.data.rows, count: result.data.count};
+})
+
+export const deleteItemsByIds = createAsyncThunk(
+ 'products/deleteByIds',
+ async (data: any, { rejectWithValue }) => {
+ try {
+ await axios.post('products/deleteByIds', { data });
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const deleteItem = createAsyncThunk('products/deleteProducts', async (id: string, { rejectWithValue }) => {
+ try {
+ await axios.delete(`products/${id}`)
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const create = createAsyncThunk('products/createProducts', async (data: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.post(
+ 'products',
+ { data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const uploadCsv = createAsyncThunk(
+ 'products/uploadCsv',
+ async (file: File, { rejectWithValue }) => {
+ try {
+ const data = new FormData();
+ data.append('file', file);
+ data.append('filename', file.name);
+
+ const result = await axios.post('products/bulk-import', data, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ });
+
+ return result.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const update = createAsyncThunk('products/updateProducts', async (payload: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.put(
+ `products/${payload.id}`,
+ { id: payload.id, data: payload.data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+
+export const productsSlice = createSlice({
+ name: 'products',
+ initialState,
+ reducers: {
+ setRefetch: (state, action: PayloadAction) => {
+ state.refetch = action.payload;
+ },
+ },
+ extraReducers: (builder) => {
+ builder.addCase(fetch.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(fetch.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(fetch.fulfilled, (state, action) => {
+ if (action.payload.rows && action.payload.count >= 0) {
+ state.products = action.payload.rows;
+ state.count = action.payload.count;
+ } else {
+ state.products = action.payload;
+ }
+ state.loading = false
+ })
+
+ builder.addCase(deleteItemsByIds.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ });
+
+ builder.addCase(deleteItemsByIds.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Products has been deleted');
+ });
+
+ builder.addCase(deleteItemsByIds.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ });
+
+ builder.addCase(deleteItem.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+
+ builder.addCase(deleteItem.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Products'.slice(0, -1)} has been deleted`);
+ })
+
+ builder.addCase(deleteItem.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(create.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Products'.slice(0, -1)} has been created`);
+ })
+
+ builder.addCase(update.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(update.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Products'.slice(0, -1)} has been updated`);
+ })
+ builder.addCase(update.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(uploadCsv.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ })
+ builder.addCase(uploadCsv.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Products has been uploaded');
+ })
+ builder.addCase(uploadCsv.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ })
+
+
+ },
+})
+
+// Action creators are generated for each case reducer function
+ export const { setRefetch } = productsSlice.actions
+
+export default productsSlice.reducer
diff --git a/frontend/src/stores/purchase_invoice_lines/purchase_invoice_linesSlice.ts b/frontend/src/stores/purchase_invoice_lines/purchase_invoice_linesSlice.ts
new file mode 100644
index 0000000..9e16aa3
--- /dev/null
+++ b/frontend/src/stores/purchase_invoice_lines/purchase_invoice_linesSlice.ts
@@ -0,0 +1,231 @@
+import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
+import axios from 'axios'
+import {fulfilledNotify, rejectNotify, resetNotify} from "../../helpers/notifyStateHandler";
+
+interface MainState {
+ purchase_invoice_lines: any
+ loading: boolean
+ count: number
+ refetch: boolean;
+ rolesWidgets: any[];
+ notify: {
+ showNotification: boolean
+ textNotification: string
+ typeNotification: string
+ }
+}
+
+const initialState: MainState = {
+ purchase_invoice_lines: [],
+ loading: false,
+ count: 0,
+ refetch: false,
+ rolesWidgets: [],
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+}
+
+export const fetch = createAsyncThunk('purchase_invoice_lines/fetch', async (data: any) => {
+ const { id, query } = data
+ const result = await axios.get(
+ `purchase_invoice_lines${
+ query || (id ? `/${id}` : '')
+ }`
+ )
+ return id ? result.data : {rows: result.data.rows, count: result.data.count};
+})
+
+export const deleteItemsByIds = createAsyncThunk(
+ 'purchase_invoice_lines/deleteByIds',
+ async (data: any, { rejectWithValue }) => {
+ try {
+ await axios.post('purchase_invoice_lines/deleteByIds', { data });
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const deleteItem = createAsyncThunk('purchase_invoice_lines/deletePurchase_invoice_lines', async (id: string, { rejectWithValue }) => {
+ try {
+ await axios.delete(`purchase_invoice_lines/${id}`)
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const create = createAsyncThunk('purchase_invoice_lines/createPurchase_invoice_lines', async (data: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.post(
+ 'purchase_invoice_lines',
+ { data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const uploadCsv = createAsyncThunk(
+ 'purchase_invoice_lines/uploadCsv',
+ async (file: File, { rejectWithValue }) => {
+ try {
+ const data = new FormData();
+ data.append('file', file);
+ data.append('filename', file.name);
+
+ const result = await axios.post('purchase_invoice_lines/bulk-import', data, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ });
+
+ return result.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const update = createAsyncThunk('purchase_invoice_lines/updatePurchase_invoice_lines', async (payload: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.put(
+ `purchase_invoice_lines/${payload.id}`,
+ { id: payload.id, data: payload.data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+
+export const purchase_invoice_linesSlice = createSlice({
+ name: 'purchase_invoice_lines',
+ initialState,
+ reducers: {
+ setRefetch: (state, action: PayloadAction) => {
+ state.refetch = action.payload;
+ },
+ },
+ extraReducers: (builder) => {
+ builder.addCase(fetch.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(fetch.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(fetch.fulfilled, (state, action) => {
+ if (action.payload.rows && action.payload.count >= 0) {
+ state.purchase_invoice_lines = action.payload.rows;
+ state.count = action.payload.count;
+ } else {
+ state.purchase_invoice_lines = action.payload;
+ }
+ state.loading = false
+ })
+
+ builder.addCase(deleteItemsByIds.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ });
+
+ builder.addCase(deleteItemsByIds.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Purchase_invoice_lines has been deleted');
+ });
+
+ builder.addCase(deleteItemsByIds.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ });
+
+ builder.addCase(deleteItem.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+
+ builder.addCase(deleteItem.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Purchase_invoice_lines'.slice(0, -1)} has been deleted`);
+ })
+
+ builder.addCase(deleteItem.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(create.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Purchase_invoice_lines'.slice(0, -1)} has been created`);
+ })
+
+ builder.addCase(update.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(update.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Purchase_invoice_lines'.slice(0, -1)} has been updated`);
+ })
+ builder.addCase(update.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(uploadCsv.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ })
+ builder.addCase(uploadCsv.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Purchase_invoice_lines has been uploaded');
+ })
+ builder.addCase(uploadCsv.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ })
+
+
+ },
+})
+
+// Action creators are generated for each case reducer function
+ export const { setRefetch } = purchase_invoice_linesSlice.actions
+
+export default purchase_invoice_linesSlice.reducer
diff --git a/frontend/src/stores/purchase_invoices/purchase_invoicesSlice.ts b/frontend/src/stores/purchase_invoices/purchase_invoicesSlice.ts
new file mode 100644
index 0000000..22410ea
--- /dev/null
+++ b/frontend/src/stores/purchase_invoices/purchase_invoicesSlice.ts
@@ -0,0 +1,231 @@
+import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
+import axios from 'axios'
+import {fulfilledNotify, rejectNotify, resetNotify} from "../../helpers/notifyStateHandler";
+
+interface MainState {
+ purchase_invoices: any
+ loading: boolean
+ count: number
+ refetch: boolean;
+ rolesWidgets: any[];
+ notify: {
+ showNotification: boolean
+ textNotification: string
+ typeNotification: string
+ }
+}
+
+const initialState: MainState = {
+ purchase_invoices: [],
+ loading: false,
+ count: 0,
+ refetch: false,
+ rolesWidgets: [],
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+}
+
+export const fetch = createAsyncThunk('purchase_invoices/fetch', async (data: any) => {
+ const { id, query } = data
+ const result = await axios.get(
+ `purchase_invoices${
+ query || (id ? `/${id}` : '')
+ }`
+ )
+ return id ? result.data : {rows: result.data.rows, count: result.data.count};
+})
+
+export const deleteItemsByIds = createAsyncThunk(
+ 'purchase_invoices/deleteByIds',
+ async (data: any, { rejectWithValue }) => {
+ try {
+ await axios.post('purchase_invoices/deleteByIds', { data });
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const deleteItem = createAsyncThunk('purchase_invoices/deletePurchase_invoices', async (id: string, { rejectWithValue }) => {
+ try {
+ await axios.delete(`purchase_invoices/${id}`)
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const create = createAsyncThunk('purchase_invoices/createPurchase_invoices', async (data: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.post(
+ 'purchase_invoices',
+ { data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const uploadCsv = createAsyncThunk(
+ 'purchase_invoices/uploadCsv',
+ async (file: File, { rejectWithValue }) => {
+ try {
+ const data = new FormData();
+ data.append('file', file);
+ data.append('filename', file.name);
+
+ const result = await axios.post('purchase_invoices/bulk-import', data, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ });
+
+ return result.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const update = createAsyncThunk('purchase_invoices/updatePurchase_invoices', async (payload: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.put(
+ `purchase_invoices/${payload.id}`,
+ { id: payload.id, data: payload.data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+
+export const purchase_invoicesSlice = createSlice({
+ name: 'purchase_invoices',
+ initialState,
+ reducers: {
+ setRefetch: (state, action: PayloadAction) => {
+ state.refetch = action.payload;
+ },
+ },
+ extraReducers: (builder) => {
+ builder.addCase(fetch.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(fetch.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(fetch.fulfilled, (state, action) => {
+ if (action.payload.rows && action.payload.count >= 0) {
+ state.purchase_invoices = action.payload.rows;
+ state.count = action.payload.count;
+ } else {
+ state.purchase_invoices = action.payload;
+ }
+ state.loading = false
+ })
+
+ builder.addCase(deleteItemsByIds.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ });
+
+ builder.addCase(deleteItemsByIds.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Purchase_invoices has been deleted');
+ });
+
+ builder.addCase(deleteItemsByIds.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ });
+
+ builder.addCase(deleteItem.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+
+ builder.addCase(deleteItem.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Purchase_invoices'.slice(0, -1)} has been deleted`);
+ })
+
+ builder.addCase(deleteItem.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(create.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Purchase_invoices'.slice(0, -1)} has been created`);
+ })
+
+ builder.addCase(update.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(update.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Purchase_invoices'.slice(0, -1)} has been updated`);
+ })
+ builder.addCase(update.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(uploadCsv.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ })
+ builder.addCase(uploadCsv.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Purchase_invoices has been uploaded');
+ })
+ builder.addCase(uploadCsv.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ })
+
+
+ },
+})
+
+// Action creators are generated for each case reducer function
+ export const { setRefetch } = purchase_invoicesSlice.actions
+
+export default purchase_invoicesSlice.reducer
diff --git a/frontend/src/stores/receipts/receiptsSlice.ts b/frontend/src/stores/receipts/receiptsSlice.ts
new file mode 100644
index 0000000..23ef6e3
--- /dev/null
+++ b/frontend/src/stores/receipts/receiptsSlice.ts
@@ -0,0 +1,231 @@
+import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
+import axios from 'axios'
+import {fulfilledNotify, rejectNotify, resetNotify} from "../../helpers/notifyStateHandler";
+
+interface MainState {
+ receipts: any
+ loading: boolean
+ count: number
+ refetch: boolean;
+ rolesWidgets: any[];
+ notify: {
+ showNotification: boolean
+ textNotification: string
+ typeNotification: string
+ }
+}
+
+const initialState: MainState = {
+ receipts: [],
+ loading: false,
+ count: 0,
+ refetch: false,
+ rolesWidgets: [],
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+}
+
+export const fetch = createAsyncThunk('receipts/fetch', async (data: any) => {
+ const { id, query } = data
+ const result = await axios.get(
+ `receipts${
+ query || (id ? `/${id}` : '')
+ }`
+ )
+ return id ? result.data : {rows: result.data.rows, count: result.data.count};
+})
+
+export const deleteItemsByIds = createAsyncThunk(
+ 'receipts/deleteByIds',
+ async (data: any, { rejectWithValue }) => {
+ try {
+ await axios.post('receipts/deleteByIds', { data });
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const deleteItem = createAsyncThunk('receipts/deleteReceipts', async (id: string, { rejectWithValue }) => {
+ try {
+ await axios.delete(`receipts/${id}`)
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const create = createAsyncThunk('receipts/createReceipts', async (data: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.post(
+ 'receipts',
+ { data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const uploadCsv = createAsyncThunk(
+ 'receipts/uploadCsv',
+ async (file: File, { rejectWithValue }) => {
+ try {
+ const data = new FormData();
+ data.append('file', file);
+ data.append('filename', file.name);
+
+ const result = await axios.post('receipts/bulk-import', data, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ });
+
+ return result.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const update = createAsyncThunk('receipts/updateReceipts', async (payload: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.put(
+ `receipts/${payload.id}`,
+ { id: payload.id, data: payload.data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+
+export const receiptsSlice = createSlice({
+ name: 'receipts',
+ initialState,
+ reducers: {
+ setRefetch: (state, action: PayloadAction) => {
+ state.refetch = action.payload;
+ },
+ },
+ extraReducers: (builder) => {
+ builder.addCase(fetch.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(fetch.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(fetch.fulfilled, (state, action) => {
+ if (action.payload.rows && action.payload.count >= 0) {
+ state.receipts = action.payload.rows;
+ state.count = action.payload.count;
+ } else {
+ state.receipts = action.payload;
+ }
+ state.loading = false
+ })
+
+ builder.addCase(deleteItemsByIds.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ });
+
+ builder.addCase(deleteItemsByIds.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Receipts has been deleted');
+ });
+
+ builder.addCase(deleteItemsByIds.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ });
+
+ builder.addCase(deleteItem.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+
+ builder.addCase(deleteItem.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Receipts'.slice(0, -1)} has been deleted`);
+ })
+
+ builder.addCase(deleteItem.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(create.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Receipts'.slice(0, -1)} has been created`);
+ })
+
+ builder.addCase(update.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(update.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Receipts'.slice(0, -1)} has been updated`);
+ })
+ builder.addCase(update.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(uploadCsv.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ })
+ builder.addCase(uploadCsv.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Receipts has been uploaded');
+ })
+ builder.addCase(uploadCsv.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ })
+
+
+ },
+})
+
+// Action creators are generated for each case reducer function
+ export const { setRefetch } = receiptsSlice.actions
+
+export default receiptsSlice.reducer
diff --git a/frontend/src/stores/roles/rolesSlice.ts b/frontend/src/stores/roles/rolesSlice.ts
new file mode 100644
index 0000000..8fe2ed7
--- /dev/null
+++ b/frontend/src/stores/roles/rolesSlice.ts
@@ -0,0 +1,280 @@
+import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
+import axios from 'axios'
+import {fulfilledNotify, rejectNotify, resetNotify} from "../../helpers/notifyStateHandler";
+
+interface MainState {
+ roles: any
+ loading: boolean
+ count: number
+ refetch: boolean;
+ rolesWidgets: any[];
+ notify: {
+ showNotification: boolean
+ textNotification: string
+ typeNotification: string
+ }
+}
+
+const initialState: MainState = {
+ roles: [],
+ loading: false,
+ count: 0,
+ refetch: false,
+ rolesWidgets: [],
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+}
+
+export const fetch = createAsyncThunk('roles/fetch', async (data: any) => {
+ const { id, query } = data
+ const result = await axios.get(
+ `roles${
+ query || (id ? `/${id}` : '')
+ }`
+ )
+ return id ? result.data : {rows: result.data.rows, count: result.data.count};
+})
+
+export const deleteItemsByIds = createAsyncThunk(
+ 'roles/deleteByIds',
+ async (data: any, { rejectWithValue }) => {
+ try {
+ await axios.post('roles/deleteByIds', { data });
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const deleteItem = createAsyncThunk('roles/deleteRoles', async (id: string, { rejectWithValue }) => {
+ try {
+ await axios.delete(`roles/${id}`)
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const create = createAsyncThunk('roles/createRoles', async (data: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.post(
+ 'roles',
+ { data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const uploadCsv = createAsyncThunk(
+ 'roles/uploadCsv',
+ async (file: File, { rejectWithValue }) => {
+ try {
+ const data = new FormData();
+ data.append('file', file);
+ data.append('filename', file.name);
+
+ const result = await axios.post('roles/bulk-import', data, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ });
+
+ return result.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const update = createAsyncThunk('roles/updateRoles', async (payload: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.put(
+ `roles/${payload.id}`,
+ { id: payload.id, data: payload.data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+
+export const removeWidget = createAsyncThunk(
+ 'openai/removeWidget',
+ async (payload: any) => {
+ const result = await axios.delete(`openai/roles-info/${payload.id}`, {
+ params: {
+ roleId: payload.roleId,
+ infoId: payload.widgetId,
+ key: 'widgets',
+ },
+ });
+ return result.data;
+ },
+);
+
+export const fetchWidgets = createAsyncThunk(
+ 'openai/fetchWidgets',
+ async (roleId: any) => {
+ const result = await axios.get(
+ `openai/info-by-key?key=widgets&roleId=${roleId}`,
+ );
+ return result.data;
+ },
+);
+
+
+export const rolesSlice = createSlice({
+ name: 'roles',
+ initialState,
+ reducers: {
+ setRefetch: (state, action: PayloadAction) => {
+ state.refetch = action.payload;
+ },
+ },
+ extraReducers: (builder) => {
+ builder.addCase(fetch.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(fetch.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(fetch.fulfilled, (state, action) => {
+ if (action.payload.rows && action.payload.count >= 0) {
+ state.roles = action.payload.rows;
+ state.count = action.payload.count;
+ } else {
+ state.roles = action.payload;
+ }
+ state.loading = false
+ })
+
+ builder.addCase(deleteItemsByIds.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ });
+
+ builder.addCase(deleteItemsByIds.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Roles has been deleted');
+ });
+
+ builder.addCase(deleteItemsByIds.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ });
+
+ builder.addCase(deleteItem.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+
+ builder.addCase(deleteItem.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Roles'.slice(0, -1)} has been deleted`);
+ })
+
+ builder.addCase(deleteItem.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(create.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Roles'.slice(0, -1)} has been created`);
+ })
+
+ builder.addCase(update.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(update.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Roles'.slice(0, -1)} has been updated`);
+ })
+ builder.addCase(update.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(uploadCsv.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ })
+ builder.addCase(uploadCsv.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Roles has been uploaded');
+ })
+ builder.addCase(uploadCsv.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ })
+
+
+ builder.addCase(removeWidget.pending, (state) => {
+ state.loading = true;
+ });
+ builder.addCase(removeWidget.fulfilled, (state) => {
+ state.loading = false;
+ });
+ builder.addCase(removeWidget.rejected, (state) => {
+ state.loading = false;
+ });
+
+
+ builder.addCase(fetchWidgets.pending, (state) => {
+ state.loading = true;
+ state.rolesWidgets = [];
+ });
+ builder.addCase(fetchWidgets.fulfilled, (state, action) => {
+ state.loading = false;
+ state.rolesWidgets = action.payload;
+ });
+ builder.addCase(fetchWidgets.rejected, (state) => {
+ state.loading = false;
+ state.rolesWidgets = [];
+ });
+
+ },
+})
+
+// Action creators are generated for each case reducer function
+ export const { setRefetch } = rolesSlice.actions
+
+export default rolesSlice.reducer
diff --git a/frontend/src/stores/sales_invoice_lines/sales_invoice_linesSlice.ts b/frontend/src/stores/sales_invoice_lines/sales_invoice_linesSlice.ts
new file mode 100644
index 0000000..f44f6be
--- /dev/null
+++ b/frontend/src/stores/sales_invoice_lines/sales_invoice_linesSlice.ts
@@ -0,0 +1,231 @@
+import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
+import axios from 'axios'
+import {fulfilledNotify, rejectNotify, resetNotify} from "../../helpers/notifyStateHandler";
+
+interface MainState {
+ sales_invoice_lines: any
+ loading: boolean
+ count: number
+ refetch: boolean;
+ rolesWidgets: any[];
+ notify: {
+ showNotification: boolean
+ textNotification: string
+ typeNotification: string
+ }
+}
+
+const initialState: MainState = {
+ sales_invoice_lines: [],
+ loading: false,
+ count: 0,
+ refetch: false,
+ rolesWidgets: [],
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+}
+
+export const fetch = createAsyncThunk('sales_invoice_lines/fetch', async (data: any) => {
+ const { id, query } = data
+ const result = await axios.get(
+ `sales_invoice_lines${
+ query || (id ? `/${id}` : '')
+ }`
+ )
+ return id ? result.data : {rows: result.data.rows, count: result.data.count};
+})
+
+export const deleteItemsByIds = createAsyncThunk(
+ 'sales_invoice_lines/deleteByIds',
+ async (data: any, { rejectWithValue }) => {
+ try {
+ await axios.post('sales_invoice_lines/deleteByIds', { data });
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const deleteItem = createAsyncThunk('sales_invoice_lines/deleteSales_invoice_lines', async (id: string, { rejectWithValue }) => {
+ try {
+ await axios.delete(`sales_invoice_lines/${id}`)
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const create = createAsyncThunk('sales_invoice_lines/createSales_invoice_lines', async (data: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.post(
+ 'sales_invoice_lines',
+ { data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const uploadCsv = createAsyncThunk(
+ 'sales_invoice_lines/uploadCsv',
+ async (file: File, { rejectWithValue }) => {
+ try {
+ const data = new FormData();
+ data.append('file', file);
+ data.append('filename', file.name);
+
+ const result = await axios.post('sales_invoice_lines/bulk-import', data, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ });
+
+ return result.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const update = createAsyncThunk('sales_invoice_lines/updateSales_invoice_lines', async (payload: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.put(
+ `sales_invoice_lines/${payload.id}`,
+ { id: payload.id, data: payload.data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+
+export const sales_invoice_linesSlice = createSlice({
+ name: 'sales_invoice_lines',
+ initialState,
+ reducers: {
+ setRefetch: (state, action: PayloadAction) => {
+ state.refetch = action.payload;
+ },
+ },
+ extraReducers: (builder) => {
+ builder.addCase(fetch.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(fetch.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(fetch.fulfilled, (state, action) => {
+ if (action.payload.rows && action.payload.count >= 0) {
+ state.sales_invoice_lines = action.payload.rows;
+ state.count = action.payload.count;
+ } else {
+ state.sales_invoice_lines = action.payload;
+ }
+ state.loading = false
+ })
+
+ builder.addCase(deleteItemsByIds.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ });
+
+ builder.addCase(deleteItemsByIds.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Sales_invoice_lines has been deleted');
+ });
+
+ builder.addCase(deleteItemsByIds.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ });
+
+ builder.addCase(deleteItem.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+
+ builder.addCase(deleteItem.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Sales_invoice_lines'.slice(0, -1)} has been deleted`);
+ })
+
+ builder.addCase(deleteItem.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(create.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Sales_invoice_lines'.slice(0, -1)} has been created`);
+ })
+
+ builder.addCase(update.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(update.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Sales_invoice_lines'.slice(0, -1)} has been updated`);
+ })
+ builder.addCase(update.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(uploadCsv.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ })
+ builder.addCase(uploadCsv.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Sales_invoice_lines has been uploaded');
+ })
+ builder.addCase(uploadCsv.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ })
+
+
+ },
+})
+
+// Action creators are generated for each case reducer function
+ export const { setRefetch } = sales_invoice_linesSlice.actions
+
+export default sales_invoice_linesSlice.reducer
diff --git a/frontend/src/stores/sales_invoices/sales_invoicesSlice.ts b/frontend/src/stores/sales_invoices/sales_invoicesSlice.ts
new file mode 100644
index 0000000..4e4af46
--- /dev/null
+++ b/frontend/src/stores/sales_invoices/sales_invoicesSlice.ts
@@ -0,0 +1,231 @@
+import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
+import axios from 'axios'
+import {fulfilledNotify, rejectNotify, resetNotify} from "../../helpers/notifyStateHandler";
+
+interface MainState {
+ sales_invoices: any
+ loading: boolean
+ count: number
+ refetch: boolean;
+ rolesWidgets: any[];
+ notify: {
+ showNotification: boolean
+ textNotification: string
+ typeNotification: string
+ }
+}
+
+const initialState: MainState = {
+ sales_invoices: [],
+ loading: false,
+ count: 0,
+ refetch: false,
+ rolesWidgets: [],
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+}
+
+export const fetch = createAsyncThunk('sales_invoices/fetch', async (data: any) => {
+ const { id, query } = data
+ const result = await axios.get(
+ `sales_invoices${
+ query || (id ? `/${id}` : '')
+ }`
+ )
+ return id ? result.data : {rows: result.data.rows, count: result.data.count};
+})
+
+export const deleteItemsByIds = createAsyncThunk(
+ 'sales_invoices/deleteByIds',
+ async (data: any, { rejectWithValue }) => {
+ try {
+ await axios.post('sales_invoices/deleteByIds', { data });
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const deleteItem = createAsyncThunk('sales_invoices/deleteSales_invoices', async (id: string, { rejectWithValue }) => {
+ try {
+ await axios.delete(`sales_invoices/${id}`)
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const create = createAsyncThunk('sales_invoices/createSales_invoices', async (data: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.post(
+ 'sales_invoices',
+ { data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const uploadCsv = createAsyncThunk(
+ 'sales_invoices/uploadCsv',
+ async (file: File, { rejectWithValue }) => {
+ try {
+ const data = new FormData();
+ data.append('file', file);
+ data.append('filename', file.name);
+
+ const result = await axios.post('sales_invoices/bulk-import', data, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ });
+
+ return result.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const update = createAsyncThunk('sales_invoices/updateSales_invoices', async (payload: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.put(
+ `sales_invoices/${payload.id}`,
+ { id: payload.id, data: payload.data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+
+export const sales_invoicesSlice = createSlice({
+ name: 'sales_invoices',
+ initialState,
+ reducers: {
+ setRefetch: (state, action: PayloadAction) => {
+ state.refetch = action.payload;
+ },
+ },
+ extraReducers: (builder) => {
+ builder.addCase(fetch.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(fetch.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(fetch.fulfilled, (state, action) => {
+ if (action.payload.rows && action.payload.count >= 0) {
+ state.sales_invoices = action.payload.rows;
+ state.count = action.payload.count;
+ } else {
+ state.sales_invoices = action.payload;
+ }
+ state.loading = false
+ })
+
+ builder.addCase(deleteItemsByIds.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ });
+
+ builder.addCase(deleteItemsByIds.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Sales_invoices has been deleted');
+ });
+
+ builder.addCase(deleteItemsByIds.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ });
+
+ builder.addCase(deleteItem.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+
+ builder.addCase(deleteItem.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Sales_invoices'.slice(0, -1)} has been deleted`);
+ })
+
+ builder.addCase(deleteItem.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(create.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Sales_invoices'.slice(0, -1)} has been created`);
+ })
+
+ builder.addCase(update.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(update.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Sales_invoices'.slice(0, -1)} has been updated`);
+ })
+ builder.addCase(update.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(uploadCsv.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ })
+ builder.addCase(uploadCsv.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Sales_invoices has been uploaded');
+ })
+ builder.addCase(uploadCsv.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ })
+
+
+ },
+})
+
+// Action creators are generated for each case reducer function
+ export const { setRefetch } = sales_invoicesSlice.actions
+
+export default sales_invoicesSlice.reducer
diff --git a/frontend/src/stores/store.ts b/frontend/src/stores/store.ts
new file mode 100644
index 0000000..d9f7113
--- /dev/null
+++ b/frontend/src/stores/store.ts
@@ -0,0 +1,65 @@
+import { configureStore } from '@reduxjs/toolkit';
+import styleReducer from './styleSlice';
+import mainReducer from './mainSlice';
+import authSlice from './authSlice';
+import openAiSlice from './openAiSlice';
+
+import usersSlice from "./users/usersSlice";
+import rolesSlice from "./roles/rolesSlice";
+import permissionsSlice from "./permissions/permissionsSlice";
+import organizationsSlice from "./organizations/organizationsSlice";
+import firmsSlice from "./firms/firmsSlice";
+import merchantsSlice from "./merchants/merchantsSlice";
+import customersSlice from "./customers/customersSlice";
+import suppliersSlice from "./suppliers/suppliersSlice";
+import productsSlice from "./products/productsSlice";
+import receiptsSlice from "./receipts/receiptsSlice";
+import ocr_extractionsSlice from "./ocr_extractions/ocr_extractionsSlice";
+import sales_invoicesSlice from "./sales_invoices/sales_invoicesSlice";
+import sales_invoice_linesSlice from "./sales_invoice_lines/sales_invoice_linesSlice";
+import purchase_invoicesSlice from "./purchase_invoices/purchase_invoicesSlice";
+import purchase_invoice_linesSlice from "./purchase_invoice_lines/purchase_invoice_linesSlice";
+import expensesSlice from "./expenses/expensesSlice";
+import tax_periodsSlice from "./tax_periods/tax_periodsSlice";
+import vat_declarationsSlice from "./vat_declarations/vat_declarationsSlice";
+import tot_declarationsSlice from "./tot_declarations/tot_declarationsSlice";
+import declaration_submissionsSlice from "./declaration_submissions/declaration_submissionsSlice";
+import messagesSlice from "./messages/messagesSlice";
+import audit_eventsSlice from "./audit_events/audit_eventsSlice";
+
+export const store = configureStore({
+ reducer: {
+ style: styleReducer,
+ main: mainReducer,
+ auth: authSlice,
+ openAi: openAiSlice,
+
+users: usersSlice,
+roles: rolesSlice,
+permissions: permissionsSlice,
+organizations: organizationsSlice,
+firms: firmsSlice,
+merchants: merchantsSlice,
+customers: customersSlice,
+suppliers: suppliersSlice,
+products: productsSlice,
+receipts: receiptsSlice,
+ocr_extractions: ocr_extractionsSlice,
+sales_invoices: sales_invoicesSlice,
+sales_invoice_lines: sales_invoice_linesSlice,
+purchase_invoices: purchase_invoicesSlice,
+purchase_invoice_lines: purchase_invoice_linesSlice,
+expenses: expensesSlice,
+tax_periods: tax_periodsSlice,
+vat_declarations: vat_declarationsSlice,
+tot_declarations: tot_declarationsSlice,
+declaration_submissions: declaration_submissionsSlice,
+messages: messagesSlice,
+audit_events: audit_eventsSlice,
+ },
+})
+
+// Infer the `RootState` and `AppDispatch` types from the store itself
+export type RootState = ReturnType
+// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
+export type AppDispatch = typeof store.dispatch
diff --git a/frontend/src/stores/styleSlice.ts b/frontend/src/stores/styleSlice.ts
new file mode 100644
index 0000000..81b0c2c
--- /dev/null
+++ b/frontend/src/stores/styleSlice.ts
@@ -0,0 +1,103 @@
+import { createSlice, PayloadAction } from '@reduxjs/toolkit'
+import * as styles from '../styles'
+import { localStorageDarkModeKey, localStorageStyleKey } from '../config'
+import { StyleKey } from '../interfaces'
+
+interface StyleState {
+ asideStyle: string
+ asideScrollbarsStyle: string
+ asideBrandStyle: string
+ asideMenuItemStyle: string
+ asideMenuItemActiveStyle: string
+ asideMenuDropdownStyle: string
+ navBarItemLabelStyle: string
+ navBarItemLabelHoverStyle: string
+ navBarItemLabelActiveColorStyle: string
+ overlayStyle: string
+ darkMode: boolean
+ bgLayoutColor: string;
+ iconsColor: string;
+ activeLinkColor: string;
+ cardsColor: string;
+ focusRingColor: string;
+ corners: string;
+ cardsStyle: string;
+ linkColor: string;
+ websiteHeder: string;
+ borders: string;
+ shadow: string;
+ websiteSectionStyle: string;
+ textSecondary: string;
+}
+
+
+const initialState: StyleState = {
+ asideStyle: styles.white.aside,
+ asideScrollbarsStyle: styles.white.asideScrollbars,
+ asideBrandStyle: styles.white.asideBrand,
+ asideMenuItemStyle: styles.white.asideMenuItem,
+ asideMenuItemActiveStyle: styles.white.asideMenuItemActive,
+ asideMenuDropdownStyle: styles.white.asideMenuDropdown,
+ navBarItemLabelStyle: styles.white.navBarItemLabel,
+ navBarItemLabelHoverStyle: styles.white.navBarItemLabelHover,
+ navBarItemLabelActiveColorStyle: styles.white.navBarItemLabelActiveColor,
+ overlayStyle: styles.white.overlay,
+ darkMode: false,
+ bgLayoutColor: styles.white.bgLayoutColor,
+ iconsColor: styles.white.iconsColor,
+ activeLinkColor: styles.white.activeLinkColor,
+ cardsColor: styles.white.cardsColor,
+ focusRingColor: styles.white.focusRingColor,
+ corners: styles.white.corners,
+ cardsStyle: styles.white.cardsStyle,
+ linkColor: styles.white.linkColor,
+ websiteHeder: styles.white.websiteHeder,
+ borders: styles.white.borders,
+ shadow: styles.white.shadow,
+ websiteSectionStyle: styles.white.websiteSectionStyle,
+ textSecondary: styles.white.textSecondary,
+}
+
+
+export const styleSlice = createSlice({
+ name: 'style',
+ initialState,
+ reducers: {
+ setDarkMode: (state, action: PayloadAction) => {
+ state.darkMode = action.payload !== null ? action.payload : !state.darkMode
+
+ if (typeof localStorage !== 'undefined') {
+ localStorage.setItem(localStorageDarkModeKey, state.darkMode ? '1' : '0')
+ }
+
+ if (typeof document !== 'undefined') {
+ document.body.classList[state.darkMode ? 'add' : 'remove']('dark-scrollbars')
+
+ document.documentElement.classList[state.darkMode ? 'add' : 'remove'](
+ 'dark-scrollbars-compat'
+ )
+ }
+ },
+
+ setStyle: (state, action: PayloadAction) => {
+ if (!styles[action.payload]) {
+ return
+ }
+
+ if (typeof localStorage !== 'undefined') {
+ localStorage.setItem(localStorageStyleKey, action.payload)
+ }
+
+ const style = styles[action.payload]
+
+ for (const key in style) {
+ state[`${key}Style`] = style[key]
+ }
+ },
+ },
+})
+
+// Action creators are generated for each case reducer function
+export const { setDarkMode, setStyle } = styleSlice.actions
+
+export default styleSlice.reducer
diff --git a/frontend/src/stores/suppliers/suppliersSlice.ts b/frontend/src/stores/suppliers/suppliersSlice.ts
new file mode 100644
index 0000000..4b7cb67
--- /dev/null
+++ b/frontend/src/stores/suppliers/suppliersSlice.ts
@@ -0,0 +1,231 @@
+import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
+import axios from 'axios'
+import {fulfilledNotify, rejectNotify, resetNotify} from "../../helpers/notifyStateHandler";
+
+interface MainState {
+ suppliers: any
+ loading: boolean
+ count: number
+ refetch: boolean;
+ rolesWidgets: any[];
+ notify: {
+ showNotification: boolean
+ textNotification: string
+ typeNotification: string
+ }
+}
+
+const initialState: MainState = {
+ suppliers: [],
+ loading: false,
+ count: 0,
+ refetch: false,
+ rolesWidgets: [],
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+}
+
+export const fetch = createAsyncThunk('suppliers/fetch', async (data: any) => {
+ const { id, query } = data
+ const result = await axios.get(
+ `suppliers${
+ query || (id ? `/${id}` : '')
+ }`
+ )
+ return id ? result.data : {rows: result.data.rows, count: result.data.count};
+})
+
+export const deleteItemsByIds = createAsyncThunk(
+ 'suppliers/deleteByIds',
+ async (data: any, { rejectWithValue }) => {
+ try {
+ await axios.post('suppliers/deleteByIds', { data });
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const deleteItem = createAsyncThunk('suppliers/deleteSuppliers', async (id: string, { rejectWithValue }) => {
+ try {
+ await axios.delete(`suppliers/${id}`)
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const create = createAsyncThunk('suppliers/createSuppliers', async (data: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.post(
+ 'suppliers',
+ { data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const uploadCsv = createAsyncThunk(
+ 'suppliers/uploadCsv',
+ async (file: File, { rejectWithValue }) => {
+ try {
+ const data = new FormData();
+ data.append('file', file);
+ data.append('filename', file.name);
+
+ const result = await axios.post('suppliers/bulk-import', data, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ });
+
+ return result.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const update = createAsyncThunk('suppliers/updateSuppliers', async (payload: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.put(
+ `suppliers/${payload.id}`,
+ { id: payload.id, data: payload.data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+
+export const suppliersSlice = createSlice({
+ name: 'suppliers',
+ initialState,
+ reducers: {
+ setRefetch: (state, action: PayloadAction) => {
+ state.refetch = action.payload;
+ },
+ },
+ extraReducers: (builder) => {
+ builder.addCase(fetch.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(fetch.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(fetch.fulfilled, (state, action) => {
+ if (action.payload.rows && action.payload.count >= 0) {
+ state.suppliers = action.payload.rows;
+ state.count = action.payload.count;
+ } else {
+ state.suppliers = action.payload;
+ }
+ state.loading = false
+ })
+
+ builder.addCase(deleteItemsByIds.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ });
+
+ builder.addCase(deleteItemsByIds.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Suppliers has been deleted');
+ });
+
+ builder.addCase(deleteItemsByIds.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ });
+
+ builder.addCase(deleteItem.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+
+ builder.addCase(deleteItem.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Suppliers'.slice(0, -1)} has been deleted`);
+ })
+
+ builder.addCase(deleteItem.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(create.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Suppliers'.slice(0, -1)} has been created`);
+ })
+
+ builder.addCase(update.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(update.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Suppliers'.slice(0, -1)} has been updated`);
+ })
+ builder.addCase(update.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(uploadCsv.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ })
+ builder.addCase(uploadCsv.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Suppliers has been uploaded');
+ })
+ builder.addCase(uploadCsv.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ })
+
+
+ },
+})
+
+// Action creators are generated for each case reducer function
+ export const { setRefetch } = suppliersSlice.actions
+
+export default suppliersSlice.reducer
diff --git a/frontend/src/stores/tax_periods/tax_periodsSlice.ts b/frontend/src/stores/tax_periods/tax_periodsSlice.ts
new file mode 100644
index 0000000..65540af
--- /dev/null
+++ b/frontend/src/stores/tax_periods/tax_periodsSlice.ts
@@ -0,0 +1,231 @@
+import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
+import axios from 'axios'
+import {fulfilledNotify, rejectNotify, resetNotify} from "../../helpers/notifyStateHandler";
+
+interface MainState {
+ tax_periods: any
+ loading: boolean
+ count: number
+ refetch: boolean;
+ rolesWidgets: any[];
+ notify: {
+ showNotification: boolean
+ textNotification: string
+ typeNotification: string
+ }
+}
+
+const initialState: MainState = {
+ tax_periods: [],
+ loading: false,
+ count: 0,
+ refetch: false,
+ rolesWidgets: [],
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+}
+
+export const fetch = createAsyncThunk('tax_periods/fetch', async (data: any) => {
+ const { id, query } = data
+ const result = await axios.get(
+ `tax_periods${
+ query || (id ? `/${id}` : '')
+ }`
+ )
+ return id ? result.data : {rows: result.data.rows, count: result.data.count};
+})
+
+export const deleteItemsByIds = createAsyncThunk(
+ 'tax_periods/deleteByIds',
+ async (data: any, { rejectWithValue }) => {
+ try {
+ await axios.post('tax_periods/deleteByIds', { data });
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const deleteItem = createAsyncThunk('tax_periods/deleteTax_periods', async (id: string, { rejectWithValue }) => {
+ try {
+ await axios.delete(`tax_periods/${id}`)
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const create = createAsyncThunk('tax_periods/createTax_periods', async (data: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.post(
+ 'tax_periods',
+ { data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const uploadCsv = createAsyncThunk(
+ 'tax_periods/uploadCsv',
+ async (file: File, { rejectWithValue }) => {
+ try {
+ const data = new FormData();
+ data.append('file', file);
+ data.append('filename', file.name);
+
+ const result = await axios.post('tax_periods/bulk-import', data, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ });
+
+ return result.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const update = createAsyncThunk('tax_periods/updateTax_periods', async (payload: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.put(
+ `tax_periods/${payload.id}`,
+ { id: payload.id, data: payload.data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+
+export const tax_periodsSlice = createSlice({
+ name: 'tax_periods',
+ initialState,
+ reducers: {
+ setRefetch: (state, action: PayloadAction) => {
+ state.refetch = action.payload;
+ },
+ },
+ extraReducers: (builder) => {
+ builder.addCase(fetch.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(fetch.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(fetch.fulfilled, (state, action) => {
+ if (action.payload.rows && action.payload.count >= 0) {
+ state.tax_periods = action.payload.rows;
+ state.count = action.payload.count;
+ } else {
+ state.tax_periods = action.payload;
+ }
+ state.loading = false
+ })
+
+ builder.addCase(deleteItemsByIds.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ });
+
+ builder.addCase(deleteItemsByIds.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Tax_periods has been deleted');
+ });
+
+ builder.addCase(deleteItemsByIds.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ });
+
+ builder.addCase(deleteItem.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+
+ builder.addCase(deleteItem.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Tax_periods'.slice(0, -1)} has been deleted`);
+ })
+
+ builder.addCase(deleteItem.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(create.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Tax_periods'.slice(0, -1)} has been created`);
+ })
+
+ builder.addCase(update.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(update.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Tax_periods'.slice(0, -1)} has been updated`);
+ })
+ builder.addCase(update.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(uploadCsv.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ })
+ builder.addCase(uploadCsv.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Tax_periods has been uploaded');
+ })
+ builder.addCase(uploadCsv.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ })
+
+
+ },
+})
+
+// Action creators are generated for each case reducer function
+ export const { setRefetch } = tax_periodsSlice.actions
+
+export default tax_periodsSlice.reducer
diff --git a/frontend/src/stores/tot_declarations/tot_declarationsSlice.ts b/frontend/src/stores/tot_declarations/tot_declarationsSlice.ts
new file mode 100644
index 0000000..7fc314a
--- /dev/null
+++ b/frontend/src/stores/tot_declarations/tot_declarationsSlice.ts
@@ -0,0 +1,231 @@
+import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
+import axios from 'axios'
+import {fulfilledNotify, rejectNotify, resetNotify} from "../../helpers/notifyStateHandler";
+
+interface MainState {
+ tot_declarations: any
+ loading: boolean
+ count: number
+ refetch: boolean;
+ rolesWidgets: any[];
+ notify: {
+ showNotification: boolean
+ textNotification: string
+ typeNotification: string
+ }
+}
+
+const initialState: MainState = {
+ tot_declarations: [],
+ loading: false,
+ count: 0,
+ refetch: false,
+ rolesWidgets: [],
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+}
+
+export const fetch = createAsyncThunk('tot_declarations/fetch', async (data: any) => {
+ const { id, query } = data
+ const result = await axios.get(
+ `tot_declarations${
+ query || (id ? `/${id}` : '')
+ }`
+ )
+ return id ? result.data : {rows: result.data.rows, count: result.data.count};
+})
+
+export const deleteItemsByIds = createAsyncThunk(
+ 'tot_declarations/deleteByIds',
+ async (data: any, { rejectWithValue }) => {
+ try {
+ await axios.post('tot_declarations/deleteByIds', { data });
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const deleteItem = createAsyncThunk('tot_declarations/deleteTot_declarations', async (id: string, { rejectWithValue }) => {
+ try {
+ await axios.delete(`tot_declarations/${id}`)
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const create = createAsyncThunk('tot_declarations/createTot_declarations', async (data: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.post(
+ 'tot_declarations',
+ { data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const uploadCsv = createAsyncThunk(
+ 'tot_declarations/uploadCsv',
+ async (file: File, { rejectWithValue }) => {
+ try {
+ const data = new FormData();
+ data.append('file', file);
+ data.append('filename', file.name);
+
+ const result = await axios.post('tot_declarations/bulk-import', data, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ });
+
+ return result.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const update = createAsyncThunk('tot_declarations/updateTot_declarations', async (payload: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.put(
+ `tot_declarations/${payload.id}`,
+ { id: payload.id, data: payload.data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+
+export const tot_declarationsSlice = createSlice({
+ name: 'tot_declarations',
+ initialState,
+ reducers: {
+ setRefetch: (state, action: PayloadAction) => {
+ state.refetch = action.payload;
+ },
+ },
+ extraReducers: (builder) => {
+ builder.addCase(fetch.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(fetch.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(fetch.fulfilled, (state, action) => {
+ if (action.payload.rows && action.payload.count >= 0) {
+ state.tot_declarations = action.payload.rows;
+ state.count = action.payload.count;
+ } else {
+ state.tot_declarations = action.payload;
+ }
+ state.loading = false
+ })
+
+ builder.addCase(deleteItemsByIds.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ });
+
+ builder.addCase(deleteItemsByIds.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Tot_declarations has been deleted');
+ });
+
+ builder.addCase(deleteItemsByIds.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ });
+
+ builder.addCase(deleteItem.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+
+ builder.addCase(deleteItem.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Tot_declarations'.slice(0, -1)} has been deleted`);
+ })
+
+ builder.addCase(deleteItem.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(create.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Tot_declarations'.slice(0, -1)} has been created`);
+ })
+
+ builder.addCase(update.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(update.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Tot_declarations'.slice(0, -1)} has been updated`);
+ })
+ builder.addCase(update.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(uploadCsv.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ })
+ builder.addCase(uploadCsv.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Tot_declarations has been uploaded');
+ })
+ builder.addCase(uploadCsv.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ })
+
+
+ },
+})
+
+// Action creators are generated for each case reducer function
+ export const { setRefetch } = tot_declarationsSlice.actions
+
+export default tot_declarationsSlice.reducer
diff --git a/frontend/src/stores/users/usersSlice.ts b/frontend/src/stores/users/usersSlice.ts
new file mode 100644
index 0000000..96013aa
--- /dev/null
+++ b/frontend/src/stores/users/usersSlice.ts
@@ -0,0 +1,231 @@
+import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
+import axios from 'axios'
+import {fulfilledNotify, rejectNotify, resetNotify} from "../../helpers/notifyStateHandler";
+
+interface MainState {
+ users: any
+ loading: boolean
+ count: number
+ refetch: boolean;
+ rolesWidgets: any[];
+ notify: {
+ showNotification: boolean
+ textNotification: string
+ typeNotification: string
+ }
+}
+
+const initialState: MainState = {
+ users: [],
+ loading: false,
+ count: 0,
+ refetch: false,
+ rolesWidgets: [],
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+}
+
+export const fetch = createAsyncThunk('users/fetch', async (data: any) => {
+ const { id, query } = data
+ const result = await axios.get(
+ `users${
+ query || (id ? `/${id}` : '')
+ }`
+ )
+ return id ? result.data : {rows: result.data.rows, count: result.data.count};
+})
+
+export const deleteItemsByIds = createAsyncThunk(
+ 'users/deleteByIds',
+ async (data: any, { rejectWithValue }) => {
+ try {
+ await axios.post('users/deleteByIds', { data });
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const deleteItem = createAsyncThunk('users/deleteUsers', async (id: string, { rejectWithValue }) => {
+ try {
+ await axios.delete(`users/${id}`)
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const create = createAsyncThunk('users/createUsers', async (data: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.post(
+ 'users',
+ { data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const uploadCsv = createAsyncThunk(
+ 'users/uploadCsv',
+ async (file: File, { rejectWithValue }) => {
+ try {
+ const data = new FormData();
+ data.append('file', file);
+ data.append('filename', file.name);
+
+ const result = await axios.post('users/bulk-import', data, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ });
+
+ return result.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const update = createAsyncThunk('users/updateUsers', async (payload: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.put(
+ `users/${payload.id}`,
+ { id: payload.id, data: payload.data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+
+export const usersSlice = createSlice({
+ name: 'users',
+ initialState,
+ reducers: {
+ setRefetch: (state, action: PayloadAction) => {
+ state.refetch = action.payload;
+ },
+ },
+ extraReducers: (builder) => {
+ builder.addCase(fetch.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(fetch.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(fetch.fulfilled, (state, action) => {
+ if (action.payload.rows && action.payload.count >= 0) {
+ state.users = action.payload.rows;
+ state.count = action.payload.count;
+ } else {
+ state.users = action.payload;
+ }
+ state.loading = false
+ })
+
+ builder.addCase(deleteItemsByIds.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ });
+
+ builder.addCase(deleteItemsByIds.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Users has been deleted');
+ });
+
+ builder.addCase(deleteItemsByIds.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ });
+
+ builder.addCase(deleteItem.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+
+ builder.addCase(deleteItem.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Users'.slice(0, -1)} has been deleted`);
+ })
+
+ builder.addCase(deleteItem.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(create.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Users'.slice(0, -1)} has been created`);
+ })
+
+ builder.addCase(update.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(update.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Users'.slice(0, -1)} has been updated`);
+ })
+ builder.addCase(update.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(uploadCsv.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ })
+ builder.addCase(uploadCsv.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Users has been uploaded');
+ })
+ builder.addCase(uploadCsv.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ })
+
+
+ },
+})
+
+// Action creators are generated for each case reducer function
+ export const { setRefetch } = usersSlice.actions
+
+export default usersSlice.reducer
diff --git a/frontend/src/stores/usersSlice.ts b/frontend/src/stores/usersSlice.ts
new file mode 100644
index 0000000..c03ffc9
--- /dev/null
+++ b/frontend/src/stores/usersSlice.ts
@@ -0,0 +1,117 @@
+import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
+import axios from 'axios'
+
+interface MainState {
+ users: any
+ loading: boolean
+ notify: {
+ showNotification: boolean
+ textNotification: string
+ typeNotification: string
+ }
+}
+
+const initialState: MainState = {
+ users: [],
+ loading: false,
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+}
+
+export const fetch = createAsyncThunk('users/fetch', async (data: any) => {
+ const { id, query } = data
+ const result = await axios.get(
+ `users${
+ query || (id ? `/${id}` : '')
+ }`
+ )
+ return id ? result.data : result.data.rows
+})
+
+export const deleteItem = createAsyncThunk('users/deleteUser', async (id: string, thunkAPI) => {
+ try {
+ await axios.delete(`users/${id}`)
+ thunkAPI.dispatch(fetch({ id: '', query: '' }))
+ } catch (error) {
+ console.log(error)
+ }
+
+ // showNotification('Users has been deleted', 'success');
+})
+
+export const create = createAsyncThunk('users/createUser', async (data: any) => {
+ const result = await axios.post(
+ 'users',
+ { data }
+ )
+ // showNotification('Users has been created', 'success');
+ return result.data
+})
+
+export const update = createAsyncThunk('users/updateUser', async (payload: any) => {
+ const result = await axios.put(
+ `users/${payload.id}`,
+ { id: payload.id, data: payload.data }
+ )
+ return result.data
+})
+
+export const usersSlice = createSlice({
+ name: 'users',
+ initialState,
+ reducers: {},
+ extraReducers: (builder) => {
+ builder.addCase(fetch.pending, (state) => {
+ state.loading = true
+ })
+ builder.addCase(fetch.rejected, (state) => {
+ state.loading = false
+ })
+
+ builder.addCase(fetch.fulfilled, (state, action) => {
+ state.users = action.payload
+ state.loading = false
+ })
+
+ builder.addCase(deleteItem.pending, (state) => {
+ state.loading = true
+ })
+
+ builder.addCase(deleteItem.fulfilled, (state) => {
+ state.loading = false
+ })
+
+ builder.addCase(deleteItem.rejected, (state) => {
+ state.loading = false
+ })
+
+ builder.addCase(create.pending, (state) => {
+ state.loading = true
+ })
+ builder.addCase(create.rejected, (state) => {
+ state.loading = false
+ })
+
+ builder.addCase(create.fulfilled, (state) => {
+ state.loading = false
+ })
+
+ builder.addCase(update.pending, (state) => {
+ state.loading = true
+ })
+ builder.addCase(update.fulfilled, (state) => {
+ state.loading = false
+ })
+ builder.addCase(update.rejected, (state) => {
+ state.loading = false
+ })
+ },
+})
+
+// Action creators are generated for each case reducer function
+// export const { } = usersSlice.actions
+
+export default usersSlice.reducer
diff --git a/frontend/src/stores/vat_declarations/vat_declarationsSlice.ts b/frontend/src/stores/vat_declarations/vat_declarationsSlice.ts
new file mode 100644
index 0000000..6ea01bc
--- /dev/null
+++ b/frontend/src/stores/vat_declarations/vat_declarationsSlice.ts
@@ -0,0 +1,231 @@
+import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
+import axios from 'axios'
+import {fulfilledNotify, rejectNotify, resetNotify} from "../../helpers/notifyStateHandler";
+
+interface MainState {
+ vat_declarations: any
+ loading: boolean
+ count: number
+ refetch: boolean;
+ rolesWidgets: any[];
+ notify: {
+ showNotification: boolean
+ textNotification: string
+ typeNotification: string
+ }
+}
+
+const initialState: MainState = {
+ vat_declarations: [],
+ loading: false,
+ count: 0,
+ refetch: false,
+ rolesWidgets: [],
+ notify: {
+ showNotification: false,
+ textNotification: '',
+ typeNotification: 'warn',
+ },
+}
+
+export const fetch = createAsyncThunk('vat_declarations/fetch', async (data: any) => {
+ const { id, query } = data
+ const result = await axios.get(
+ `vat_declarations${
+ query || (id ? `/${id}` : '')
+ }`
+ )
+ return id ? result.data : {rows: result.data.rows, count: result.data.count};
+})
+
+export const deleteItemsByIds = createAsyncThunk(
+ 'vat_declarations/deleteByIds',
+ async (data: any, { rejectWithValue }) => {
+ try {
+ await axios.post('vat_declarations/deleteByIds', { data });
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const deleteItem = createAsyncThunk('vat_declarations/deleteVat_declarations', async (id: string, { rejectWithValue }) => {
+ try {
+ await axios.delete(`vat_declarations/${id}`)
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const create = createAsyncThunk('vat_declarations/createVat_declarations', async (data: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.post(
+ 'vat_declarations',
+ { data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+export const uploadCsv = createAsyncThunk(
+ 'vat_declarations/uploadCsv',
+ async (file: File, { rejectWithValue }) => {
+ try {
+ const data = new FormData();
+ data.append('file', file);
+ data.append('filename', file.name);
+
+ const result = await axios.post('vat_declarations/bulk-import', data, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ });
+
+ return result.data;
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+ },
+);
+
+export const update = createAsyncThunk('vat_declarations/updateVat_declarations', async (payload: any, { rejectWithValue }) => {
+ try {
+ const result = await axios.put(
+ `vat_declarations/${payload.id}`,
+ { id: payload.id, data: payload.data }
+ )
+ return result.data
+ } catch (error) {
+ if (!error.response) {
+ throw error;
+ }
+
+ return rejectWithValue(error.response.data);
+ }
+})
+
+
+export const vat_declarationsSlice = createSlice({
+ name: 'vat_declarations',
+ initialState,
+ reducers: {
+ setRefetch: (state, action: PayloadAction) => {
+ state.refetch = action.payload;
+ },
+ },
+ extraReducers: (builder) => {
+ builder.addCase(fetch.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(fetch.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(fetch.fulfilled, (state, action) => {
+ if (action.payload.rows && action.payload.count >= 0) {
+ state.vat_declarations = action.payload.rows;
+ state.count = action.payload.count;
+ } else {
+ state.vat_declarations = action.payload;
+ }
+ state.loading = false
+ })
+
+ builder.addCase(deleteItemsByIds.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ });
+
+ builder.addCase(deleteItemsByIds.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Vat_declarations has been deleted');
+ });
+
+ builder.addCase(deleteItemsByIds.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ });
+
+ builder.addCase(deleteItem.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+
+ builder.addCase(deleteItem.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Vat_declarations'.slice(0, -1)} has been deleted`);
+ })
+
+ builder.addCase(deleteItem.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(create.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(create.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Vat_declarations'.slice(0, -1)} has been created`);
+ })
+
+ builder.addCase(update.pending, (state) => {
+ state.loading = true
+ resetNotify(state);
+ })
+ builder.addCase(update.fulfilled, (state) => {
+ state.loading = false
+ fulfilledNotify(state, `${'Vat_declarations'.slice(0, -1)} has been updated`);
+ })
+ builder.addCase(update.rejected, (state, action) => {
+ state.loading = false
+ rejectNotify(state, action);
+ })
+
+ builder.addCase(uploadCsv.pending, (state) => {
+ state.loading = true;
+ resetNotify(state);
+ })
+ builder.addCase(uploadCsv.fulfilled, (state) => {
+ state.loading = false;
+ fulfilledNotify(state, 'Vat_declarations has been uploaded');
+ })
+ builder.addCase(uploadCsv.rejected, (state, action) => {
+ state.loading = false;
+ rejectNotify(state, action);
+ })
+
+
+ },
+})
+
+// Action creators are generated for each case reducer function
+ export const { setRefetch } = vat_declarationsSlice.actions
+
+export default vat_declarationsSlice.reducer
diff --git a/frontend/src/styles.ts b/frontend/src/styles.ts
new file mode 100644
index 0000000..a969b60
--- /dev/null
+++ b/frontend/src/styles.ts
@@ -0,0 +1,107 @@
+interface StyleObject {
+ aside: string
+ asideScrollbars: string
+ asideBrand: string
+ asideMenuItem: string
+ asideMenuItemActive: string
+ asideMenuDropdown: string
+ navBarItemLabel: string
+ navBarItemLabelHover: string
+ navBarItemLabelActiveColor: string
+ overlay: string
+ activeLinkColor: string;
+ bgLayoutColor: string;
+ iconsColor: string;
+ cardsColor: string;
+ focusRingColor: string;
+ corners: string;
+ cardsStyle: string;
+ linkColor: string;
+ websiteHeder: string;
+ borders: string;
+ shadow: string;
+ websiteSectionStyle: string;
+ textSecondary: string;
+}
+
+export const white: StyleObject = {
+ aside: 'bg-white dark:text-white',
+ asideScrollbars: 'aside-scrollbars-light',
+ asideBrand: '',
+ asideMenuItem: 'text-gray-700 hover:bg-gray-100/70 dark:text-dark-500 dark:hover:text-white dark:hover:bg-dark-800',
+ asideMenuItemActive: 'font-bold text-black dark:text-white',
+ asideMenuDropdown: 'bg-gray-100/75',
+ navBarItemLabel: 'text-blue-600',
+ navBarItemLabelHover: 'hover:text-black',
+ navBarItemLabelActiveColor: 'text-black',
+ overlay: 'from-white via-gray-100 to-white',
+ activeLinkColor: 'bg-gray-100/70',
+ bgLayoutColor: 'bg-gray-50',
+ iconsColor: 'text-blue-500',
+ cardsColor: 'bg-white',
+ focusRingColor: 'focus:ring focus:ring-blue-600 focus:border-blue-600 focus:outline-none border-gray-300 dark:focus:ring-blue-600 dark:focus:border-blue-600',
+ corners: 'rounded',
+ cardsStyle: 'bg-white border border-pavitra-400',
+ linkColor: 'text-blue-600',
+ websiteHeder: 'border-b border-gray-200',
+ borders: 'border-gray-200',
+ shadow: '',
+ websiteSectionStyle: '',
+ textSecondary: 'text-gray-500',
+}
+
+
+
+
+
+export const dataGridStyles = {
+ '& .MuiDataGrid-cell': {
+ paddingX: 3,
+ border: 'none',
+ },
+ '& .MuiDataGrid-columnHeader': {
+ paddingX: 3,
+ },
+ '& .MuiDataGrid-columnHeaderCheckbox': {
+ paddingX: 0,
+ },
+ '& .MuiDataGrid-columnHeaders': {
+ paddingY: 4,
+ borderStartStartRadius: 7,
+ borderStartEndRadius: 7,
+ },
+ '& .MuiDataGrid-footerContainer': {
+ paddingY: 0.5,
+ borderEndStartRadius: 7,
+ borderEndEndRadius: 7,
+ },
+ '& .MuiDataGrid-root': {
+ border: 'none',
+ },
+};
+
+export const basic: StyleObject = {
+ aside: 'bg-gray-800',
+ asideScrollbars: 'aside-scrollbars-gray',
+ asideBrand: 'bg-gray-900 text-white',
+ asideMenuItem: 'text-gray-300 hover:text-white',
+ asideMenuItemActive: 'font-bold text-white',
+ asideMenuDropdown: 'bg-gray-700/50',
+ navBarItemLabel: 'text-black',
+ navBarItemLabelHover: 'hover:text-blue-500',
+ navBarItemLabelActiveColor: 'text-blue-600',
+ overlay: 'from-gray-700 via-gray-900 to-gray-700',
+ activeLinkColor: 'bg-gray-100/70',
+ bgLayoutColor: 'bg-gray-50',
+ iconsColor: 'text-blue-500',
+ cardsColor: 'bg-white',
+ focusRingColor: 'focus:ring focus:ring-blue-600 focus:border-blue-600 focus:outline-none dark:focus:ring-blue-600 border-gray-300 dark:focus:border-blue-600',
+ corners: 'rounded',
+ cardsStyle: 'bg-white border border-pavitra-400',
+ linkColor: 'text-black',
+ websiteHeder: '',
+ borders: '',
+ shadow: '',
+ websiteSectionStyle: '',
+ textSecondary: '',
+}
diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js
new file mode 100644
index 0000000..a06c7d1
--- /dev/null
+++ b/frontend/tailwind.config.js
@@ -0,0 +1,110 @@
+/* eslint-env node */
+/* eslint-disable-next-line */
+const plugin = require('tailwindcss/plugin')
+
+module.exports = {
+ content: [
+ './src/**/*.{js,ts,jsx,tsx}',
+ ],
+ darkMode: 'class', // or 'media' or 'class'
+ theme: {
+ asideScrollbars: {
+ light: 'light',
+ gray: 'gray'
+ },
+ extend: {
+ zIndex: {
+ '-1': '-1'
+ },
+ flexGrow: {
+ 5: '5'
+ },
+ maxHeight: {
+ 'screen-menu': 'calc(100vh - 3.5rem)',
+ modal: 'calc(100vh - 160px)'
+ },
+ transitionProperty: {
+ position: 'right, left, top, bottom, margin, padding',
+ textColor: 'color'
+ },
+ keyframes: {
+ 'fade-out': {
+ from: { opacity: 1 },
+ to: { opacity: 0 }
+ },
+ 'fade-in': {
+ from: { opacity: 0 },
+ to: { opacity: 1 }
+ }
+ },
+ animation: {
+ 'fade-out': 'fade-out 250ms ease-in-out',
+ 'fade-in': 'fade-in 250ms ease-in-out'
+ },
+ colors: {
+ dark: {
+ 900: '#131618',
+ 800: '#21242A',
+ 700: '#2C2F36',
+ 600: '#9CA3AF',
+ 500: '#CBD5E1',
+ },
+ green:{
+ text: '#45B26B',
+ },
+ 'pavitra': {
+ 'blue': '#0162FD',
+ 'green': '#00B448',
+ 'orange': '#FFAA00',
+ 'red': '#F20041',
+ 900: '#14142A',
+ 800: '#4E4B66',
+ 700: '#6E7191',
+ 600: '#A0A3BD',
+ 500: '#D9DBE9',
+ 400: '#EFF0F6',
+ 300: '#F7F7FC'
+ },
+
+
+ },
+ borderRadius: {
+ '3xl': '2rem',
+ },
+ }
+ },
+ plugins: [
+ require('@tailwindcss/forms'),
+ require('@tailwindcss/typography'),
+ plugin(function ({ matchUtilities, theme }) {
+ matchUtilities(
+ {
+ 'aside-scrollbars': (value) => {
+ const track = value === 'light' ? '100' : '900';
+ const thumb = value === 'light' ? '300' : '600';
+ const color = value === 'light' ? 'gray' : value;
+
+ return {
+ scrollbarWidth: 'thin',
+ scrollbarColor: `${theme(`colors.${color}.${thumb}`)} ${theme(
+ `colors.${color}.${track}`,
+ )}`,
+ '&::-webkit-scrollbar': {
+ width: '8px',
+ height: '8px',
+ },
+ '&::-webkit-scrollbar-track': {
+ backgroundColor: theme(`colors.${color}.${track}`),
+ },
+ '&::-webkit-scrollbar-thumb': {
+ borderRadius: '0.25rem',
+ backgroundColor: theme(`colors.${color}.${thumb}`),
+ },
+ };
+ },
+ },
+ { values: theme('asideScrollbars') },
+ );
+ }),
+ ],
+}
diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json
new file mode 100644
index 0000000..5bee8c4
--- /dev/null
+++ b/frontend/tsconfig.json
@@ -0,0 +1,30 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "forceConsistentCasingInFileNames": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "incremental": true
+ },
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/frontend/yarn.lock b/frontend/yarn.lock
new file mode 100644
index 0000000..5c2e352
--- /dev/null
+++ b/frontend/yarn.lock
@@ -0,0 +1,3608 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@alloc/quick-lru@^5.2.0":
+ version "5.2.0"
+ resolved "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz"
+ integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==
+
+"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.2":
+ version "7.26.2"
+ resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz"
+ integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.25.9"
+ js-tokens "^4.0.0"
+ picocolors "^1.0.0"
+
+"@babel/generator@^7.26.3":
+ version "7.26.3"
+ resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz"
+ integrity sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==
+ dependencies:
+ "@babel/parser" "^7.26.3"
+ "@babel/types" "^7.26.3"
+ "@jridgewell/gen-mapping" "^0.3.5"
+ "@jridgewell/trace-mapping" "^0.3.25"
+ jsesc "^3.0.2"
+
+"@babel/helper-module-imports@^7.16.7":
+ version "7.25.9"
+ resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz"
+ integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==
+ dependencies:
+ "@babel/traverse" "^7.25.9"
+ "@babel/types" "^7.25.9"
+
+"@babel/helper-string-parser@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz"
+ integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==
+
+"@babel/helper-validator-identifier@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz"
+ integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==
+
+"@babel/parser@^7.25.9", "@babel/parser@^7.26.3":
+ version "7.26.3"
+ resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz"
+ integrity sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==
+ dependencies:
+ "@babel/types" "^7.26.3"
+
+"@babel/runtime-corejs3@^7.10.2":
+ version "7.19.0"
+ resolved "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.19.0.tgz"
+ integrity sha512-JyXXoCu1N8GLuKc2ii8y5RGma5FMpFeO2nAQIe0Yzrbq+rQnN+sFj47auLblR5ka6aHNGPDgv8G/iI2Grb0ldQ==
+ dependencies:
+ core-js-pure "^3.20.2"
+ regenerator-runtime "^0.13.4"
+
+"@babel/runtime@^7.10.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.9", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.23.2", "@babel/runtime@^7.23.9", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
+ version "7.26.0"
+ resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz"
+ integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==
+ dependencies:
+ regenerator-runtime "^0.14.0"
+
+"@babel/template@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz"
+ integrity sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==
+ dependencies:
+ "@babel/code-frame" "^7.25.9"
+ "@babel/parser" "^7.25.9"
+ "@babel/types" "^7.25.9"
+
+"@babel/traverse@^7.25.9":
+ version "7.26.4"
+ resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.4.tgz"
+ integrity sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==
+ dependencies:
+ "@babel/code-frame" "^7.26.2"
+ "@babel/generator" "^7.26.3"
+ "@babel/parser" "^7.26.3"
+ "@babel/template" "^7.25.9"
+ "@babel/types" "^7.26.3"
+ debug "^4.3.1"
+ globals "^11.1.0"
+
+"@babel/types@^7.25.9", "@babel/types@^7.26.3":
+ version "7.26.3"
+ resolved "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz"
+ integrity sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==
+ dependencies:
+ "@babel/helper-string-parser" "^7.25.9"
+ "@babel/helper-validator-identifier" "^7.25.9"
+
+"@emotion/babel-plugin@^11.13.5":
+ version "11.13.5"
+ resolved "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz"
+ integrity sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==
+ dependencies:
+ "@babel/helper-module-imports" "^7.16.7"
+ "@babel/runtime" "^7.18.3"
+ "@emotion/hash" "^0.9.2"
+ "@emotion/memoize" "^0.9.0"
+ "@emotion/serialize" "^1.3.3"
+ babel-plugin-macros "^3.1.0"
+ convert-source-map "^1.5.0"
+ escape-string-regexp "^4.0.0"
+ find-root "^1.1.0"
+ source-map "^0.5.7"
+ stylis "4.2.0"
+
+"@emotion/cache@^11.13.5", "@emotion/cache@^11.14.0", "@emotion/cache@^11.4.0":
+ version "11.14.0"
+ resolved "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz"
+ integrity sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==
+ dependencies:
+ "@emotion/memoize" "^0.9.0"
+ "@emotion/sheet" "^1.4.0"
+ "@emotion/utils" "^1.4.2"
+ "@emotion/weak-memoize" "^0.4.0"
+ stylis "4.2.0"
+
+"@emotion/hash@^0.9.2":
+ version "0.9.2"
+ resolved "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz"
+ integrity sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==
+
+"@emotion/is-prop-valid@^1.3.0":
+ version "1.3.1"
+ resolved "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz"
+ integrity sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==
+ dependencies:
+ "@emotion/memoize" "^0.9.0"
+
+"@emotion/memoize@^0.9.0":
+ version "0.9.0"
+ resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz"
+ integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==
+
+"@emotion/react@^11.11.3", "@emotion/react@^11.8.1":
+ version "11.14.0"
+ resolved "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz"
+ integrity sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==
+ dependencies:
+ "@babel/runtime" "^7.18.3"
+ "@emotion/babel-plugin" "^11.13.5"
+ "@emotion/cache" "^11.14.0"
+ "@emotion/serialize" "^1.3.3"
+ "@emotion/use-insertion-effect-with-fallbacks" "^1.2.0"
+ "@emotion/utils" "^1.4.2"
+ "@emotion/weak-memoize" "^0.4.0"
+ hoist-non-react-statics "^3.3.1"
+
+"@emotion/serialize@^1.3.3":
+ version "1.3.3"
+ resolved "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz"
+ integrity sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==
+ dependencies:
+ "@emotion/hash" "^0.9.2"
+ "@emotion/memoize" "^0.9.0"
+ "@emotion/unitless" "^0.10.0"
+ "@emotion/utils" "^1.4.2"
+ csstype "^3.0.2"
+
+"@emotion/sheet@^1.4.0":
+ version "1.4.0"
+ resolved "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz"
+ integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==
+
+"@emotion/styled@^11.11.0":
+ version "11.14.0"
+ resolved "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.0.tgz"
+ integrity sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA==
+ dependencies:
+ "@babel/runtime" "^7.18.3"
+ "@emotion/babel-plugin" "^11.13.5"
+ "@emotion/is-prop-valid" "^1.3.0"
+ "@emotion/serialize" "^1.3.3"
+ "@emotion/use-insertion-effect-with-fallbacks" "^1.2.0"
+ "@emotion/utils" "^1.4.2"
+
+"@emotion/unitless@^0.10.0":
+ version "0.10.0"
+ resolved "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz"
+ integrity sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==
+
+"@emotion/use-insertion-effect-with-fallbacks@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz"
+ integrity sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==
+
+"@emotion/utils@^1.4.2":
+ version "1.4.2"
+ resolved "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz"
+ integrity sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==
+
+"@emotion/weak-memoize@^0.4.0":
+ version "0.4.0"
+ resolved "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz"
+ integrity sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==
+
+"@eslint/eslintrc@^1.3.2":
+ version "1.3.2"
+ resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.2.tgz"
+ integrity sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ==
+ dependencies:
+ ajv "^6.12.4"
+ debug "^4.3.2"
+ espree "^9.4.0"
+ globals "^13.15.0"
+ ignore "^5.2.0"
+ import-fresh "^3.2.1"
+ js-yaml "^4.1.0"
+ minimatch "^3.1.2"
+ strip-json-comments "^3.1.1"
+
+"@floating-ui/core@^1.6.0":
+ version "1.6.8"
+ resolved "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.8.tgz"
+ integrity sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==
+ dependencies:
+ "@floating-ui/utils" "^0.2.8"
+
+"@floating-ui/dom@^1.0.1":
+ version "1.6.12"
+ resolved "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.12.tgz"
+ integrity sha512-NP83c0HjokcGVEMeoStg317VD9W7eDlGK7457dMBANbKA6GJZdc7rjujdgqzTaz93jkGgc5P/jeWbaCHnMNc+w==
+ dependencies:
+ "@floating-ui/core" "^1.6.0"
+ "@floating-ui/utils" "^0.2.8"
+
+"@floating-ui/utils@^0.2.8":
+ version "0.2.8"
+ resolved "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz"
+ integrity sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==
+
+"@humanwhocodes/config-array@^0.10.4":
+ version "0.10.4"
+ resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz"
+ integrity sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==
+ dependencies:
+ "@humanwhocodes/object-schema" "^1.2.1"
+ debug "^4.1.1"
+ minimatch "^3.0.4"
+
+"@humanwhocodes/gitignore-to-minimatch@^1.0.2":
+ version "1.0.2"
+ resolved "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz"
+ integrity sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==
+
+"@humanwhocodes/module-importer@^1.0.1":
+ version "1.0.1"
+ resolved "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz"
+ integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==
+
+"@humanwhocodes/object-schema@^1.2.1":
+ version "1.2.1"
+ resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz"
+ integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
+
+"@isaacs/cliui@^8.0.2":
+ version "8.0.2"
+ resolved "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz"
+ integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==
+ dependencies:
+ string-width "^5.1.2"
+ string-width-cjs "npm:string-width@^4.2.0"
+ strip-ansi "^7.0.1"
+ strip-ansi-cjs "npm:strip-ansi@^6.0.1"
+ wrap-ansi "^8.1.0"
+ wrap-ansi-cjs "npm:wrap-ansi@^7.0.0"
+
+"@jridgewell/gen-mapping@^0.3.2", "@jridgewell/gen-mapping@^0.3.5":
+ version "0.3.8"
+ resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz"
+ integrity sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==
+ dependencies:
+ "@jridgewell/set-array" "^1.2.1"
+ "@jridgewell/sourcemap-codec" "^1.4.10"
+ "@jridgewell/trace-mapping" "^0.3.24"
+
+"@jridgewell/resolve-uri@^3.1.0":
+ version "3.1.2"
+ resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz"
+ integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==
+
+"@jridgewell/set-array@^1.2.1":
+ version "1.2.1"
+ resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz"
+ integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==
+
+"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14":
+ version "1.5.0"
+ resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz"
+ integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==
+
+"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25":
+ version "0.3.25"
+ resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz"
+ integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==
+ dependencies:
+ "@jridgewell/resolve-uri" "^3.1.0"
+ "@jridgewell/sourcemap-codec" "^1.4.14"
+
+"@kurkle/color@^0.3.0":
+ version "0.3.4"
+ resolved "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz"
+ integrity sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==
+
+"@mdi/js@^7.4.47":
+ version "7.4.47"
+ resolved "https://registry.npmjs.org/@mdi/js/-/js-7.4.47.tgz"
+ integrity sha512-KPnNOtm5i2pMabqZxpUz7iQf+mfrYZyKCZ8QNz85czgEt7cuHcGorWfdzUMWYA0SD+a6Hn4FmJ+YhzzzjkTZrQ==
+
+"@mui/core-downloads-tracker@^5.16.13":
+ version "5.16.13"
+ resolved "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.13.tgz"
+ integrity sha512-xe5RwI0Q2O709Bd2Y7l1W1NIwNmln0y+xaGk5VgX3vDJbkQEqzdfTFZ73e0CkEZgJwyiWgk5HY0l8R4nysOxjw==
+
+"@mui/material@^5.15.7":
+ version "5.16.13"
+ resolved "https://registry.npmjs.org/@mui/material/-/material-5.16.13.tgz"
+ integrity sha512-FhLDkDPYDzvrWCHFsdXzRArhS4AdYufU8d69rmLL+bwhodPcbm2C7cS8Gq5VR32PsW6aKZb58gvAgvEVaiiJbA==
+ dependencies:
+ "@babel/runtime" "^7.23.9"
+ "@mui/core-downloads-tracker" "^5.16.13"
+ "@mui/system" "^5.16.13"
+ "@mui/types" "^7.2.15"
+ "@mui/utils" "^5.16.13"
+ "@popperjs/core" "^2.11.8"
+ "@types/react-transition-group" "^4.4.10"
+ clsx "^2.1.0"
+ csstype "^3.1.3"
+ prop-types "^15.8.1"
+ react-is "^19.0.0"
+ react-transition-group "^4.4.5"
+
+"@mui/private-theming@^5.16.13":
+ version "5.16.13"
+ resolved "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.16.13.tgz"
+ integrity sha512-+s0FklvDvO7j0yBZn19DIIT3rLfub2fWvXGtMX49rG/xHfDFcP7fbWbZKHZMMP/2/IoTRDrZCbY1iP0xZlmuJA==
+ dependencies:
+ "@babel/runtime" "^7.23.9"
+ "@mui/utils" "^5.16.13"
+ prop-types "^15.8.1"
+
+"@mui/styled-engine@^5.16.13":
+ version "5.16.13"
+ resolved "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.16.13.tgz"
+ integrity sha512-2XNHEG8/o1ucSLhTA9J+HIIXjzlnEc0OV7kneeUQ5JukErPYT2zc6KYBDLjlKWrzQyvnQzbiffjjspgHUColZg==
+ dependencies:
+ "@babel/runtime" "^7.23.9"
+ "@emotion/cache" "^11.13.5"
+ csstype "^3.1.3"
+ prop-types "^15.8.1"
+
+"@mui/system@^5.16.13":
+ version "5.16.13"
+ resolved "https://registry.npmjs.org/@mui/system/-/system-5.16.13.tgz"
+ integrity sha512-JnO3VH3yNoAmgyr44/2jiS1tcNwshwAqAaG5fTEEjHQbkuZT/mvPYj2GC1cON0zEQ5V03xrCNl/D+gU9AXibpw==
+ dependencies:
+ "@babel/runtime" "^7.23.9"
+ "@mui/private-theming" "^5.16.13"
+ "@mui/styled-engine" "^5.16.13"
+ "@mui/types" "^7.2.15"
+ "@mui/utils" "^5.16.13"
+ clsx "^2.1.0"
+ csstype "^3.1.3"
+ prop-types "^15.8.1"
+
+"@mui/types@^7.2.15":
+ version "7.2.20"
+ resolved "https://registry.npmjs.org/@mui/types/-/types-7.2.20.tgz"
+ integrity sha512-straFHD7L8v05l/N5vcWk+y7eL9JF0C2mtph/y4BPm3gn2Eh61dDwDB65pa8DLss3WJfDXYC7Kx5yjP0EmXpgw==
+
+"@mui/utils@^5.14.16", "@mui/utils@^5.16.13":
+ version "5.16.13"
+ resolved "https://registry.npmjs.org/@mui/utils/-/utils-5.16.13.tgz"
+ integrity sha512-35kLiShnDPByk57Mz4PP66fQUodCFiOD92HfpW6dK9lc7kjhZsKHRKeYPgWuwEHeXwYsCSFtBCW4RZh/8WT+TQ==
+ dependencies:
+ "@babel/runtime" "^7.23.9"
+ "@mui/types" "^7.2.15"
+ "@types/prop-types" "^15.7.12"
+ clsx "^2.1.1"
+ prop-types "^15.8.1"
+ react-is "^19.0.0"
+
+"@mui/x-data-grid@^6.19.2":
+ version "6.20.4"
+ resolved "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-6.20.4.tgz"
+ integrity sha512-I0JhinVV4e25hD2dB+R6biPBtpGeFrXf8RwlMPQbr9gUggPmPmNtWKo8Kk2PtBBMlGtdMAgHWe7PqhmucUxU1w==
+ dependencies:
+ "@babel/runtime" "^7.23.2"
+ "@mui/utils" "^5.14.16"
+ clsx "^2.0.0"
+ prop-types "^15.8.1"
+ reselect "^4.1.8"
+
+"@next/env@14.2.22":
+ version "14.2.22"
+ resolved "https://registry.npmjs.org/@next/env/-/env-14.2.22.tgz"
+ integrity sha512-EQ6y1QeNQglNmNIXvwP/Bb+lf7n9WtgcWvtoFsHquVLCJUuxRs+6SfZ5EK0/EqkkLex4RrDySvKgKNN7PXip7Q==
+
+"@next/eslint-plugin-next@13.0.4":
+ version "13.0.4"
+ resolved "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.0.4.tgz"
+ integrity sha512-jZ4urKT+aO9QHm3ttihrIQscQISDSKK8isAom750+EySn9o3LCSkTdPGBtvBqY7Yku+NqhfQempR5J58DqTaVg==
+ dependencies:
+ glob "7.1.7"
+
+"@next/swc-darwin-arm64@14.2.22":
+ version "14.2.22"
+ resolved "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.22.tgz"
+ integrity sha512-HUaLiehovgnqY4TMBZJ3pDaOsTE1spIXeR10pWgdQVPYqDGQmHJBj3h3V6yC0uuo/RoY2GC0YBFRkOX3dI9WVQ==
+
+"@nodelib/fs.scandir@2.1.5":
+ version "2.1.5"
+ resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz"
+ integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
+ dependencies:
+ "@nodelib/fs.stat" "2.0.5"
+ run-parallel "^1.1.9"
+
+"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5":
+ version "2.0.5"
+ resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz"
+ integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
+
+"@nodelib/fs.walk@^1.2.3":
+ version "1.2.8"
+ resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz"
+ integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
+ dependencies:
+ "@nodelib/fs.scandir" "2.1.5"
+ fastq "^1.6.0"
+
+"@pkgjs/parseargs@^0.11.0":
+ version "0.11.0"
+ resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz"
+ integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
+
+"@pkgr/utils@^2.3.1":
+ version "2.3.1"
+ resolved "https://registry.npmjs.org/@pkgr/utils/-/utils-2.3.1.tgz"
+ integrity sha512-wfzX8kc1PMyUILA+1Z/EqoE4UCXGy0iRGMhPwdfae1+f0OXlLqCk+By+aMzgJBzR9AzS4CDizioG6Ss1gvAFJw==
+ dependencies:
+ cross-spawn "^7.0.3"
+ is-glob "^4.0.3"
+ open "^8.4.0"
+ picocolors "^1.0.0"
+ tiny-glob "^0.2.9"
+ tslib "^2.4.0"
+
+"@popperjs/core@^2.11.6", "@popperjs/core@^2.11.8":
+ version "2.11.8"
+ resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz"
+ integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==
+
+"@reduxjs/toolkit@^2.1.0":
+ version "2.5.0"
+ resolved "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.5.0.tgz"
+ integrity sha512-awNe2oTodsZ6LmRqmkFhtb/KH03hUhxOamEQy411m3Njj3BbFvoBovxo4Q1cBWnV1ErprVj9MlF0UPXkng0eyg==
+ dependencies:
+ immer "^10.0.3"
+ redux "^5.0.1"
+ redux-thunk "^3.1.0"
+ reselect "^5.1.0"
+
+"@restart/hooks@^0.4.7":
+ version "0.4.16"
+ resolved "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.16.tgz"
+ integrity sha512-f7aCv7c+nU/3mF7NWLtVVr0Ra80RqsO89hO72r+Y/nvQr5+q0UFGkocElTH6MJApvReVh6JHUFYn2cw1WdHF3w==
+ dependencies:
+ dequal "^2.0.3"
+
+"@rushstack/eslint-patch@^1.1.3":
+ version "1.1.4"
+ resolved "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.4.tgz"
+ integrity sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA==
+
+"@seznam/compose-react-refs@^1.0.6":
+ version "1.0.6"
+ resolved "https://registry.npmjs.org/@seznam/compose-react-refs/-/compose-react-refs-1.0.6.tgz"
+ integrity sha512-izzOXQfeQLonzrIQb8u6LQ8dk+ymz3WXTIXjvOlTXHq6sbzROg3NWU+9TTAOpEoK9Bth24/6F/XrfHJ5yR5n6Q==
+
+"@swc/counter@^0.1.3":
+ version "0.1.3"
+ resolved "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz"
+ integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==
+
+"@swc/helpers@0.5.5":
+ version "0.5.5"
+ resolved "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz"
+ integrity sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==
+ dependencies:
+ "@swc/counter" "^0.1.3"
+ tslib "^2.4.0"
+
+"@tailwindcss/forms@^0.5.7":
+ version "0.5.9"
+ resolved "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.9.tgz"
+ integrity sha512-tM4XVr2+UVTxXJzey9Twx48c1gcxFStqn1pQz0tRsX8o3DvxhN5oY5pvyAbUx7VTaZxpej4Zzvc6h+1RJBzpIg==
+ dependencies:
+ mini-svg-data-uri "^1.2.3"
+
+"@tailwindcss/line-clamp@^0.4.4":
+ version "0.4.4"
+ resolved "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.4.4.tgz"
+ integrity sha512-5U6SY5z8N42VtrCrKlsTAA35gy2VSyYtHWCsg1H87NU1SXnEfekTVlrga9fzUDrrHcGi2Lb5KenUWb4lRQT5/g==
+
+"@tailwindcss/typography@^0.5.13":
+ version "0.5.15"
+ resolved "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.15.tgz"
+ integrity sha512-AqhlCXl+8grUz8uqExv5OTtgpjuVIwFTSXTrh8y9/pw6q2ek7fJ+Y8ZEVw7EB2DCcuCOtEjf9w3+J3rzts01uA==
+ dependencies:
+ lodash.castarray "^4.4.0"
+ lodash.isplainobject "^4.0.6"
+ lodash.merge "^4.6.2"
+ postcss-selector-parser "6.0.10"
+
+"@tinymce/tinymce-react@^4.3.2":
+ version "4.3.2"
+ resolved "https://registry.npmjs.org/@tinymce/tinymce-react/-/tinymce-react-4.3.2.tgz"
+ integrity sha512-wJHZhPf2Mk3yTtdVC/uIGh+kvDgKuTw/qV13uzdChTNo68JI1l7jYMrSQOpyimDyn5LHAw0E1zFByrm1WHAVeA==
+ dependencies:
+ prop-types "^15.6.2"
+ tinymce "^6.0.0 || ^5.5.1"
+
+"@types/date-arithmetic@*":
+ version "4.1.4"
+ resolved "https://registry.npmjs.org/@types/date-arithmetic/-/date-arithmetic-4.1.4.tgz"
+ integrity sha512-p9eZ2X9B80iKiTW4ukVj8B4K6q9/+xFtQ5MGYA5HWToY9nL4EkhV9+6ftT2VHpVMEZb5Tv00Iel516bVdO+yRw==
+
+"@types/hoist-non-react-statics@^3.3.0", "@types/hoist-non-react-statics@^3.3.1":
+ version "3.3.1"
+ resolved "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz"
+ integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
+ dependencies:
+ "@types/react" "*"
+ hoist-non-react-statics "^3.3.0"
+
+"@types/json-schema@^7.0.9":
+ version "7.0.11"
+ resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz"
+ integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==
+
+"@types/json5@^0.0.29":
+ version "0.0.29"
+ resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz"
+ integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
+
+"@types/node@18.7.16":
+ version "18.7.16"
+ resolved "https://registry.npmjs.org/@types/node/-/node-18.7.16.tgz"
+ integrity sha512-EQHhixfu+mkqHMZl1R2Ovuvn47PUw18azMJOTwSZr9/fhzHNGXAJ0ma0dayRVchprpCj0Kc1K1xKoWaATWF1qg==
+
+"@types/numeral@^2.0.2":
+ version "2.0.2"
+ resolved "https://registry.npmjs.org/@types/numeral/-/numeral-2.0.2.tgz"
+ integrity sha512-A8F30k2gYJ/6e07spSCPpkuZu79LCnkPTvqmIWQzNGcrzwFKpVOydG41lNt5wZXjSI149qjyzC2L1+F2PD/NUA==
+
+"@types/parse-json@^4.0.0":
+ version "4.0.2"
+ resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz"
+ integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==
+
+"@types/prop-types@*", "@types/prop-types@^15.7.12":
+ version "15.7.14"
+ resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz"
+ integrity sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==
+
+"@types/react-big-calendar@^1.8.8":
+ version "1.16.0"
+ resolved "https://registry.npmjs.org/@types/react-big-calendar/-/react-big-calendar-1.16.0.tgz"
+ integrity sha512-1w2GXAJWlGmaPZOd9J9cyWA/XBNOGRZ4MmRNypEQhwEMIIL9cfd1UdcvzSrQsnBm0qYF/scqmsISNbUzPBE1vg==
+ dependencies:
+ "@types/date-arithmetic" "*"
+ "@types/prop-types" "*"
+ "@types/react" "*"
+
+"@types/react-redux@^7.1.24":
+ version "7.1.24"
+ resolved "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.24.tgz"
+ integrity sha512-7FkurKcS1k0FHZEtdbbgN8Oc6b+stGSfZYjQGicofJ0j4U0qIn/jaSvnP2pLwZKiai3/17xqqxkkrxTgN8UNbQ==
+ dependencies:
+ "@types/hoist-non-react-statics" "^3.3.0"
+ "@types/react" "*"
+ hoist-non-react-statics "^3.3.0"
+ redux "^4.0.0"
+
+"@types/react-transition-group@^4.4.0", "@types/react-transition-group@^4.4.10":
+ version "4.4.12"
+ resolved "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz"
+ integrity sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==
+
+"@types/react@*", "@types/react@>=16.9.11":
+ version "18.0.19"
+ resolved "https://registry.npmjs.org/@types/react/-/react-18.0.19.tgz"
+ integrity sha512-BDc3Q+4Q3zsn7k9xZrKfjWyJsSlEDMs38gD1qp2eDazLCdcPqAT+vq1ND+Z8AGel/UiwzNUk8ptpywgNQcJ1MQ==
+ dependencies:
+ "@types/prop-types" "*"
+ "@types/scheduler" "*"
+ csstype "^3.0.2"
+
+"@types/scheduler@*":
+ version "0.16.2"
+ resolved "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz"
+ integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==
+
+"@types/use-sync-external-store@^0.0.3":
+ version "0.0.3"
+ resolved "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz"
+ integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==
+
+"@types/warning@^3.0.0":
+ version "3.0.3"
+ resolved "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz"
+ integrity sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q==
+
+"@typescript-eslint/eslint-plugin@^5.37.0":
+ version "5.37.0"
+ resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.37.0.tgz"
+ integrity sha512-Fde6W0IafXktz1UlnhGkrrmnnGpAo1kyX7dnyHHVrmwJOn72Oqm3eYtddrpOwwel2W8PAK9F3pIL5S+lfoM0og==
+ dependencies:
+ "@typescript-eslint/scope-manager" "5.37.0"
+ "@typescript-eslint/type-utils" "5.37.0"
+ "@typescript-eslint/utils" "5.37.0"
+ debug "^4.3.4"
+ functional-red-black-tree "^1.0.1"
+ ignore "^5.2.0"
+ regexpp "^3.2.0"
+ semver "^7.3.7"
+ tsutils "^3.21.0"
+
+"@typescript-eslint/parser@^5.37.0", "@typescript-eslint/parser@^5.42.0":
+ version "5.43.0"
+ resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.43.0.tgz"
+ integrity sha512-2iHUK2Lh7PwNUlhFxxLI2haSDNyXvebBO9izhjhMoDC+S3XI9qt2DGFUsiJ89m2k7gGYch2aEpYqV5F/+nwZug==
+ dependencies:
+ "@typescript-eslint/scope-manager" "5.43.0"
+ "@typescript-eslint/types" "5.43.0"
+ "@typescript-eslint/typescript-estree" "5.43.0"
+ debug "^4.3.4"
+
+"@typescript-eslint/scope-manager@5.37.0":
+ version "5.37.0"
+ resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.37.0.tgz"
+ integrity sha512-F67MqrmSXGd/eZnujjtkPgBQzgespu/iCZ+54Ok9X5tALb9L2v3G+QBSoWkXG0p3lcTJsL+iXz5eLUEdSiJU9Q==
+ dependencies:
+ "@typescript-eslint/types" "5.37.0"
+ "@typescript-eslint/visitor-keys" "5.37.0"
+
+"@typescript-eslint/scope-manager@5.43.0":
+ version "5.43.0"
+ resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.43.0.tgz"
+ integrity sha512-XNWnGaqAtTJsUiZaoiGIrdJYHsUOd3BZ3Qj5zKp9w6km6HsrjPk/TGZv0qMTWyWj0+1QOqpHQ2gZOLXaGA9Ekw==
+ dependencies:
+ "@typescript-eslint/types" "5.43.0"
+ "@typescript-eslint/visitor-keys" "5.43.0"
+
+"@typescript-eslint/type-utils@5.37.0":
+ version "5.37.0"
+ resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.37.0.tgz"
+ integrity sha512-BSx/O0Z0SXOF5tY0bNTBcDEKz2Ec20GVYvq/H/XNKiUorUFilH7NPbFUuiiyzWaSdN3PA8JV0OvYx0gH/5aFAQ==
+ dependencies:
+ "@typescript-eslint/typescript-estree" "5.37.0"
+ "@typescript-eslint/utils" "5.37.0"
+ debug "^4.3.4"
+ tsutils "^3.21.0"
+
+"@typescript-eslint/types@5.37.0":
+ version "5.37.0"
+ resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.37.0.tgz"
+ integrity sha512-3frIJiTa5+tCb2iqR/bf7XwU20lnU05r/sgPJnRpwvfZaqCJBrl8Q/mw9vr3NrNdB/XtVyMA0eppRMMBqdJ1bA==
+
+"@typescript-eslint/types@5.43.0":
+ version "5.43.0"
+ resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.43.0.tgz"
+ integrity sha512-jpsbcD0x6AUvV7tyOlyvon0aUsQpF8W+7TpJntfCUWU1qaIKu2K34pMwQKSzQH8ORgUrGYY6pVIh1Pi8TNeteg==
+
+"@typescript-eslint/typescript-estree@5.37.0":
+ version "5.37.0"
+ resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.37.0.tgz"
+ integrity sha512-JkFoFIt/cx59iqEDSgIGnQpCTRv96MQnXCYvJi7QhBC24uyuzbD8wVbajMB1b9x4I0octYFJ3OwjAwNqk1AjDA==
+ dependencies:
+ "@typescript-eslint/types" "5.37.0"
+ "@typescript-eslint/visitor-keys" "5.37.0"
+ debug "^4.3.4"
+ globby "^11.1.0"
+ is-glob "^4.0.3"
+ semver "^7.3.7"
+ tsutils "^3.21.0"
+
+"@typescript-eslint/typescript-estree@5.43.0":
+ version "5.43.0"
+ resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.43.0.tgz"
+ integrity sha512-BZ1WVe+QQ+igWal2tDbNg1j2HWUkAa+CVqdU79L4HP9izQY6CNhXfkNwd1SS4+sSZAP/EthI1uiCSY/+H0pROg==
+ dependencies:
+ "@typescript-eslint/types" "5.43.0"
+ "@typescript-eslint/visitor-keys" "5.43.0"
+ debug "^4.3.4"
+ globby "^11.1.0"
+ is-glob "^4.0.3"
+ semver "^7.3.7"
+ tsutils "^3.21.0"
+
+"@typescript-eslint/utils@5.37.0":
+ version "5.37.0"
+ resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.37.0.tgz"
+ integrity sha512-jUEJoQrWbZhmikbcWSMDuUSxEE7ID2W/QCV/uz10WtQqfOuKZUqFGjqLJ+qhDd17rjgp+QJPqTdPIBWwoob2NQ==
+ dependencies:
+ "@types/json-schema" "^7.0.9"
+ "@typescript-eslint/scope-manager" "5.37.0"
+ "@typescript-eslint/types" "5.37.0"
+ "@typescript-eslint/typescript-estree" "5.37.0"
+ eslint-scope "^5.1.1"
+ eslint-utils "^3.0.0"
+
+"@typescript-eslint/visitor-keys@5.37.0":
+ version "5.37.0"
+ resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.37.0.tgz"
+ integrity sha512-Hp7rT4cENBPIzMwrlehLW/28EVCOcE9U1Z1BQTc8EA8v5qpr7GRGuG+U58V5tTY48zvUOA3KHvw3rA8tY9fbdA==
+ dependencies:
+ "@typescript-eslint/types" "5.37.0"
+ eslint-visitor-keys "^3.3.0"
+
+"@typescript-eslint/visitor-keys@5.43.0":
+ version "5.43.0"
+ resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.43.0.tgz"
+ integrity sha512-icl1jNH/d18OVHLfcwdL3bWUKsBeIiKYTGxMJCoGe7xFht+E4QgzOqoWYrU8XSLJWhVw8nTacbm03v23J/hFTg==
+ dependencies:
+ "@typescript-eslint/types" "5.43.0"
+ eslint-visitor-keys "^3.3.0"
+
+"@vtaits/use-lazy-ref@^0.1.3":
+ version "0.1.3"
+ resolved "https://registry.npmjs.org/@vtaits/use-lazy-ref/-/use-lazy-ref-0.1.3.tgz"
+ integrity sha512-ZTLuFBHSivPcgWrwkXe5ExVt6R3/ybD+N0yFPy4ClzCztk/9bUD/1udKQ/jd7eCal+lapSrRWXbffqI9jkpDlg==
+
+"@yr/monotone-cubic-spline@^1.0.3":
+ version "1.0.3"
+ resolved "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz"
+ integrity sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA==
+
+acorn-jsx@^5.3.2:
+ version "5.3.2"
+ resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
+ integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
+
+acorn@^8.8.0:
+ version "8.8.0"
+ resolved "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz"
+ integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==
+
+ajv@^6.10.0, ajv@^6.12.4:
+ version "6.12.6"
+ resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz"
+ integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
+ dependencies:
+ fast-deep-equal "^3.1.1"
+ fast-json-stable-stringify "^2.0.0"
+ json-schema-traverse "^0.4.1"
+ uri-js "^4.2.2"
+
+ansi-regex@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz"
+ integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
+
+ansi-regex@^6.0.1:
+ version "6.1.0"
+ resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz"
+ integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==
+
+ansi-styles@^4.0.0, ansi-styles@^4.1.0:
+ version "4.3.0"
+ resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz"
+ integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
+ dependencies:
+ color-convert "^2.0.1"
+
+ansi-styles@^6.1.0:
+ version "6.2.1"
+ resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz"
+ integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
+
+any-promise@^1.0.0:
+ version "1.3.0"
+ resolved "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz"
+ integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==
+
+anymatch@~3.1.2:
+ version "3.1.3"
+ resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz"
+ integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
+ dependencies:
+ normalize-path "^3.0.0"
+ picomatch "^2.0.4"
+
+apexcharts@^3.45.2:
+ version "3.54.1"
+ resolved "https://registry.npmjs.org/apexcharts/-/apexcharts-3.54.1.tgz"
+ integrity sha512-E4et0h/J1U3r3EwS/WlqJCQIbepKbp6wGUmaAwJOMjHUP4Ci0gxanLa7FR3okx6p9coi4st6J853/Cb1NP0vpA==
+ dependencies:
+ "@yr/monotone-cubic-spline" "^1.0.3"
+ svg.draggable.js "^2.2.2"
+ svg.easing.js "^2.0.0"
+ svg.filter.js "^2.0.2"
+ svg.pathmorphing.js "^0.1.3"
+ svg.resize.js "^1.4.3"
+ svg.select.js "^3.0.1"
+
+arg@^5.0.2:
+ version "5.0.2"
+ resolved "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz"
+ integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==
+
+argparse@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz"
+ integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
+
+aria-query@^4.2.2:
+ version "4.2.2"
+ resolved "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz"
+ integrity sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==
+ dependencies:
+ "@babel/runtime" "^7.10.2"
+ "@babel/runtime-corejs3" "^7.10.2"
+
+array-includes@^3.1.4, array-includes@^3.1.5:
+ version "3.1.5"
+ resolved "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz"
+ integrity sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.19.5"
+ get-intrinsic "^1.1.1"
+ is-string "^1.0.7"
+
+array-union@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz"
+ integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
+
+array.prototype.flat@^1.2.5:
+ version "1.3.1"
+ resolved "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz"
+ integrity sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+ es-shim-unscopables "^1.0.0"
+
+array.prototype.flatmap@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz"
+ integrity sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+ es-abstract "^1.19.2"
+ es-shim-unscopables "^1.0.0"
+
+ast-types-flow@^0.0.7:
+ version "0.0.7"
+ resolved "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz"
+ integrity sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==
+
+asynckit@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz"
+ integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
+
+autoprefixer@^10.4.0:
+ version "10.4.9"
+ resolved "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.9.tgz"
+ integrity sha512-Uu67eduPEmOeA0vyJby5ghu1AAELCCNSsLAjK+lz6kYzNM5sqnBO36MqfsjhPjQF/BaJM5U/UuFYyl7PavY/wQ==
+ dependencies:
+ browserslist "^4.21.3"
+ caniuse-lite "^1.0.30001394"
+ fraction.js "^4.2.0"
+ normalize-range "^0.1.2"
+ picocolors "^1.0.0"
+ postcss-value-parser "^4.2.0"
+
+axe-core@^4.4.3:
+ version "4.4.3"
+ resolved "https://registry.npmjs.org/axe-core/-/axe-core-4.4.3.tgz"
+ integrity sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w==
+
+axios@^1.6.7:
+ version "1.7.9"
+ resolved "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz"
+ integrity sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==
+ dependencies:
+ follow-redirects "^1.15.6"
+ form-data "^4.0.0"
+ proxy-from-env "^1.1.0"
+
+axobject-query@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz"
+ integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==
+
+babel-plugin-macros@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz"
+ integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==
+ dependencies:
+ "@babel/runtime" "^7.12.5"
+ cosmiconfig "^7.0.0"
+ resolve "^1.19.0"
+
+balanced-match@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
+ integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
+
+binary-extensions@^2.0.0:
+ version "2.3.0"
+ resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz"
+ integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==
+
+brace-expansion@^1.1.7:
+ version "1.1.11"
+ resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz"
+ integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
+brace-expansion@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz"
+ integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
+ dependencies:
+ balanced-match "^1.0.0"
+
+braces@^3.0.3, braces@~3.0.2:
+ version "3.0.3"
+ resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz"
+ integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
+ dependencies:
+ fill-range "^7.1.1"
+
+browserslist@^4.21.3:
+ version "4.21.3"
+ resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz"
+ integrity sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==
+ dependencies:
+ caniuse-lite "^1.0.30001370"
+ electron-to-chromium "^1.4.202"
+ node-releases "^2.0.6"
+ update-browserslist-db "^1.0.5"
+
+buffer-equal-constant-time@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz"
+ integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==
+
+busboy@1.6.0:
+ version "1.6.0"
+ resolved "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz"
+ integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==
+ dependencies:
+ streamsearch "^1.1.0"
+
+call-bind@^1.0.0, call-bind@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz"
+ integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
+ dependencies:
+ function-bind "^1.1.1"
+ get-intrinsic "^1.0.2"
+
+callsites@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz"
+ integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
+
+camelcase-css@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz"
+ integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==
+
+caniuse-lite@^1.0.30001370, caniuse-lite@^1.0.30001394, caniuse-lite@^1.0.30001579:
+ version "1.0.30001690"
+ resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz"
+ integrity sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==
+
+chalk@^4.0.0:
+ version "4.1.2"
+ resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
+ integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
+ dependencies:
+ ansi-styles "^4.1.0"
+ supports-color "^7.1.0"
+
+chart.js@^4.4.1:
+ version "4.4.7"
+ resolved "https://registry.npmjs.org/chart.js/-/chart.js-4.4.7.tgz"
+ integrity sha512-pwkcKfdzTMAU/+jNosKhNL2bHtJc/sSmYgVbuGTEDhzkrhmyihmP7vUc/5ZK9WopidMDHNe3Wm7jOd/WhuHWuw==
+ dependencies:
+ "@kurkle/color" "^0.3.0"
+
+chokidar@^3.6.0:
+ version "3.6.0"
+ resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz"
+ integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
+ dependencies:
+ anymatch "~3.1.2"
+ braces "~3.0.2"
+ glob-parent "~5.1.2"
+ is-binary-path "~2.1.0"
+ is-glob "~4.0.1"
+ normalize-path "~3.0.0"
+ readdirp "~3.6.0"
+ optionalDependencies:
+ fsevents "~2.3.2"
+
+chroma-js@^2.4.2:
+ version "2.6.0"
+ resolved "https://registry.npmjs.org/chroma-js/-/chroma-js-2.6.0.tgz"
+ integrity sha512-BLHvCB9s8Z1EV4ethr6xnkl/P2YRFOGqfgvuMG/MyCbZPrTA+NeiByY6XvgF0zP4/2deU2CXnWyMa3zu1LqQ3A==
+
+classnames@^2.2.6:
+ version "2.5.1"
+ resolved "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz"
+ integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==
+
+client-only@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz"
+ integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==
+
+clsx@^1.1.1:
+ version "1.2.1"
+ resolved "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz"
+ integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==
+
+clsx@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz"
+ integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==
+
+clsx@^2.0.0, clsx@^2.1.0, clsx@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz"
+ integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
+
+color-convert@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz"
+ integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
+ dependencies:
+ color-name "~1.1.4"
+
+color-name@~1.1.4:
+ version "1.1.4"
+ resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
+ integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+
+combined-stream@^1.0.8:
+ version "1.0.8"
+ resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz"
+ integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
+ dependencies:
+ delayed-stream "~1.0.0"
+
+commander@^4.0.0:
+ version "4.1.1"
+ resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz"
+ integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
+
+concat-map@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
+ integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
+
+convert-source-map@^1.5.0:
+ version "1.9.0"
+ resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz"
+ integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==
+
+core-js-pure@^3.20.2:
+ version "3.25.1"
+ resolved "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.25.1.tgz"
+ integrity sha512-7Fr74bliUDdeJCBMxkkIuQ4xfxn/SwrVg+HkJUAoNEXVqYLv55l6Af0dJ5Lq2YBUW9yKqSkLXaS5SYPK6MGa/A==
+
+cosmiconfig@^7.0.0:
+ version "7.1.0"
+ resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz"
+ integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==
+ dependencies:
+ "@types/parse-json" "^4.0.0"
+ import-fresh "^3.2.1"
+ parse-json "^5.0.0"
+ path-type "^4.0.0"
+ yaml "^1.10.0"
+
+cross-env@^7.0.3:
+ version "7.0.3"
+ resolved "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz"
+ integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==
+ dependencies:
+ cross-spawn "^7.0.1"
+
+cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
+ version "7.0.3"
+ resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz"
+ integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
+ dependencies:
+ path-key "^3.1.0"
+ shebang-command "^2.0.0"
+ which "^2.0.1"
+
+cssesc@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz"
+ integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
+
+csstype@^3.0.2, csstype@^3.1.3:
+ version "3.1.3"
+ resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz"
+ integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
+
+damerau-levenshtein@^1.0.8:
+ version "1.0.8"
+ resolved "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz"
+ integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==
+
+date-arithmetic@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.npmjs.org/date-arithmetic/-/date-arithmetic-4.1.0.tgz"
+ integrity sha512-QWxYLR5P/6GStZcdem+V1xoto6DMadYWpMXU82ES3/RfR3Wdwr3D0+be7mgOJ+Ov0G9D5Dmb9T17sNLQYj9XOg==
+
+date-fns@^2.30.0:
+ version "2.30.0"
+ resolved "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz"
+ integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==
+ dependencies:
+ "@babel/runtime" "^7.21.0"
+
+dayjs@^1.11.10, dayjs@^1.11.7:
+ version "1.11.13"
+ resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz"
+ integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==
+
+debug@^2.6.9:
+ version "2.6.9"
+ resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz"
+ integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
+ dependencies:
+ ms "2.0.0"
+
+debug@^3.2.7:
+ version "3.2.7"
+ resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz"
+ integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
+ dependencies:
+ ms "^2.1.1"
+
+debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4:
+ version "4.3.4"
+ resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz"
+ integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
+ dependencies:
+ ms "2.1.2"
+
+decode-uri-component@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.4.1.tgz"
+ integrity sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ==
+
+deep-is@^0.1.3:
+ version "0.1.4"
+ resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz"
+ integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
+
+deepmerge@^2.1.1:
+ version "2.2.1"
+ resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz"
+ integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==
+
+define-lazy-prop@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz"
+ integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==
+
+define-properties@^1.1.3, define-properties@^1.1.4:
+ version "1.1.4"
+ resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz"
+ integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==
+ dependencies:
+ has-property-descriptors "^1.0.0"
+ object-keys "^1.1.1"
+
+delayed-stream@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz"
+ integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
+
+dequal@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz"
+ integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==
+
+didyoumean@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz"
+ integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==
+
+dir-glob@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz"
+ integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==
+ dependencies:
+ path-type "^4.0.0"
+
+dlv@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz"
+ integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==
+
+doctrine@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz"
+ integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==
+ dependencies:
+ esutils "^2.0.2"
+
+doctrine@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz"
+ integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==
+ dependencies:
+ esutils "^2.0.2"
+
+dom-helpers@^5.0.1, dom-helpers@^5.2.0, dom-helpers@^5.2.1:
+ version "5.2.1"
+ resolved "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz"
+ integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==
+ dependencies:
+ "@babel/runtime" "^7.8.7"
+ csstype "^3.0.2"
+
+eastasianwidth@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz"
+ integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
+
+ecdsa-sig-formatter@1.0.11:
+ version "1.0.11"
+ resolved "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz"
+ integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==
+ dependencies:
+ safe-buffer "^5.0.1"
+
+electron-to-chromium@^1.4.202:
+ version "1.4.248"
+ resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.248.tgz"
+ integrity sha512-qShjzEYpa57NnhbW2K+g+Fl+eNoDvQ7I+2MRwWnU6Z6F0HhXekzsECCLv+y2OJUsRodjqoSfwHkIX42VUFtUzg==
+
+emoji-regex@^8.0.0:
+ version "8.0.0"
+ resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz"
+ integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
+
+emoji-regex@^9.2.2:
+ version "9.2.2"
+ resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz"
+ integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
+
+enhanced-resolve@^5.10.0:
+ version "5.10.0"
+ resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz"
+ integrity sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==
+ dependencies:
+ graceful-fs "^4.2.4"
+ tapable "^2.2.0"
+
+error-ex@^1.3.1:
+ version "1.3.2"
+ resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz"
+ integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
+ dependencies:
+ is-arrayish "^0.2.1"
+
+es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5, es-abstract@^1.20.4:
+ version "1.20.4"
+ resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.4.tgz"
+ integrity sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA==
+ dependencies:
+ call-bind "^1.0.2"
+ es-to-primitive "^1.2.1"
+ function-bind "^1.1.1"
+ function.prototype.name "^1.1.5"
+ get-intrinsic "^1.1.3"
+ get-symbol-description "^1.0.0"
+ has "^1.0.3"
+ has-property-descriptors "^1.0.0"
+ has-symbols "^1.0.3"
+ internal-slot "^1.0.3"
+ is-callable "^1.2.7"
+ is-negative-zero "^2.0.2"
+ is-regex "^1.1.4"
+ is-shared-array-buffer "^1.0.2"
+ is-string "^1.0.7"
+ is-weakref "^1.0.2"
+ object-inspect "^1.12.2"
+ object-keys "^1.1.1"
+ object.assign "^4.1.4"
+ regexp.prototype.flags "^1.4.3"
+ safe-regex-test "^1.0.0"
+ string.prototype.trimend "^1.0.5"
+ string.prototype.trimstart "^1.0.5"
+ unbox-primitive "^1.0.2"
+
+es-shim-unscopables@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz"
+ integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==
+ dependencies:
+ has "^1.0.3"
+
+es-to-primitive@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz"
+ integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==
+ dependencies:
+ is-callable "^1.1.4"
+ is-date-object "^1.0.1"
+ is-symbol "^1.0.2"
+
+escalade@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz"
+ integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
+
+escape-string-regexp@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz"
+ integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
+
+eslint-config-next@^13.0.4:
+ version "13.0.4"
+ resolved "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.0.4.tgz"
+ integrity sha512-moEC7BW2TK7JKq3QfnaauqRjWzVcEf71gp5DbClpFPHM6QXE0u0uVvSTiHlmOgtCe1vyWAO+AhF87ZITd8mIDw==
+ dependencies:
+ "@next/eslint-plugin-next" "13.0.4"
+ "@rushstack/eslint-patch" "^1.1.3"
+ "@typescript-eslint/parser" "^5.42.0"
+ eslint-import-resolver-node "^0.3.6"
+ eslint-import-resolver-typescript "^3.5.2"
+ eslint-plugin-import "^2.26.0"
+ eslint-plugin-jsx-a11y "^6.5.1"
+ eslint-plugin-react "^7.31.7"
+ eslint-plugin-react-hooks "^4.5.0"
+
+eslint-config-prettier@^8.5.0:
+ version "8.5.0"
+ resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz"
+ integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==
+
+eslint-import-resolver-node@^0.3.6:
+ version "0.3.6"
+ resolved "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz"
+ integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==
+ dependencies:
+ debug "^3.2.7"
+ resolve "^1.20.0"
+
+eslint-import-resolver-typescript@^3.5.2:
+ version "3.5.2"
+ resolved "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.2.tgz"
+ integrity sha512-zX4ebnnyXiykjhcBvKIf5TNvt8K7yX6bllTRZ14MiurKPjDpCAZujlszTdB8pcNXhZcOf+god4s9SjQa5GnytQ==
+ dependencies:
+ debug "^4.3.4"
+ enhanced-resolve "^5.10.0"
+ get-tsconfig "^4.2.0"
+ globby "^13.1.2"
+ is-core-module "^2.10.0"
+ is-glob "^4.0.3"
+ synckit "^0.8.4"
+
+eslint-module-utils@^2.7.3:
+ version "2.7.4"
+ resolved "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz"
+ integrity sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==
+ dependencies:
+ debug "^3.2.7"
+
+eslint-plugin-import@^2.26.0:
+ version "2.26.0"
+ resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz"
+ integrity sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==
+ dependencies:
+ array-includes "^3.1.4"
+ array.prototype.flat "^1.2.5"
+ debug "^2.6.9"
+ doctrine "^2.1.0"
+ eslint-import-resolver-node "^0.3.6"
+ eslint-module-utils "^2.7.3"
+ has "^1.0.3"
+ is-core-module "^2.8.1"
+ is-glob "^4.0.3"
+ minimatch "^3.1.2"
+ object.values "^1.1.5"
+ resolve "^1.22.0"
+ tsconfig-paths "^3.14.1"
+
+eslint-plugin-jsx-a11y@^6.5.1:
+ version "6.6.1"
+ resolved "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.6.1.tgz"
+ integrity sha512-sXgFVNHiWffBq23uiS/JaP6eVR622DqwB4yTzKvGZGcPq6/yZ3WmOZfuBks/vHWo9GaFOqC2ZK4i6+C35knx7Q==
+ dependencies:
+ "@babel/runtime" "^7.18.9"
+ aria-query "^4.2.2"
+ array-includes "^3.1.5"
+ ast-types-flow "^0.0.7"
+ axe-core "^4.4.3"
+ axobject-query "^2.2.0"
+ damerau-levenshtein "^1.0.8"
+ emoji-regex "^9.2.2"
+ has "^1.0.3"
+ jsx-ast-utils "^3.3.2"
+ language-tags "^1.0.5"
+ minimatch "^3.1.2"
+ semver "^6.3.0"
+
+eslint-plugin-react-hooks@^4.5.0:
+ version "4.6.0"
+ resolved "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz"
+ integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==
+
+eslint-plugin-react@^7.31.7:
+ version "7.31.8"
+ resolved "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.8.tgz"
+ integrity sha512-5lBTZmgQmARLLSYiwI71tiGVTLUuqXantZM6vlSY39OaDSV0M7+32K5DnLkmFrwTe+Ksz0ffuLUC91RUviVZfw==
+ dependencies:
+ array-includes "^3.1.5"
+ array.prototype.flatmap "^1.3.0"
+ doctrine "^2.1.0"
+ estraverse "^5.3.0"
+ jsx-ast-utils "^2.4.1 || ^3.0.0"
+ minimatch "^3.1.2"
+ object.entries "^1.1.5"
+ object.fromentries "^2.0.5"
+ object.hasown "^1.1.1"
+ object.values "^1.1.5"
+ prop-types "^15.8.1"
+ resolve "^2.0.0-next.3"
+ semver "^6.3.0"
+ string.prototype.matchall "^4.0.7"
+
+eslint-scope@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz"
+ integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
+ dependencies:
+ esrecurse "^4.3.0"
+ estraverse "^4.1.1"
+
+eslint-scope@^7.1.1:
+ version "7.1.1"
+ resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz"
+ integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==
+ dependencies:
+ esrecurse "^4.3.0"
+ estraverse "^5.2.0"
+
+eslint-utils@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz"
+ integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==
+ dependencies:
+ eslint-visitor-keys "^2.0.0"
+
+eslint-visitor-keys@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz"
+ integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==
+
+eslint-visitor-keys@^3.3.0:
+ version "3.3.0"
+ resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz"
+ integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
+
+eslint@^8.23.1:
+ version "8.23.1"
+ resolved "https://registry.npmjs.org/eslint/-/eslint-8.23.1.tgz"
+ integrity sha512-w7C1IXCc6fNqjpuYd0yPlcTKKmHlHHktRkzmBPZ+7cvNBQuiNjx0xaMTjAJGCafJhQkrFJooREv0CtrVzmHwqg==
+ dependencies:
+ "@eslint/eslintrc" "^1.3.2"
+ "@humanwhocodes/config-array" "^0.10.4"
+ "@humanwhocodes/gitignore-to-minimatch" "^1.0.2"
+ "@humanwhocodes/module-importer" "^1.0.1"
+ ajv "^6.10.0"
+ chalk "^4.0.0"
+ cross-spawn "^7.0.2"
+ debug "^4.3.2"
+ doctrine "^3.0.0"
+ escape-string-regexp "^4.0.0"
+ eslint-scope "^7.1.1"
+ eslint-utils "^3.0.0"
+ eslint-visitor-keys "^3.3.0"
+ espree "^9.4.0"
+ esquery "^1.4.0"
+ esutils "^2.0.2"
+ fast-deep-equal "^3.1.3"
+ file-entry-cache "^6.0.1"
+ find-up "^5.0.0"
+ glob-parent "^6.0.1"
+ globals "^13.15.0"
+ globby "^11.1.0"
+ grapheme-splitter "^1.0.4"
+ ignore "^5.2.0"
+ import-fresh "^3.0.0"
+ imurmurhash "^0.1.4"
+ is-glob "^4.0.0"
+ js-sdsl "^4.1.4"
+ js-yaml "^4.1.0"
+ json-stable-stringify-without-jsonify "^1.0.1"
+ levn "^0.4.1"
+ lodash.merge "^4.6.2"
+ minimatch "^3.1.2"
+ natural-compare "^1.4.0"
+ optionator "^0.9.1"
+ regexpp "^3.2.0"
+ strip-ansi "^6.0.1"
+ strip-json-comments "^3.1.0"
+ text-table "^0.2.0"
+
+espree@^9.4.0:
+ version "9.4.0"
+ resolved "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz"
+ integrity sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==
+ dependencies:
+ acorn "^8.8.0"
+ acorn-jsx "^5.3.2"
+ eslint-visitor-keys "^3.3.0"
+
+esquery@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz"
+ integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==
+ dependencies:
+ estraverse "^5.1.0"
+
+esrecurse@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz"
+ integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
+ dependencies:
+ estraverse "^5.2.0"
+
+estraverse@^4.1.1:
+ version "4.3.0"
+ resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz"
+ integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
+
+estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0:
+ version "5.3.0"
+ resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz"
+ integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
+
+esutils@^2.0.2:
+ version "2.0.3"
+ resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz"
+ integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
+
+fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
+ version "3.1.3"
+ resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz"
+ integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
+
+fast-glob@^3.2.11, fast-glob@^3.2.9, fast-glob@^3.3.2:
+ version "3.3.2"
+ resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz"
+ integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==
+ dependencies:
+ "@nodelib/fs.stat" "^2.0.2"
+ "@nodelib/fs.walk" "^1.2.3"
+ glob-parent "^5.1.2"
+ merge2 "^1.3.0"
+ micromatch "^4.0.4"
+
+fast-json-stable-stringify@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz"
+ integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
+
+fast-levenshtein@^2.0.6:
+ version "2.0.6"
+ resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz"
+ integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
+
+fastq@^1.6.0:
+ version "1.13.0"
+ resolved "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz"
+ integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==
+ dependencies:
+ reusify "^1.0.4"
+
+file-entry-cache@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz"
+ integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==
+ dependencies:
+ flat-cache "^3.0.4"
+
+file-saver@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz"
+ integrity sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==
+
+fill-range@^7.1.1:
+ version "7.1.1"
+ resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz"
+ integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
+ dependencies:
+ to-regex-range "^5.0.1"
+
+filter-obj@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.npmjs.org/filter-obj/-/filter-obj-5.1.0.tgz"
+ integrity sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng==
+
+find-root@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz"
+ integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==
+
+find-up@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz"
+ integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
+ dependencies:
+ locate-path "^6.0.0"
+ path-exists "^4.0.0"
+
+flat-cache@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz"
+ integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==
+ dependencies:
+ flatted "^3.1.0"
+ rimraf "^3.0.2"
+
+flatted@^3.1.0:
+ version "3.2.7"
+ resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz"
+ integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
+
+follow-redirects@^1.15.6:
+ version "1.15.9"
+ resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz"
+ integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==
+
+foreground-child@^3.1.0:
+ version "3.3.0"
+ resolved "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz"
+ integrity sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==
+ dependencies:
+ cross-spawn "^7.0.0"
+ signal-exit "^4.0.1"
+
+form-data@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz"
+ integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.8"
+ mime-types "^2.1.12"
+
+formik@^2.4.5:
+ version "2.4.6"
+ resolved "https://registry.npmjs.org/formik/-/formik-2.4.6.tgz"
+ integrity sha512-A+2EI7U7aG296q2TLGvNapDNTZp1khVt5Vk0Q/fyfSROss0V/V6+txt2aJnwEos44IxTCW/LYAi/zgWzlevj+g==
+ dependencies:
+ "@types/hoist-non-react-statics" "^3.3.1"
+ deepmerge "^2.1.1"
+ hoist-non-react-statics "^3.3.0"
+ lodash "^4.17.21"
+ lodash-es "^4.17.21"
+ react-fast-compare "^2.0.1"
+ tiny-warning "^1.0.2"
+ tslib "^2.0.0"
+
+fraction.js@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz"
+ integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==
+
+fs.realpath@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
+ integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
+
+function-bind@^1.1.1, function-bind@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz"
+ integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
+
+function.prototype.name@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz"
+ integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+ es-abstract "^1.19.0"
+ functions-have-names "^1.2.2"
+
+functional-red-black-tree@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz"
+ integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==
+
+functions-have-names@^1.2.2:
+ version "1.2.3"
+ resolved "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz"
+ integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
+
+get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz"
+ integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==
+ dependencies:
+ function-bind "^1.1.1"
+ has "^1.0.3"
+ has-symbols "^1.0.3"
+
+get-symbol-description@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz"
+ integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==
+ dependencies:
+ call-bind "^1.0.2"
+ get-intrinsic "^1.1.1"
+
+get-tsconfig@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.2.0.tgz"
+ integrity sha512-X8u8fREiYOE6S8hLbq99PeykTDoLVnxvF4DjWKJmz9xy2nNRdUcV8ZN9tniJFeKyTU3qnC9lL8n4Chd6LmVKHg==
+
+glob-parent@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz"
+ integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
+ dependencies:
+ is-glob "^4.0.1"
+
+glob-parent@^6.0.1, glob-parent@^6.0.2:
+ version "6.0.2"
+ resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz"
+ integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
+ dependencies:
+ is-glob "^4.0.3"
+
+glob-parent@~5.1.2:
+ version "5.1.2"
+ resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz"
+ integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
+ dependencies:
+ is-glob "^4.0.1"
+
+glob@^10.3.10:
+ version "10.4.5"
+ resolved "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz"
+ integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==
+ dependencies:
+ foreground-child "^3.1.0"
+ jackspeak "^3.1.2"
+ minimatch "^9.0.4"
+ minipass "^7.1.2"
+ package-json-from-dist "^1.0.0"
+ path-scurry "^1.11.1"
+
+glob@^7.1.3, glob@7.1.7:
+ version "7.1.7"
+ resolved "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz"
+ integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.0.4"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+globalize@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.npmjs.org/globalize/-/globalize-0.1.1.tgz"
+ integrity sha512-5e01v8eLGfuQSOvx2MsDMOWS0GFtCx1wPzQSmcHw4hkxFzrQDBO3Xwg/m8Hr/7qXMrHeOIE29qWVzyv06u1TZA==
+
+globals@^11.1.0:
+ version "11.12.0"
+ resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz"
+ integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
+
+globals@^13.15.0:
+ version "13.17.0"
+ resolved "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz"
+ integrity sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==
+ dependencies:
+ type-fest "^0.20.2"
+
+globalyzer@0.1.0:
+ version "0.1.0"
+ resolved "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz"
+ integrity sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==
+
+globby@^11.1.0:
+ version "11.1.0"
+ resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz"
+ integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
+ dependencies:
+ array-union "^2.1.0"
+ dir-glob "^3.0.1"
+ fast-glob "^3.2.9"
+ ignore "^5.2.0"
+ merge2 "^1.4.1"
+ slash "^3.0.0"
+
+globby@^13.1.2:
+ version "13.1.2"
+ resolved "https://registry.npmjs.org/globby/-/globby-13.1.2.tgz"
+ integrity sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ==
+ dependencies:
+ dir-glob "^3.0.1"
+ fast-glob "^3.2.11"
+ ignore "^5.2.0"
+ merge2 "^1.4.1"
+ slash "^4.0.0"
+
+globrex@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz"
+ integrity sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==
+
+graceful-fs@^4.2.11, graceful-fs@^4.2.4:
+ version "4.2.11"
+ resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz"
+ integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
+
+grapheme-splitter@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz"
+ integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==
+
+has-bigints@^1.0.1, has-bigints@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz"
+ integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==
+
+has-flag@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz"
+ integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
+
+has-property-descriptors@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz"
+ integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==
+ dependencies:
+ get-intrinsic "^1.1.1"
+
+has-symbols@^1.0.2, has-symbols@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz"
+ integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
+
+has-tostringtag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz"
+ integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==
+ dependencies:
+ has-symbols "^1.0.2"
+
+has@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz"
+ integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
+ dependencies:
+ function-bind "^1.1.1"
+
+hasown@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz"
+ integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
+ dependencies:
+ function-bind "^1.1.2"
+
+hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2:
+ version "3.3.2"
+ resolved "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz"
+ integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
+ dependencies:
+ react-is "^16.7.0"
+
+ignore@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz"
+ integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==
+
+immer@^10.0.3:
+ version "10.1.1"
+ resolved "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz"
+ integrity sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==
+
+import-fresh@^3.0.0, import-fresh@^3.2.1:
+ version "3.3.0"
+ resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz"
+ integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
+ dependencies:
+ parent-module "^1.0.0"
+ resolve-from "^4.0.0"
+
+imurmurhash@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz"
+ integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
+
+inflight@^1.0.4:
+ version "1.0.6"
+ resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz"
+ integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
+ dependencies:
+ once "^1.3.0"
+ wrappy "1"
+
+inherits@2:
+ version "2.0.4"
+ resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
+ integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+
+internal-slot@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz"
+ integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==
+ dependencies:
+ get-intrinsic "^1.1.0"
+ has "^1.0.3"
+ side-channel "^1.0.4"
+
+intro.js-react@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/intro.js-react/-/intro.js-react-1.0.0.tgz"
+ integrity sha512-zR8pbTyX20RnCZpJMc0nuHBpsjcr1wFkj3ZookV6Ly4eE/LGpFTQwPsaA61Cryzwiy/tTFsusf4hPU9NpI9UOg==
+
+intro.js@^7.2.0:
+ version "7.2.0"
+ resolved "https://registry.npmjs.org/intro.js/-/intro.js-7.2.0.tgz"
+ integrity sha512-qbMfaB70rOXVBceIWNYnYTpVTiZsvQh/MIkfdQbpA9di9VBfj1GigUPfcCv3aOfsbrtPcri8vTLTA4FcEDcHSQ==
+
+invariant@^2.2.4:
+ version "2.2.4"
+ resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz"
+ integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
+ dependencies:
+ loose-envify "^1.0.0"
+
+is-arrayish@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz"
+ integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
+
+is-bigint@^1.0.1:
+ version "1.0.4"
+ resolved "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz"
+ integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==
+ dependencies:
+ has-bigints "^1.0.1"
+
+is-binary-path@~2.1.0:
+ version "2.1.0"
+ resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz"
+ integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
+ dependencies:
+ binary-extensions "^2.0.0"
+
+is-boolean-object@^1.1.0:
+ version "1.1.2"
+ resolved "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz"
+ integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==
+ dependencies:
+ call-bind "^1.0.2"
+ has-tostringtag "^1.0.0"
+
+is-callable@^1.1.4, is-callable@^1.2.7:
+ version "1.2.7"
+ resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz"
+ integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==
+
+is-core-module@^2.10.0, is-core-module@^2.16.0, is-core-module@^2.8.1, is-core-module@^2.9.0:
+ version "2.16.1"
+ resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz"
+ integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==
+ dependencies:
+ hasown "^2.0.2"
+
+is-date-object@^1.0.1:
+ version "1.0.5"
+ resolved "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz"
+ integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==
+ dependencies:
+ has-tostringtag "^1.0.0"
+
+is-docker@^2.0.0, is-docker@^2.1.1:
+ version "2.2.1"
+ resolved "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz"
+ integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==
+
+is-extglob@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz"
+ integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
+
+is-fullwidth-code-point@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz"
+ integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
+
+is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
+ version "4.0.3"
+ resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz"
+ integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
+ dependencies:
+ is-extglob "^2.1.1"
+
+is-negative-zero@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz"
+ integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==
+
+is-number-object@^1.0.4:
+ version "1.0.7"
+ resolved "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz"
+ integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==
+ dependencies:
+ has-tostringtag "^1.0.0"
+
+is-number@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz"
+ integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+
+is-regex@^1.1.4:
+ version "1.1.4"
+ resolved "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz"
+ integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==
+ dependencies:
+ call-bind "^1.0.2"
+ has-tostringtag "^1.0.0"
+
+is-shared-array-buffer@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz"
+ integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==
+ dependencies:
+ call-bind "^1.0.2"
+
+is-string@^1.0.5, is-string@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz"
+ integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==
+ dependencies:
+ has-tostringtag "^1.0.0"
+
+is-symbol@^1.0.2, is-symbol@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz"
+ integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==
+ dependencies:
+ has-symbols "^1.0.2"
+
+is-weakref@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz"
+ integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==
+ dependencies:
+ call-bind "^1.0.2"
+
+is-wsl@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz"
+ integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==
+ dependencies:
+ is-docker "^2.0.0"
+
+isexe@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz"
+ integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
+
+jackspeak@^3.1.2:
+ version "3.4.3"
+ resolved "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz"
+ integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==
+ dependencies:
+ "@isaacs/cliui" "^8.0.2"
+ optionalDependencies:
+ "@pkgjs/parseargs" "^0.11.0"
+
+jiti@^1.21.6:
+ version "1.21.7"
+ resolved "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz"
+ integrity sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==
+
+js-sdsl@^4.1.4:
+ version "4.1.4"
+ resolved "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz"
+ integrity sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw==
+
+"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz"
+ integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
+
+js-yaml@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz"
+ integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
+ dependencies:
+ argparse "^2.0.1"
+
+jsesc@^3.0.2:
+ version "3.1.0"
+ resolved "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz"
+ integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==
+
+json-parse-even-better-errors@^2.3.0:
+ version "2.3.1"
+ resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz"
+ integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
+
+json-schema-traverse@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz"
+ integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
+
+json-stable-stringify-without-jsonify@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz"
+ integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==
+
+json5@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz"
+ integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==
+ dependencies:
+ minimist "^1.2.0"
+
+jsonwebtoken@^9.0.2:
+ version "9.0.2"
+ resolved "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz"
+ integrity sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==
+ dependencies:
+ jws "^3.2.2"
+ lodash.includes "^4.3.0"
+ lodash.isboolean "^3.0.3"
+ lodash.isinteger "^4.0.4"
+ lodash.isnumber "^3.0.3"
+ lodash.isplainobject "^4.0.6"
+ lodash.isstring "^4.0.1"
+ lodash.once "^4.0.0"
+ ms "^2.1.1"
+ semver "^7.5.4"
+
+"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.2:
+ version "3.3.3"
+ resolved "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz"
+ integrity sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==
+ dependencies:
+ array-includes "^3.1.5"
+ object.assign "^4.1.3"
+
+jwa@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz"
+ integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==
+ dependencies:
+ buffer-equal-constant-time "1.0.1"
+ ecdsa-sig-formatter "1.0.11"
+ safe-buffer "^5.0.1"
+
+jws@^3.2.2:
+ version "3.2.2"
+ resolved "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz"
+ integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==
+ dependencies:
+ jwa "^1.4.1"
+ safe-buffer "^5.0.1"
+
+jwt-decode@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz"
+ integrity sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==
+
+krustykrab@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.npmjs.org/krustykrab/-/krustykrab-1.1.0.tgz"
+ integrity sha512-xpX9MPbw+nJseewe6who9Oq46RQwrBfps+dO/N4fSjJhsf2+y4XWC2kz46oBGX8yzMHyYJj35ug0X5s5yxB6tA==
+
+language-subtag-registry@~0.3.2:
+ version "0.3.22"
+ resolved "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz"
+ integrity sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==
+
+language-tags@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz"
+ integrity sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==
+ dependencies:
+ language-subtag-registry "~0.3.2"
+
+levn@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz"
+ integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==
+ dependencies:
+ prelude-ls "^1.2.1"
+ type-check "~0.4.0"
+
+lilconfig@^3.0.0, lilconfig@^3.1.3:
+ version "3.1.3"
+ resolved "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz"
+ integrity sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==
+
+lines-and-columns@^1.1.6:
+ version "1.2.4"
+ resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz"
+ integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
+
+locate-path@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz"
+ integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
+ dependencies:
+ p-locate "^5.0.0"
+
+lodash-es@^4.17.21:
+ version "4.17.21"
+ resolved "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz"
+ integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
+
+lodash.castarray@^4.4.0:
+ version "4.4.0"
+ resolved "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz"
+ integrity sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==
+
+lodash.includes@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz"
+ integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==
+
+lodash.isboolean@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz"
+ integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==
+
+lodash.isinteger@^4.0.4:
+ version "4.0.4"
+ resolved "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz"
+ integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==
+
+lodash.isnumber@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz"
+ integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==
+
+lodash.isplainobject@^4.0.6:
+ version "4.0.6"
+ resolved "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz"
+ integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==
+
+lodash.isstring@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz"
+ integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==
+
+lodash.merge@^4.6.2:
+ version "4.6.2"
+ resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz"
+ integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
+
+lodash.once@^4.0.0:
+ version "4.1.1"
+ resolved "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz"
+ integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==
+
+lodash@^4.17.21:
+ version "4.17.21"
+ resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
+ integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
+
+loose-envify@^1.0.0, loose-envify@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz"
+ integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
+ dependencies:
+ js-tokens "^3.0.0 || ^4.0.0"
+
+lru-cache@^10.2.0:
+ version "10.4.3"
+ resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz"
+ integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==
+
+luxon@^3.2.1:
+ version "3.5.0"
+ resolved "https://registry.npmjs.org/luxon/-/luxon-3.5.0.tgz"
+ integrity sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==
+
+memoize-one@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz"
+ integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==
+
+merge2@^1.3.0, merge2@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz"
+ integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
+
+micromatch@^4.0.4, micromatch@^4.0.8:
+ version "4.0.8"
+ resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz"
+ integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==
+ dependencies:
+ braces "^3.0.3"
+ picomatch "^2.3.1"
+
+mime-db@1.52.0:
+ version "1.52.0"
+ resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz"
+ integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
+
+mime-types@^2.1.12:
+ version "2.1.35"
+ resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz"
+ integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
+ dependencies:
+ mime-db "1.52.0"
+
+mini-svg-data-uri@^1.2.3:
+ version "1.4.4"
+ resolved "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz"
+ integrity sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==
+
+minimatch@^3.0.4, minimatch@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz"
+ integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
+ dependencies:
+ brace-expansion "^1.1.7"
+
+minimatch@^9.0.4:
+ version "9.0.5"
+ resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz"
+ integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==
+ dependencies:
+ brace-expansion "^2.0.1"
+
+minimist@^1.2.0, minimist@^1.2.6:
+ version "1.2.6"
+ resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz"
+ integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
+
+"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2:
+ version "7.1.2"
+ resolved "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz"
+ integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==
+
+moment-timezone@^0.5.40:
+ version "0.5.46"
+ resolved "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.46.tgz"
+ integrity sha512-ZXm9b36esbe7OmdABqIWJuBBiLLwAjrN7CE+7sYdCCx82Nabt1wHDj8TVseS59QIlfFPbOoiBPm6ca9BioG4hw==
+ dependencies:
+ moment "^2.29.4"
+
+moment@^2.29.4:
+ version "2.30.1"
+ resolved "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz"
+ integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==
+
+ms@^2.1.1, ms@2.1.2:
+ version "2.1.2"
+ resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
+ integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
+
+ms@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz"
+ integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
+
+mz@^2.7.0:
+ version "2.7.0"
+ resolved "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz"
+ integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==
+ dependencies:
+ any-promise "^1.0.0"
+ object-assign "^4.0.1"
+ thenify-all "^1.0.0"
+
+nanoid@^3.3.6, nanoid@^3.3.7:
+ version "3.3.8"
+ resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz"
+ integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==
+
+natural-compare@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz"
+ integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
+
+next@^14.1.0:
+ version "14.2.22"
+ resolved "https://registry.npmjs.org/next/-/next-14.2.22.tgz"
+ integrity sha512-Ps2caobQ9hlEhscLPiPm3J3SYhfwfpMqzsoCMZGWxt9jBRK9hoBZj2A37i8joKhsyth2EuVKDVJCTF5/H4iEDw==
+ dependencies:
+ "@next/env" "14.2.22"
+ "@swc/helpers" "0.5.5"
+ busboy "1.6.0"
+ caniuse-lite "^1.0.30001579"
+ graceful-fs "^4.2.11"
+ postcss "8.4.31"
+ styled-jsx "5.1.1"
+ optionalDependencies:
+ "@next/swc-darwin-arm64" "14.2.22"
+ "@next/swc-darwin-x64" "14.2.22"
+ "@next/swc-linux-arm64-gnu" "14.2.22"
+ "@next/swc-linux-arm64-musl" "14.2.22"
+ "@next/swc-linux-x64-gnu" "14.2.22"
+ "@next/swc-linux-x64-musl" "14.2.22"
+ "@next/swc-win32-arm64-msvc" "14.2.22"
+ "@next/swc-win32-ia32-msvc" "14.2.22"
+ "@next/swc-win32-x64-msvc" "14.2.22"
+
+node-releases@^2.0.6:
+ version "2.0.6"
+ resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz"
+ integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==
+
+normalize-path@^3.0.0, normalize-path@~3.0.0:
+ version "3.0.0"
+ resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz"
+ integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
+
+normalize-range@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz"
+ integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==
+
+numeral@^2.0.6:
+ version "2.0.6"
+ resolved "https://registry.npmjs.org/numeral/-/numeral-2.0.6.tgz"
+ integrity sha512-qaKRmtYPZ5qdw4jWJD6bxEf1FJEqllJrwxCLIm0sQU/A7v2/czigzOb+C2uSiFsa9lBUzeH7M1oK+Q+OLxL3kA==
+
+object-assign@^4.0.1, object-assign@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz"
+ integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
+
+object-hash@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz"
+ integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==
+
+object-inspect@^1.12.2, object-inspect@^1.9.0:
+ version "1.12.2"
+ resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz"
+ integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==
+
+object-keys@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz"
+ integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
+
+object.assign@^4.1.3, object.assign@^4.1.4:
+ version "4.1.4"
+ resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz"
+ integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ has-symbols "^1.0.3"
+ object-keys "^1.1.1"
+
+object.entries@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz"
+ integrity sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+ es-abstract "^1.19.1"
+
+object.fromentries@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz"
+ integrity sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+ es-abstract "^1.19.1"
+
+object.hasown@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.1.tgz"
+ integrity sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A==
+ dependencies:
+ define-properties "^1.1.4"
+ es-abstract "^1.19.5"
+
+object.values@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz"
+ integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+ es-abstract "^1.19.1"
+
+once@^1.3.0:
+ version "1.4.0"
+ resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz"
+ integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
+ dependencies:
+ wrappy "1"
+
+open@^8.4.0:
+ version "8.4.0"
+ resolved "https://registry.npmjs.org/open/-/open-8.4.0.tgz"
+ integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==
+ dependencies:
+ define-lazy-prop "^2.0.0"
+ is-docker "^2.1.1"
+ is-wsl "^2.2.0"
+
+optionator@^0.9.1:
+ version "0.9.1"
+ resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz"
+ integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==
+ dependencies:
+ deep-is "^0.1.3"
+ fast-levenshtein "^2.0.6"
+ levn "^0.4.1"
+ prelude-ls "^1.2.1"
+ type-check "^0.4.0"
+ word-wrap "^1.2.3"
+
+p-limit@^3.0.2:
+ version "3.1.0"
+ resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz"
+ integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
+ dependencies:
+ yocto-queue "^0.1.0"
+
+p-locate@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz"
+ integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
+ dependencies:
+ p-limit "^3.0.2"
+
+package-json-from-dist@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz"
+ integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==
+
+parent-module@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz"
+ integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
+ dependencies:
+ callsites "^3.0.0"
+
+parse-json@^5.0.0:
+ version "5.2.0"
+ resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz"
+ integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
+ dependencies:
+ "@babel/code-frame" "^7.0.0"
+ error-ex "^1.3.1"
+ json-parse-even-better-errors "^2.3.0"
+ lines-and-columns "^1.1.6"
+
+path-exists@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz"
+ integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
+
+path-is-absolute@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz"
+ integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
+
+path-key@^3.1.0:
+ version "3.1.1"
+ resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz"
+ integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
+
+path-parse@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz"
+ integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
+
+path-scurry@^1.11.1:
+ version "1.11.1"
+ resolved "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz"
+ integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==
+ dependencies:
+ lru-cache "^10.2.0"
+ minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
+
+path-type@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz"
+ integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
+
+picocolors@^1.0.0, picocolors@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz"
+ integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
+
+picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz"
+ integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
+
+pify@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz"
+ integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==
+
+pirates@^4.0.1:
+ version "4.0.6"
+ resolved "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz"
+ integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==
+
+postcss-import@^14.1.0:
+ version "14.1.0"
+ resolved "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz"
+ integrity sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==
+ dependencies:
+ postcss-value-parser "^4.0.0"
+ read-cache "^1.0.0"
+ resolve "^1.1.7"
+
+postcss-import@^15.1.0:
+ version "15.1.0"
+ resolved "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz"
+ integrity sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==
+ dependencies:
+ postcss-value-parser "^4.0.0"
+ read-cache "^1.0.0"
+ resolve "^1.1.7"
+
+postcss-js@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz"
+ integrity sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==
+ dependencies:
+ camelcase-css "^2.0.1"
+
+postcss-load-config@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz"
+ integrity sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==
+ dependencies:
+ lilconfig "^3.0.0"
+ yaml "^2.3.4"
+
+postcss-nested@^6.2.0:
+ version "6.2.0"
+ resolved "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz"
+ integrity sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==
+ dependencies:
+ postcss-selector-parser "^6.1.1"
+
+postcss-selector-parser@^6.1.1:
+ version "6.1.2"
+ resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz"
+ integrity sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==
+ dependencies:
+ cssesc "^3.0.0"
+ util-deprecate "^1.0.2"
+
+postcss-selector-parser@^6.1.2:
+ version "6.1.2"
+ resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz"
+ integrity sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==
+ dependencies:
+ cssesc "^3.0.0"
+ util-deprecate "^1.0.2"
+
+postcss-selector-parser@6.0.10:
+ version "6.0.10"
+ resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz"
+ integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==
+ dependencies:
+ cssesc "^3.0.0"
+ util-deprecate "^1.0.2"
+
+postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz"
+ integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
+
+postcss@^8.4.4, postcss@^8.4.47:
+ version "8.4.49"
+ resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz"
+ integrity sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==
+ dependencies:
+ nanoid "^3.3.7"
+ picocolors "^1.1.1"
+ source-map-js "^1.2.1"
+
+postcss@8.4.31:
+ version "8.4.31"
+ resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz"
+ integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==
+ dependencies:
+ nanoid "^3.3.6"
+ picocolors "^1.0.0"
+ source-map-js "^1.0.2"
+
+prelude-ls@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz"
+ integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
+
+prettier@^3.2.4:
+ version "3.4.2"
+ resolved "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz"
+ integrity sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==
+
+prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
+ version "15.8.1"
+ resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz"
+ integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
+ dependencies:
+ loose-envify "^1.4.0"
+ object-assign "^4.1.1"
+ react-is "^16.13.1"
+
+proxy-from-env@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz"
+ integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
+
+punycode@^2.1.0:
+ version "2.1.1"
+ resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz"
+ integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
+
+query-string@^8.1.0:
+ version "8.2.0"
+ resolved "https://registry.npmjs.org/query-string/-/query-string-8.2.0.tgz"
+ integrity sha512-tUZIw8J0CawM5wyGBiDOAp7ObdRQh4uBor/fUR9ZjmbZVvw95OD9If4w3MQxr99rg0DJZ/9CIORcpEqU5hQG7g==
+ dependencies:
+ decode-uri-component "^0.4.1"
+ filter-obj "^5.1.0"
+ split-on-first "^3.0.0"
+
+queue-microtask@^1.2.2:
+ version "1.2.3"
+ resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz"
+ integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
+
+react-apexcharts@^1.4.1:
+ version "1.7.0"
+ resolved "https://registry.npmjs.org/react-apexcharts/-/react-apexcharts-1.7.0.tgz"
+ integrity sha512-03oScKJyNLRf0Oe+ihJxFZliBQM9vW3UWwomVn4YVRTN1jsIR58dLWt0v1sb8RwJVHDMbeHiKQueM0KGpn7nOA==
+ dependencies:
+ prop-types "^15.8.1"
+
+react-big-calendar@^1.10.3:
+ version "1.17.1"
+ resolved "https://registry.npmjs.org/react-big-calendar/-/react-big-calendar-1.17.1.tgz"
+ integrity sha512-LltUAMSGODWQBKx4013bRe6R0jaINV9hrs970+F860KedpozwRGGMT66esV9mA3mAhfSKoazF/QH1WCyLkXYZA==
+ dependencies:
+ "@babel/runtime" "^7.20.7"
+ clsx "^1.2.1"
+ date-arithmetic "^4.1.0"
+ dayjs "^1.11.7"
+ dom-helpers "^5.2.1"
+ globalize "^0.1.1"
+ invariant "^2.2.4"
+ lodash "^4.17.21"
+ lodash-es "^4.17.21"
+ luxon "^3.2.1"
+ memoize-one "^6.0.0"
+ moment "^2.29.4"
+ moment-timezone "^0.5.40"
+ prop-types "^15.8.1"
+ react-overlays "^5.2.1"
+ uncontrollable "^7.2.1"
+
+react-chartjs-2@^4.3.1:
+ version "4.3.1"
+ resolved "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-4.3.1.tgz"
+ integrity sha512-5i3mjP6tU7QSn0jvb8I4hudTzHJqS8l00ORJnVwI2sYu0ihpj83Lv2YzfxunfxTZkscKvZu2F2w9LkwNBhj6xA==
+
+react-datepicker@^4.10.0:
+ version "4.25.0"
+ resolved "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.25.0.tgz"
+ integrity sha512-zB7CSi44SJ0sqo8hUQ3BF1saE/knn7u25qEMTO1CQGofY1VAKahO8k9drZtp0cfW1DMfoYLR3uSY1/uMvbEzbg==
+ dependencies:
+ "@popperjs/core" "^2.11.8"
+ classnames "^2.2.6"
+ date-fns "^2.30.0"
+ prop-types "^15.7.2"
+ react-onclickoutside "^6.13.0"
+ react-popper "^2.3.0"
+
+react-dom@^19.0.0:
+ version "19.0.0"
+ resolved "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz"
+ integrity sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==
+ dependencies:
+ scheduler "^0.25.0"
+
+react-fast-compare@^2.0.1:
+ version "2.0.4"
+ resolved "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz"
+ integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
+
+react-fast-compare@^3.0.1:
+ version "3.2.2"
+ resolved "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz"
+ integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==
+
+react-is@^16.13.1, react-is@^16.7.0:
+ version "16.13.1"
+ resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
+ integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
+
+react-is@^18.0.0:
+ version "18.2.0"
+ resolved "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz"
+ integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
+
+react-is@^19.0.0:
+ version "19.0.0"
+ resolved "https://registry.npmjs.org/react-is/-/react-is-19.0.0.tgz"
+ integrity sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g==
+
+react-lifecycles-compat@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz"
+ integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
+
+react-onclickoutside@^6.13.0:
+ version "6.13.1"
+ resolved "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.1.tgz"
+ integrity sha512-LdrrxK/Yh9zbBQdFbMTXPp3dTSN9B+9YJQucdDu3JNKRrbdU+H+/TVONJoWtOwy4II8Sqf1y/DTI6w/vGPYW0w==
+
+react-overlays@^5.2.1:
+ version "5.2.1"
+ resolved "https://registry.npmjs.org/react-overlays/-/react-overlays-5.2.1.tgz"
+ integrity sha512-GLLSOLWr21CqtJn8geSwQfoJufdt3mfdsnIiQswouuQ2MMPns+ihZklxvsTDKD3cR2tF8ELbi5xUsvqVhR6WvA==
+ dependencies:
+ "@babel/runtime" "^7.13.8"
+ "@popperjs/core" "^2.11.6"
+ "@restart/hooks" "^0.4.7"
+ "@types/warning" "^3.0.0"
+ dom-helpers "^5.2.0"
+ prop-types "^15.7.2"
+ uncontrollable "^7.2.1"
+ warning "^4.0.3"
+
+react-popper@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz"
+ integrity sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==
+ dependencies:
+ react-fast-compare "^3.0.1"
+ warning "^4.0.2"
+
+react-redux@^8.0.2:
+ version "8.0.2"
+ resolved "https://registry.npmjs.org/react-redux/-/react-redux-8.0.2.tgz"
+ integrity sha512-nBwiscMw3NoP59NFCXFf02f8xdo+vSHT/uZ1ldDwF7XaTpzm+Phk97VT4urYBl5TYAPNVaFm12UHAEyzkpNzRA==
+ dependencies:
+ "@babel/runtime" "^7.12.1"
+ "@types/hoist-non-react-statics" "^3.3.1"
+ "@types/use-sync-external-store" "^0.0.3"
+ hoist-non-react-statics "^3.3.2"
+ react-is "^18.0.0"
+ use-sync-external-store "^1.0.0"
+
+react-select-async-paginate@^0.7.9:
+ version "0.7.9"
+ resolved "https://registry.npmjs.org/react-select-async-paginate/-/react-select-async-paginate-0.7.9.tgz"
+ integrity sha512-oGdmXWatj06MNUcLwFkyt8qLBA0km0gFvDF52qaQQEArRjprbTajaYwhtjVotKTw1IXfw3fiq3G9Lgsjfpjz/Q==
+ dependencies:
+ "@seznam/compose-react-refs" "^1.0.6"
+ "@vtaits/use-lazy-ref" "^0.1.3"
+ krustykrab "^1.1.0"
+ sleep-promise "^9.1.0"
+ use-is-mounted-ref "^1.5.0"
+ use-latest "^1.3.0"
+
+react-select@^5.7.0:
+ version "5.9.0"
+ resolved "https://registry.npmjs.org/react-select/-/react-select-5.9.0.tgz"
+ integrity sha512-nwRKGanVHGjdccsnzhFte/PULziueZxGD8LL2WojON78Mvnq7LdAMEtu2frrwld1fr3geixg3iiMBIc/LLAZpw==
+ dependencies:
+ "@babel/runtime" "^7.12.0"
+ "@emotion/cache" "^11.4.0"
+ "@emotion/react" "^11.8.1"
+ "@floating-ui/dom" "^1.0.1"
+ "@types/react-transition-group" "^4.4.0"
+ memoize-one "^6.0.0"
+ prop-types "^15.6.0"
+ react-transition-group "^4.3.0"
+ use-isomorphic-layout-effect "^1.2.0"
+
+react-switch@^7.0.0:
+ version "7.1.0"
+ resolved "https://registry.npmjs.org/react-switch/-/react-switch-7.1.0.tgz"
+ integrity sha512-4xVeyImZE8QOTDw2FmhWz0iqo2psoRiS7XzdjaZBCIP8Dzo3rT0esHUjLee5WsAPSFXWWl1eVA5arp9n2C6yQA==
+ dependencies:
+ prop-types "^15.7.2"
+
+react-toastify@^9.1.2:
+ version "9.1.3"
+ resolved "https://registry.npmjs.org/react-toastify/-/react-toastify-9.1.3.tgz"
+ integrity sha512-fPfb8ghtn/XMxw3LkxQBk3IyagNpF/LIKjOBflbexr2AWxAH1MJgvnESwEwBn9liLFXgTKWgBSdZpw9m4OTHTg==
+ dependencies:
+ clsx "^1.1.1"
+
+react-transition-group@^4.3.0, react-transition-group@^4.4.5:
+ version "4.4.5"
+ resolved "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz"
+ integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==
+ dependencies:
+ "@babel/runtime" "^7.5.5"
+ dom-helpers "^5.0.1"
+ loose-envify "^1.4.0"
+ prop-types "^15.6.2"
+
+react@^19.0.0:
+ version "19.0.0"
+ resolved "https://registry.npmjs.org/react/-/react-19.0.0.tgz"
+ integrity sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==
+
+read-cache@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz"
+ integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==
+ dependencies:
+ pify "^2.3.0"
+
+readdirp@~3.6.0:
+ version "3.6.0"
+ resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz"
+ integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
+ dependencies:
+ picomatch "^2.2.1"
+
+redux-thunk@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz"
+ integrity sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==
+
+redux@^4.0.0:
+ version "4.2.0"
+ resolved "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz"
+ integrity sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==
+ dependencies:
+ "@babel/runtime" "^7.9.2"
+
+redux@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz"
+ integrity sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==
+
+regenerator-runtime@^0.13.4:
+ version "0.13.9"
+ resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz"
+ integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==
+
+regenerator-runtime@^0.14.0:
+ version "0.14.1"
+ resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz"
+ integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==
+
+regexp.prototype.flags@^1.4.1, regexp.prototype.flags@^1.4.3:
+ version "1.4.3"
+ resolved "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz"
+ integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+ functions-have-names "^1.2.2"
+
+regexpp@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz"
+ integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==
+
+reselect@^4.1.8:
+ version "4.1.8"
+ resolved "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz"
+ integrity sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==
+
+reselect@^5.1.0:
+ version "5.1.1"
+ resolved "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz"
+ integrity sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==
+
+resolve-from@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz"
+ integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
+
+resolve@^1.1.7, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.22.8:
+ version "1.22.10"
+ resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz"
+ integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==
+ dependencies:
+ is-core-module "^2.16.0"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
+
+resolve@^2.0.0-next.3:
+ version "2.0.0-next.4"
+ resolved "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz"
+ integrity sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==
+ dependencies:
+ is-core-module "^2.9.0"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
+
+reusify@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz"
+ integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
+
+rimraf@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz"
+ integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
+ dependencies:
+ glob "^7.1.3"
+
+run-parallel@^1.1.9:
+ version "1.2.0"
+ resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz"
+ integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
+ dependencies:
+ queue-microtask "^1.2.2"
+
+safe-buffer@^5.0.1:
+ version "5.2.1"
+ resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz"
+ integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
+
+safe-regex-test@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz"
+ integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==
+ dependencies:
+ call-bind "^1.0.2"
+ get-intrinsic "^1.1.3"
+ is-regex "^1.1.4"
+
+scheduler@^0.25.0:
+ version "0.25.0"
+ resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz"
+ integrity sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==
+
+semver@^6.3.0:
+ version "6.3.0"
+ resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz"
+ integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
+
+semver@^7.3.7, semver@^7.5.4:
+ version "7.6.3"
+ resolved "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz"
+ integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==
+
+shebang-command@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz"
+ integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
+ dependencies:
+ shebang-regex "^3.0.0"
+
+shebang-regex@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz"
+ integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
+
+side-channel@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz"
+ integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==
+ dependencies:
+ call-bind "^1.0.0"
+ get-intrinsic "^1.0.2"
+ object-inspect "^1.9.0"
+
+signal-exit@^4.0.1:
+ version "4.1.0"
+ resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz"
+ integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==
+
+slash@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz"
+ integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
+
+slash@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz"
+ integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==
+
+sleep-promise@^9.1.0:
+ version "9.1.0"
+ resolved "https://registry.npmjs.org/sleep-promise/-/sleep-promise-9.1.0.tgz"
+ integrity sha512-UHYzVpz9Xn8b+jikYSD6bqvf754xL2uBUzDFwiU6NcdZeifPr6UfgU43xpkPu67VMS88+TI2PSI7Eohgqf2fKA==
+
+source-map-js@^1.0.2, source-map-js@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz"
+ integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
+
+source-map@^0.5.7:
+ version "0.5.7"
+ resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz"
+ integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==
+
+split-on-first@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.npmjs.org/split-on-first/-/split-on-first-3.0.0.tgz"
+ integrity sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==
+
+streamsearch@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz"
+ integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
+
+"string-width-cjs@npm:string-width@^4.2.0":
+ version "4.2.3"
+ resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
+ integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+ dependencies:
+ emoji-regex "^8.0.0"
+ is-fullwidth-code-point "^3.0.0"
+ strip-ansi "^6.0.1"
+
+string-width@^4.1.0:
+ version "4.2.3"
+ resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
+ integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+ dependencies:
+ emoji-regex "^8.0.0"
+ is-fullwidth-code-point "^3.0.0"
+ strip-ansi "^6.0.1"
+
+string-width@^5.0.1, string-width@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz"
+ integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==
+ dependencies:
+ eastasianwidth "^0.2.0"
+ emoji-regex "^9.2.2"
+ strip-ansi "^7.0.1"
+
+string.prototype.matchall@^4.0.7:
+ version "4.0.7"
+ resolved "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz"
+ integrity sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+ es-abstract "^1.19.1"
+ get-intrinsic "^1.1.1"
+ has-symbols "^1.0.3"
+ internal-slot "^1.0.3"
+ regexp.prototype.flags "^1.4.1"
+ side-channel "^1.0.4"
+
+string.prototype.trimend@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz"
+ integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.19.5"
+
+string.prototype.trimstart@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz"
+ integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.19.5"
+
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
+ version "6.0.1"
+ resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
+ integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+ dependencies:
+ ansi-regex "^5.0.1"
+
+strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
+ integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+ dependencies:
+ ansi-regex "^5.0.1"
+
+strip-ansi@^7.0.1:
+ version "7.1.0"
+ resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz"
+ integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==
+ dependencies:
+ ansi-regex "^6.0.1"
+
+strip-bom@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz"
+ integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==
+
+strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz"
+ integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
+
+styled-jsx@5.1.1:
+ version "5.1.1"
+ resolved "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz"
+ integrity sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==
+ dependencies:
+ client-only "0.0.1"
+
+stylis@4.2.0:
+ version "4.2.0"
+ resolved "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz"
+ integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==
+
+sucrase@^3.35.0:
+ version "3.35.0"
+ resolved "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz"
+ integrity sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==
+ dependencies:
+ "@jridgewell/gen-mapping" "^0.3.2"
+ commander "^4.0.0"
+ glob "^10.3.10"
+ lines-and-columns "^1.1.6"
+ mz "^2.7.0"
+ pirates "^4.0.1"
+ ts-interface-checker "^0.1.9"
+
+supports-color@^7.1.0:
+ version "7.2.0"
+ resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz"
+ integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
+ dependencies:
+ has-flag "^4.0.0"
+
+supports-preserve-symlinks-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz"
+ integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
+
+svg.draggable.js@^2.2.2:
+ version "2.2.2"
+ resolved "https://registry.npmjs.org/svg.draggable.js/-/svg.draggable.js-2.2.2.tgz"
+ integrity sha512-JzNHBc2fLQMzYCZ90KZHN2ohXL0BQJGQimK1kGk6AvSeibuKcIdDX9Kr0dT9+UJ5O8nYA0RB839Lhvk4CY4MZw==
+ dependencies:
+ svg.js "^2.0.1"
+
+svg.easing.js@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.npmjs.org/svg.easing.js/-/svg.easing.js-2.0.0.tgz"
+ integrity sha512-//ctPdJMGy22YoYGV+3HEfHbm6/69LJUTAqI2/5qBvaNHZ9uUFVC82B0Pl299HzgH13rKrBgi4+XyXXyVWWthA==
+ dependencies:
+ svg.js ">=2.3.x"
+
+svg.filter.js@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.npmjs.org/svg.filter.js/-/svg.filter.js-2.0.2.tgz"
+ integrity sha512-xkGBwU+dKBzqg5PtilaTb0EYPqPfJ9Q6saVldX+5vCRy31P6TlRCP3U9NxH3HEufkKkpNgdTLBJnmhDHeTqAkw==
+ dependencies:
+ svg.js "^2.2.5"
+
+svg.js@^2.0.1, svg.js@^2.2.5, svg.js@^2.4.0, svg.js@^2.6.5, svg.js@>=2.3.x:
+ version "2.7.1"
+ resolved "https://registry.npmjs.org/svg.js/-/svg.js-2.7.1.tgz"
+ integrity sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA==
+
+svg.pathmorphing.js@^0.1.3:
+ version "0.1.3"
+ resolved "https://registry.npmjs.org/svg.pathmorphing.js/-/svg.pathmorphing.js-0.1.3.tgz"
+ integrity sha512-49HWI9X4XQR/JG1qXkSDV8xViuTLIWm/B/7YuQELV5KMOPtXjiwH4XPJvr/ghEDibmLQ9Oc22dpWpG0vUDDNww==
+ dependencies:
+ svg.js "^2.4.0"
+
+svg.resize.js@^1.4.3:
+ version "1.4.3"
+ resolved "https://registry.npmjs.org/svg.resize.js/-/svg.resize.js-1.4.3.tgz"
+ integrity sha512-9k5sXJuPKp+mVzXNvxz7U0uC9oVMQrrf7cFsETznzUDDm0x8+77dtZkWdMfRlmbkEEYvUn9btKuZ3n41oNA+uw==
+ dependencies:
+ svg.js "^2.6.5"
+ svg.select.js "^2.1.2"
+
+svg.select.js@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.npmjs.org/svg.select.js/-/svg.select.js-2.1.2.tgz"
+ integrity sha512-tH6ABEyJsAOVAhwcCjF8mw4crjXSI1aa7j2VQR8ZuJ37H2MBUbyeqYr5nEO7sSN3cy9AR9DUwNg0t/962HlDbQ==
+ dependencies:
+ svg.js "^2.2.5"
+
+svg.select.js@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.npmjs.org/svg.select.js/-/svg.select.js-3.0.1.tgz"
+ integrity sha512-h5IS/hKkuVCbKSieR9uQCj9w+zLHoPh+ce19bBYyqF53g6mnPB8sAtIbe1s9dh2S2fCmYX2xel1Ln3PJBbK4kw==
+ dependencies:
+ svg.js "^2.6.5"
+
+swr@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.npmjs.org/swr/-/swr-1.3.0.tgz"
+ integrity sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw==
+
+synckit@^0.8.4:
+ version "0.8.4"
+ resolved "https://registry.npmjs.org/synckit/-/synckit-0.8.4.tgz"
+ integrity sha512-Dn2ZkzMdSX827QbowGbU/4yjWuvNaCoScLLoMo/yKbu+P4GBR6cRGKZH27k6a9bRzdqcyd1DE96pQtQ6uNkmyw==
+ dependencies:
+ "@pkgr/utils" "^2.3.1"
+ tslib "^2.4.0"
+
+tailwindcss@^3.4.1:
+ version "3.4.17"
+ resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz"
+ integrity sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==
+ dependencies:
+ "@alloc/quick-lru" "^5.2.0"
+ arg "^5.0.2"
+ chokidar "^3.6.0"
+ didyoumean "^1.2.2"
+ dlv "^1.1.3"
+ fast-glob "^3.3.2"
+ glob-parent "^6.0.2"
+ is-glob "^4.0.3"
+ jiti "^1.21.6"
+ lilconfig "^3.1.3"
+ micromatch "^4.0.8"
+ normalize-path "^3.0.0"
+ object-hash "^3.0.0"
+ picocolors "^1.1.1"
+ postcss "^8.4.47"
+ postcss-import "^15.1.0"
+ postcss-js "^4.0.1"
+ postcss-load-config "^4.0.2"
+ postcss-nested "^6.2.0"
+ postcss-selector-parser "^6.1.2"
+ resolve "^1.22.8"
+ sucrase "^3.35.0"
+
+tapable@^2.2.0:
+ version "2.2.1"
+ resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz"
+ integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
+
+text-table@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz"
+ integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
+
+thenify-all@^1.0.0:
+ version "1.6.0"
+ resolved "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz"
+ integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==
+ dependencies:
+ thenify ">= 3.1.0 < 4"
+
+"thenify@>= 3.1.0 < 4":
+ version "3.3.1"
+ resolved "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz"
+ integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==
+ dependencies:
+ any-promise "^1.0.0"
+
+tiny-glob@^0.2.9:
+ version "0.2.9"
+ resolved "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz"
+ integrity sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==
+ dependencies:
+ globalyzer "0.1.0"
+ globrex "^0.1.2"
+
+tiny-warning@^1.0.2:
+ version "1.0.3"
+ resolved "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz"
+ integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
+
+"tinymce@^6.0.0 || ^5.5.1":
+ version "6.8.5"
+ resolved "https://registry.npmjs.org/tinymce/-/tinymce-6.8.5.tgz"
+ integrity sha512-qAL/FxL7cwZHj4BfaF818zeJJizK9jU5IQzTcSLL4Rj5MaJdiVblEj7aDr80VCV1w9h4Lak9hlnALhq/kVtN1g==
+
+to-regex-range@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz"
+ integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+ dependencies:
+ is-number "^7.0.0"
+
+ts-interface-checker@^0.1.9:
+ version "0.1.13"
+ resolved "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz"
+ integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==
+
+tsconfig-paths@^3.14.1:
+ version "3.14.1"
+ resolved "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz"
+ integrity sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==
+ dependencies:
+ "@types/json5" "^0.0.29"
+ json5 "^1.0.1"
+ minimist "^1.2.6"
+ strip-bom "^3.0.0"
+
+tslib@^1.8.1:
+ version "1.14.1"
+ resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz"
+ integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
+
+tslib@^2.0.0, tslib@^2.4.0:
+ version "2.4.0"
+ resolved "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz"
+ integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
+
+tsutils@^3.21.0:
+ version "3.21.0"
+ resolved "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz"
+ integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==
+ dependencies:
+ tslib "^1.8.1"
+
+type-check@^0.4.0, type-check@~0.4.0:
+ version "0.4.0"
+ resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz"
+ integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==
+ dependencies:
+ prelude-ls "^1.2.1"
+
+type-fest@^0.20.2:
+ version "0.20.2"
+ resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz"
+ integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
+
+typescript@^4.8.3:
+ version "4.8.3"
+ resolved "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz"
+ integrity sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==
+
+unbox-primitive@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz"
+ integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==
+ dependencies:
+ call-bind "^1.0.2"
+ has-bigints "^1.0.2"
+ has-symbols "^1.0.3"
+ which-boxed-primitive "^1.0.2"
+
+uncontrollable@^7.2.1:
+ version "7.2.1"
+ resolved "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz"
+ integrity sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==
+ dependencies:
+ "@babel/runtime" "^7.6.3"
+ "@types/react" ">=16.9.11"
+ invariant "^2.2.4"
+ react-lifecycles-compat "^3.0.4"
+
+update-browserslist-db@^1.0.5:
+ version "1.0.9"
+ resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz"
+ integrity sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg==
+ dependencies:
+ escalade "^3.1.1"
+ picocolors "^1.0.0"
+
+uri-js@^4.2.2:
+ version "4.4.1"
+ resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz"
+ integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
+ dependencies:
+ punycode "^2.1.0"
+
+use-is-mounted-ref@^1.5.0:
+ version "1.5.0"
+ resolved "https://registry.npmjs.org/use-is-mounted-ref/-/use-is-mounted-ref-1.5.0.tgz"
+ integrity sha512-p5FksHf/ospZUr5KU9ese6u3jp9fzvZ3wuSb50i0y6fdONaHWgmOqQtxR/PUcwi6hnhQDbNxWSg3eTK3N6m+dg==
+
+use-isomorphic-layout-effect@^1.1.1, use-isomorphic-layout-effect@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.0.tgz"
+ integrity sha512-q6ayo8DWoPZT0VdG4u3D3uxcgONP3Mevx2i2b0434cwWBoL+aelL1DzkXI6w3PhTZzUeR2kaVlZn70iCiseP6w==
+
+use-latest@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.npmjs.org/use-latest/-/use-latest-1.3.0.tgz"
+ integrity sha512-mhg3xdm9NaM8q+gLT8KryJPnRFOz1/5XPBhmDEVZK1webPzDjrPk7f/mbpeLqTgB9msytYWANxgALOCJKnLvcQ==
+ dependencies:
+ use-isomorphic-layout-effect "^1.1.1"
+
+use-sync-external-store@^1.0.0:
+ version "1.2.0"
+ resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz"
+ integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
+
+util-deprecate@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
+ integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
+
+uuid@^9.0.0:
+ version "9.0.1"
+ resolved "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz"
+ integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==
+
+warning@^4.0.2, warning@^4.0.3:
+ version "4.0.3"
+ resolved "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz"
+ integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==
+ dependencies:
+ loose-envify "^1.0.0"
+
+which-boxed-primitive@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz"
+ integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==
+ dependencies:
+ is-bigint "^1.0.1"
+ is-boolean-object "^1.1.0"
+ is-number-object "^1.0.4"
+ is-string "^1.0.5"
+ is-symbol "^1.0.3"
+
+which@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz"
+ integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
+ dependencies:
+ isexe "^2.0.0"
+
+word-wrap@^1.2.3:
+ version "1.2.3"
+ resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz"
+ integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
+
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz"
+ integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
+wrap-ansi@^8.1.0:
+ version "8.1.0"
+ resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz"
+ integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==
+ dependencies:
+ ansi-styles "^6.1.0"
+ string-width "^5.0.1"
+ strip-ansi "^7.0.1"
+
+wrappy@1:
+ version "1.0.2"
+ resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
+ integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
+
+yaml@^1.10.0:
+ version "1.10.2"
+ resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz"
+ integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
+
+yaml@^2.3.4:
+ version "2.7.0"
+ resolved "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz"
+ integrity sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==
+
+yocto-queue@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz"
+ integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
diff --git a/nginx.conf b/nginx.conf
new file mode 100644
index 0000000..926fcdd
--- /dev/null
+++ b/nginx.conf
@@ -0,0 +1,96 @@
+worker_processes 1;
+
+events {
+ worker_connections 1024;
+}
+
+http {
+ client_max_body_size 10M;
+ map $http_upgrade $connection_upgrade {
+ default upgrade;
+ '' close;
+ }
+
+ server {
+ listen 8080;
+
+ error_page 502 /502.html;
+ location = /502.html {
+ root /usr/share/nginx/html;
+ internal;
+ }
+
+ location /api/logError {
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_pass http://127.0.0.1:3001/api/logError;
+ }
+
+
+ location /api-docs/ {
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_pass http://127.0.0.1:3000/api-docs/;
+ }
+
+ location /api/ {
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ add_header 'Access-Control-Allow-Origin' '*';
+ add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
+ add_header 'Access-Control-Allow-Headers' 'DNT, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Range';
+ add_header 'Access-Control-Expose-Headers' 'Content-Length, Content-Range';
+ proxy_pass http://127.0.0.1:3000/api/;
+ }
+
+ location / {
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_pass http://127.0.0.1:3001/;
+ }
+
+ location /app-shell/ {
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_pass http://127.0.0.1:4000/;
+ }
+
+ location /locales/ {
+ root /app/frontend/public;
+ expires 1h;
+ add_header Cache-Control "public, must-revalidate";
+ try_files $uri =404;
+ }
+
+ location ~ /_next/webpack-hmr {
+ proxy_pass http://127.0.0.1:3001;
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection $connection_upgrade;
+ proxy_set_header Host $host;
+ proxy_cache_bypass $http_upgrade;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ }
+
+ location ~ ^/_next/ {
+ proxy_pass http://127.0.0.1:3001;
+ proxy_http_version 1.1;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ }
+ }
+}
\ No newline at end of file
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..cf4ff37
--- /dev/null
+++ b/package.json
@@ -0,0 +1,8 @@
+{
+ "name": "app",
+ "version": "0.0.1",
+ "scripts": {
+ "build:production": "cd ./frontend && yarn install && yarn run build && rm -rf ./node_modules && cd ../backend && yarn install",
+ "start:production": "cd ./backend && NODE_ENV=production yarn start"
+ }
+}