1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-08 23:46:14 +01:00
fab-manager/app/frontend/src/javascript/components/store/orders.tsx

274 lines
8.2 KiB
TypeScript
Raw Normal View History

2022-08-29 19:15:10 +02:00
import React, { useState, useEffect } from 'react';
import { useImmer } from 'use-immer';
import { useTranslation } from 'react-i18next';
import { react2angular } from 'react2angular';
import { Loader } from '../base/loader';
import { IApplication } from '../../models/application';
2022-09-07 18:36:54 +02:00
import { useForm } from 'react-hook-form';
2022-08-29 19:15:10 +02:00
import { FabButton } from '../base/fab-button';
import { StoreListHeader } from './store-list-header';
import { AccordionItem } from './accordion-item';
2022-09-01 16:08:37 +02:00
import { OrderItem } from './order-item';
import { MemberSelect } from '../user/member-select';
2022-09-07 15:35:46 +02:00
import { User } from '../../models/user';
2022-09-07 18:36:54 +02:00
import { FormInput } from '../form/form-input';
import { TDateISODate } from '../../typings/date-iso';
import OrderAPI from '../../api/order';
import { Order } from '../../models/order';
2022-08-29 19:15:10 +02:00
declare const Application: IApplication;
interface OrdersProps {
2022-09-07 15:35:46 +02:00
currentUser?: User,
2022-08-29 19:15:10 +02:00
onSuccess: (message: string) => void,
onError: (message: string) => void,
}
/**
2022-09-01 16:08:37 +02:00
* Option format, expected by react-select
* @see https://github.com/JedWatson/react-select
*/
type selectOption = { value: number, label: string };
/**
* Option format, expected by checklist
*/
2022-08-29 19:15:10 +02:00
type checklistOption = { value: number, label: string };
/**
* Admin list of orders
*/
2022-09-07 09:22:16 +02:00
// TODO: delete next eslint disable
// eslint-disable-next-line @typescript-eslint/no-unused-vars
2022-09-07 15:35:46 +02:00
const Orders: React.FC<OrdersProps> = ({ currentUser, onSuccess, onError }) => {
2022-08-29 19:15:10 +02:00
const { t } = useTranslation('admin');
2022-09-07 18:36:54 +02:00
const { register, getValues } = useForm();
const [orders, setOrders] = useState<Array<Order>>([]);
2022-08-29 19:15:10 +02:00
const [filters, setFilters] = useImmer<Filters>(initFilters);
const [clearFilters, setClearFilters] = useState<boolean>(false);
const [accordion, setAccordion] = useState({});
useEffect(() => {
OrderAPI.index({}).then(res => {
setOrders(res.data);
}).catch(onError);
}, []);
2022-08-29 19:15:10 +02:00
useEffect(() => {
applyFilters();
setClearFilters(false);
}, [clearFilters]);
/**
* Create a new order
*/
const newOrder = () => {
console.log('Create new order');
};
2022-09-01 16:08:37 +02:00
const statusOptions: checklistOption[] = [
{ value: 0, label: t('app.admin.store.orders.status.error') },
{ value: 1, label: t('app.admin.store.orders.status.canceled') },
{ value: 2, label: t('app.admin.store.orders.status.pending') },
{ value: 3, label: t('app.admin.store.orders.status.under_preparation') },
{ value: 4, label: t('app.admin.store.orders.status.paid') },
{ value: 5, label: t('app.admin.store.orders.status.ready') },
{ value: 6, label: t('app.admin.store.orders.status.collected') },
{ value: 7, label: t('app.admin.store.orders.status.refunded') }
];
2022-08-29 19:15:10 +02:00
/**
* Apply filters
*/
const applyFilters = () => {
console.log('Apply filters:', filters);
};
/**
* Clear filters
*/
const clearAllFilters = () => {
setFilters(initFilters);
setClearFilters(true);
console.log('Clear all filters');
};
/**
* Creates sorting options to the react-select format
*/
const buildOptions = (): Array<selectOption> => {
return [
{ value: 0, label: t('app.admin.store.orders.sort.newest') },
{ value: 1, label: t('app.admin.store.orders.sort.oldest') }
];
};
/**
* Display option: sorting
*/
const handleSorting = (option: selectOption) => {
console.log('Sort option:', option);
};
/**
* Filter: by status
*/
const handleSelectStatus = (s: checklistOption, checked) => {
const list = [...filters.status];
checked
? list.push(s)
: list.splice(list.indexOf(s), 1);
setFilters(draft => {
return { ...draft, status: list };
});
};
2022-09-01 16:08:37 +02:00
/**
* Filter: by member
*/
const handleSelectMember = (userId: number) => {
setFilters(draft => {
return { ...draft, memberId: userId };
});
};
2022-09-07 18:36:54 +02:00
/**
* Filter: by period
*/
const handlePeriod = () => {
console.log(getValues(['period_from', 'period_to']));
};
2022-08-29 19:15:10 +02:00
/**
* Open/close accordion items
*/
const handleAccordion = (id, state) => {
setAccordion({ ...accordion, [id]: state });
};
return (
<div className='orders'>
<header>
<h2>{t('app.admin.store.orders.heading')}</h2>
2022-09-01 16:08:37 +02:00
{false &&
<div className='grpBtn'>
<FabButton className="main-action-btn" onClick={newOrder}>{t('app.admin.store.orders.create_order')}</FabButton>
</div>
}
2022-08-29 19:15:10 +02:00
</header>
<div className="store-filters">
<header>
<h3>{t('app.admin.store.orders.filter')}</h3>
<div className='grpBtn'>
<FabButton onClick={clearAllFilters} className="is-black">{t('app.admin.store.orders.filter_clear')}</FabButton>
</div>
</header>
<div className="accordion">
<AccordionItem id={0}
isOpen={accordion[0]}
onChange={handleAccordion}
2022-09-01 16:08:37 +02:00
label={t('app.admin.store.orders.filter_ref')}
>
<div className='content'>
<div className="group">
<input type="text" />
<FabButton onClick={applyFilters} className="is-info">{t('app.admin.store.orders.filter_apply')}</FabButton>
</div>
</div>
</AccordionItem>
<AccordionItem id={1}
isOpen={accordion[1]}
onChange={handleAccordion}
2022-08-29 19:15:10 +02:00
label={t('app.admin.store.orders.filter_status')}
>
<div className='content'>
2022-09-01 16:08:37 +02:00
<div className="group u-scrollbar">
2022-08-29 19:15:10 +02:00
{statusOptions.map(s => (
<label key={s.value}>
2022-09-01 16:08:37 +02:00
<input type="checkbox" checked={filters.status.some(o => o.label === s.label)} onChange={(event) => handleSelectStatus(s, event.target.checked)} />
2022-08-29 19:15:10 +02:00
<p>{s.label}</p>
</label>
))}
</div>
<FabButton onClick={applyFilters} className="is-info">{t('app.admin.store.orders.filter_apply')}</FabButton>
</div>
</AccordionItem>
2022-09-01 16:08:37 +02:00
<AccordionItem id={2}
isOpen={accordion[2]}
onChange={handleAccordion}
label={t('app.admin.store.orders.filter_client')}
>
<div className='content'>
<div className="group">
<MemberSelect noHeader onSelected={handleSelectMember} />
<FabButton onClick={applyFilters} className="is-info">{t('app.admin.store.orders.filter_apply')}</FabButton>
</div>
</div>
</AccordionItem>
2022-09-07 18:36:54 +02:00
<AccordionItem id={3}
isOpen={accordion[3]}
onChange={handleAccordion}
label={t('app.admin.store.orders.filter_period')}
>
<div className='content'>
<div className="group">
<div className="period">
from
<FormInput id="period_from"
register={register}
type="date" />
to
<FormInput id="period_to"
register={register}
type="date" />
</div>
<FabButton onClick={handlePeriod} className="is-info">{t('app.admin.store.orders.filter_apply')}</FabButton>
</div>
</div>
</AccordionItem>
2022-08-29 19:15:10 +02:00
</div>
</div>
<div className="store-list">
<StoreListHeader
productsCount={0}
selectOptions={buildOptions()}
onSelectOptionsChange={handleSorting}
/>
2022-09-01 16:08:37 +02:00
<div className="orders-list">
{orders.map(order => (
<OrderItem key={order.id} order={order} currentUser={currentUser} />
))}
2022-09-01 16:08:37 +02:00
</div>
2022-08-29 19:15:10 +02:00
</div>
</div>
);
};
const OrdersWrapper: React.FC<OrdersProps> = (props) => {
return (
<Loader>
<Orders {...props} />
</Loader>
);
};
2022-09-07 15:35:46 +02:00
Application.Components.component('orders', react2angular(OrdersWrapper, ['currentUser', 'onSuccess', 'onError']));
2022-08-29 19:15:10 +02:00
interface Filters {
reference: string,
2022-09-01 16:08:37 +02:00
status: checklistOption[],
2022-09-07 18:36:54 +02:00
memberId: number,
period_from: TDateISODate,
period_to: TDateISODate
2022-08-29 19:15:10 +02:00
}
const initFilters: Filters = {
reference: '',
2022-09-01 16:08:37 +02:00
status: [],
2022-09-07 18:36:54 +02:00
memberId: null,
period_from: null,
period_to: null
2022-08-29 19:15:10 +02:00
};