1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-02-17 11:54:22 +01:00

show more results for the payment schedules interface

This commit is contained in:
Sylvain 2021-02-04 15:47:11 +01:00
parent eddf23622d
commit d22d011a10
11 changed files with 152 additions and 46 deletions

View File

@ -0,0 +1,38 @@
/**
* This component is a template for a clickable button that wraps the application style
*/
import React, { ReactNode, SyntheticEvent } from 'react';
interface FabButtonProps {
onClick?: (event: SyntheticEvent) => void,
icon?: ReactNode,
className?: string,
}
export const FabButton: React.FC<FabButtonProps> = ({ onClick, icon, className, children }) => {
/**
* Check if the current component was provided an icon to display
*/
const hasIcon = (): boolean => {
return !!icon;
}
/**
* Handle the action of the button
*/
const handleClick = (e: SyntheticEvent): void => {
if (typeof onClick === 'function') {
onClick(e);
}
}
return (
<button onClick={handleClick} className={`fab-button ${className}`}>
{hasIcon() && <span className="fab-button--icon">{icon}</span>}
{children}
</button>
);
}

View File

@ -10,23 +10,63 @@ import { react2angular } from 'react2angular';
import PaymentScheduleAPI from '../api/payment-schedule';
import { DocumentFilters } from './document-filters';
import { PaymentSchedulesTable } from './payment-schedules-table';
import { FabButton } from './fab-button';
declare var Application: IApplication;
const PAGE_SIZE = 20;
const paymentSchedulesList = PaymentScheduleAPI.list({ query: { page: 1, size: 20 } });
const PaymentSchedulesList: React.FC = () => {
const { t } = useTranslation('admin');
const [paymentSchedules, setPaymentSchedules] = useState(paymentSchedulesList.read());
const [pageNumber, setPageNumber] = useState(1);
const [referenceFilter, setReferenceFilter] = useState(null);
const [customerFilter, setCustomerFilter] = useState(null);
const [dateFilter, setDateFilter] = useState(null);
/**
* Fetch from the API the payments schedules matching the given filters and reset the results table with the new schedules.
*/
const handleFiltersChange = ({ reference, customer, date }): void => {
setReferenceFilter(reference);
setCustomerFilter(customer);
setDateFilter(date);
const api = new PaymentScheduleAPI();
api.list({ query: { reference, customer, date, page: 1, size: 20 }}).then((res) => {
api.list({ query: { reference, customer, date, page: 1, size: PAGE_SIZE }}).then((res) => {
setPaymentSchedules(res);
});
};
/**
* Fetch from the API the next payment schedules to display, for the current filters, and append them to the current results table.
*/
const handleLoadMore = (): void => {
setPageNumber(pageNumber + 1);
const api = new PaymentScheduleAPI();
api.list({ query: { reference: referenceFilter, customer: customerFilter, date: dateFilter, page: pageNumber + 1, size: PAGE_SIZE }}).then((res) => {
const list = paymentSchedules.concat(res);
setPaymentSchedules(list);
});
}
/**
* Check if the current collection of payment schedules is empty or not.
*/
const hasSchedules = (): boolean => {
return paymentSchedules.length > 0;
}
/**
* Check if there are some results for the current filters that aren't currently shown.
*/
const hasMoreSchedules = (): boolean => {
return hasSchedules() && paymentSchedules.length < paymentSchedules[0].max_length;
}
return (
<div className="payment-schedules-list">
<h3>
@ -36,7 +76,11 @@ const PaymentSchedulesList: React.FC = () => {
<div className="schedules-filters">
<DocumentFilters onFilterChange={handleFiltersChange} />
</div>
<PaymentSchedulesTable paymentSchedules={paymentSchedules} showCustomer={true} />
{!hasSchedules() && <div>{t('app.admin.invoices.payment_schedules.no_payment_schedules')}</div>}
{hasSchedules() && <div className="schedules-list">
<PaymentSchedulesTable paymentSchedules={paymentSchedules} showCustomer={true} />
{hasMoreSchedules() && <FabButton className="load-more" onClick={handleLoadMore}>{t('app.admin.invoices.payment_schedules.load_more')}</FabButton>}
</div>}
</div>
);
}

View File

@ -9,6 +9,7 @@ import moment from 'moment';
import { IFablab } from '../models/fablab';
import _ from 'lodash';
import { PaymentSchedule, PaymentScheduleItem, PaymentScheduleItemState } from '../models/payment-schedule';
import { FabButton } from './fab-button';
declare var Fablab: IFablab;
@ -119,24 +120,24 @@ const PaymentSchedulesTableComponent: React.FC<PaymentSchedulesTableProps> = ({
return downloadButton(TargetType.Invoice, item.invoice_id);
case PaymentScheduleItemState.Pending:
return (
<button className="action-button" onClick={handleConfirmCheckPayment(item)}>
<i className="fas fa-money-check" />
<FabButton onClick={handleConfirmCheckPayment(item)}
icon={<i className="fas fa-money-check" />}>
{t('app.admin.invoices.schedules_table.confirm_payment')}
</button>
</FabButton>
);
case PaymentScheduleItemState.RequireAction:
return (
<button className="action-button" onClick={handleSolveAction(item)}>
<i className="fas fa-wrench" />
<FabButton onClick={handleSolveAction(item)}
icon={<i className="fas fa-wrench" />}>
{t('app.admin.invoices.schedules_table.solve')}
</button>
</FabButton>
);
case PaymentScheduleItemState.RequirePaymentMethod:
return (
<button className="action-button" onClick={handleUpdateCard(item)}>
<i className="fas fa-credit-card" />
<FabButton onClick={handleUpdateCard(item)}
icon={<i className="fas fa-credit-card" />}>
{t('app.admin.invoices.schedules_table.update_card')}
</button>
</FabButton>
);
default:
return <span />

View File

@ -27,6 +27,7 @@ export interface PaymentScheduleItem {
}
export interface PaymentSchedule {
max_length: number;
id: number,
scheduled_type: string,
scheduled_id: number,

View File

@ -22,6 +22,7 @@
@import "modules/stripe";
@import "modules/tour";
@import "modules/fab-modal";
@import "modules/fab-button";
@import "modules/payment-schedule-summary";
@import "modules/wallet-info";
@import "modules/stripe-modal";

View File

@ -0,0 +1,39 @@
.fab-button {
color: black;
background-color: #fbfbfb;
display: inline-block;
margin-bottom: 0;
font-weight: normal;
text-align: center;
white-space: nowrap;
vertical-align: middle;
touch-action: manipulation;
cursor: pointer;
background-image: none;
border: 1px solid #c9c9c9;
padding: 6px 12px;
font-size: 16px;
line-height: 1.5;
border-radius: 4px;
user-select: none;
text-decoration: none;
&:hover {
background-color: #f2f2f2;
color: black;
border-color: #aaaaaa;
text-decoration: none;
}
&:active {
color: black;
background-color: #f2f2f2;
border-color: #aaaaaa;
outline: 0;
box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
}
&--icon {
margin-right: 0.5em;
}
}

View File

@ -1,3 +1,11 @@
.schedules-filters {
margin-bottom: 2em;
}
.schedules-list {
text-align: center;
.load-more {
margin-top: 2em;
}
}

View File

@ -99,41 +99,8 @@
}
}
.download-button,
.action-button {
color: black;
background-color: #fbfbfb;
display: inline-block;
margin-bottom: 0;
font-weight: normal;
text-align: center;
white-space: nowrap;
vertical-align: middle;
touch-action: manipulation;
cursor: pointer;
background-image: none;
border: 1px solid #c9c9c9;
padding: 6px 12px;
font-size: 16px;
line-height: 1.5;
border-radius: 4px;
user-select: none;
text-decoration: none;
&:hover {
background-color: #f2f2f2;
color: black;
border-color: #aaaaaa;
text-decoration: none;
}
&:active {
color: black;
background-color: #f2f2f2;
border-color: #aaaaaa;
outline: 0;
box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
}
.download-button {
@extend .fab-button;
& > i {
margin-right: 0.5em;

View File

@ -1,6 +1,9 @@
# frozen_string_literal: true
max_schedules = @payment_schedules.except(:offset, :limit, :order).count
json.array! @payment_schedules do |ps|
json.max_length max_schedules
json.extract! ps, :id, :reference, :created_at, :payment_method
json.total ps.total / 100.00
json.chained_footprint ps.check_footprint

View File

@ -642,6 +642,8 @@ en:
stripe_currency: "Stripe currency"
payment_schedules:
filter_schedules: "Filter schedules"
no_payment_schedules: "No payment schedules to display"
load_more: "Load more"
schedules_table:
schedule_num: "Schedule #"
date: "Date"

View File

@ -642,6 +642,8 @@ fr:
stripe_currency: "Devise Stripe"
payment_schedules:
filter_schedules: "Filtrer les échéanciers"
no_payment_schedules: "Pas d'échéancier à afficher"
load_more: "Voir plus"
schedules_table:
schedule_num: "Échéancier n°"
date: "Date"