Retour aux réalisations
CashMag·développeur alternant

Cashmonitor

AmplifyDashboard est un tableau de bord de gestion des terminaux de paiement destiné aux entreprises. Il permet de surveiller et de gérer des terminaux de paiement en assurant le suivi de l'état du matériel, des stocks de caisse, des transactions et des opérations des utilisateurs sur des comptes multi-locataires, grâce à un contrôle d'accès basé sur les rôles et une prise en charge bilingue (anglais/français).

ReactAWS
1 / 3

Composant de recherches réutilisable et système de filtrage centralisé

Mise en place d'une infrastructure de recherche réutilisable à l'échelle de l'application. Celle-ci a permis de remplacer les logiques de filtrage dispersées et redondantes présentes dans chaque module d'administration par un système centralisé composé de trois éléments : un composant générique SearchBar, un module AccountFilteringLogic et un module PaystationFilteringLogic.

Le composant SearchBar est un champ de texte TextField de Material-UI, doté d'icônes de recherche et d'effacement, qui peut être intégré à n'importe quelle vue.

Captures d'écran

Exemple visuel du composant de filtrage

Extraits de code

Composant de recherches réutilisablejsx
const SearchBar = props => {
    const [currentSearch, setCurrentSearch] = useState('');

    const handleChange = event => {
        setCurrentSearch( event.target.value );
        props.onChange( event );
    };

    const handleClear = () => {
        setCurrentSearch( '' );
        props.onClear();
    };

    return (
        <TextField
            id={props.id}
            autoComplete="off"
            value={currentSearch}
            label={props.label}
            variant={props.variant}
            size={props.size}
            InputProps={{
                startAdornment: (
                    <InputAdornment position="start"><Search /></InputAdornment>
                ),
                endAdornment: (
                    <InputAdornment position="end">
                        <IconButton size="small" edge="end" onClick={handleClear}>
                            <Clear fontSize="small" />
                        </IconButton>
                    </InputAdornment>
                ),
            }}
            onChange={handleChange}
        />
    );
};
Logique de filtrage des terminaux de paiementsjavascript
const payStationMatchesFilter = ( payStation, filter, accounts ) => {
    if( ! filter || filter.trim() === '' ) return true;

    const cleanedFilter = sanitizeInput( filter );
    const finder = new PayStationFinder( payStation );
    const terminal = payStation.terminals?.[0] || null;
    const terminalExtraData = finder.buildTerminalExtraData( terminal );
    const reseller = extractReseller( payStation.box );
    const customer = extractCustomer( payStation.box );
    const resellerAccount = accounts?.filter( item => item.code === reseller.code && item.type === RESELLER );
    const customerAccount = accounts?.filter( account => account.code === customer.code && account.type === CUSTOMER );

    const candidates = [
        payStation.informations?.attributes?.name,
        payStation.box?.informations?.attributes?.name,
        resellerAccount?.length > 0 ? sanitizeInput( resellerAccount[0]?.name ) : null,
        customerAccount?.length > 0 ? sanitizeInput( customerAccount[0]?.name ) : null,
        terminalExtraData,
        ...( payStation.devices?.map( device => device?.informations?.identity?.serial ) || [] ),
    ];

    return candidates.filter( Boolean ).some(
        candidate => String( candidate ).toLowerCase().includes( cleanedFilter )
    );
}

const sanitizeInput = input => {
    return input
        .toString()
        .normalize( 'NFD' )
        .replace( /[\u0300-\u036f]/g, '' )           // Strip diacritics
        .replace( /[\u200B\u200C\u200D\uFEFF\u00A0\u202E]/g, '' ) // Remove invisible chars
        .toLowerCase()
        .trim();
}
Logique de filtrage des comptesjavascript
const filterUser = ( list , filter ) => {
    if( ! filter ) return list;
    const cleanedFilter = sanitizeInput( filter );
    const filtered = [];
    if( list && list.length > 0 ) {
        list.forEach( candidate => {
            if( nameMatchesFilter( candidate , cleanedFilter ) ||
                emailMatchesFilter( candidate , cleanedFilter ) ||
                phoneMatchesFilter( candidate , cleanedFilter ) ||
                groupMatchesFilter( candidate , cleanedFilter ) ||
                userIdMatchesFilter( candidate , cleanedFilter ) ) {
                filtered.push( candidate );
            }
        } );
    }
    return filtered;
};

const filterGroups = ( list , filter ) => {
    if( ! filter ) return list;
    const cleanedFilter = sanitizeInput( filter );
    const filtered = [];
    if( list && list.length > 0 ) {
        list.forEach( userGroup => {
            if ( matchesGroupName( userGroup, cleanedFilter ) ||
                 matchesGroupId( userGroup, cleanedFilter ) ||
                 userBelongsToGroup( userGroup, cleanedFilter ) ||
                 userBelongsToSubGroup( userGroup, cleanedFilter ) ||
                 matchesCustomSelection( userGroup, cleanedFilter ) ) {
                filtered.push( userGroup );
            }
        } );
    }
    return filtered;
}