From 8d71b4c7e5ee413443a9e4a0621bfcc0c234e865 Mon Sep 17 00:00:00 2001 From: Yaroslav Kosterin Date: Thu, 12 Feb 2026 19:08:32 +0200 Subject: [PATCH 01/19] disable product action if expired for sponsor --- .../FundProviderProductView.tsx | 10 ++++------ .../panes/ProductDetailsBlockPropertiesPane.tsx | 6 +++++- react/src/dashboard/i18n/nl/pages/product.js | 1 + 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/react/src/dashboard/components/pages/fund-provider-product-view/FundProviderProductView.tsx b/react/src/dashboard/components/pages/fund-provider-product-view/FundProviderProductView.tsx index 050b18592..048dda1ec 100644 --- a/react/src/dashboard/components/pages/fund-provider-product-view/FundProviderProductView.tsx +++ b/react/src/dashboard/components/pages/fund-provider-product-view/FundProviderProductView.tsx @@ -274,15 +274,13 @@ export default function FundProviderProductView() { )} ) : ( - { - e?.preventDefault(); - editProduct(fund, fundProvider, product).then(setFundProvider); - }}> + disabled={product.expired} + onClick={() => editProduct(fund, fundProvider, product).then(setFundProvider)}> {translate('product.buttons.approve_product')} - + )} )} diff --git a/react/src/dashboard/components/pages/products-view/elements/panes/ProductDetailsBlockPropertiesPane.tsx b/react/src/dashboard/components/pages/products-view/elements/panes/ProductDetailsBlockPropertiesPane.tsx index 08b6796a4..1e06001d3 100644 --- a/react/src/dashboard/components/pages/products-view/elements/panes/ProductDetailsBlockPropertiesPane.tsx +++ b/react/src/dashboard/components/pages/products-view/elements/panes/ProductDetailsBlockPropertiesPane.tsx @@ -8,6 +8,7 @@ import StateNavLink from '../../../../../modules/state_router/StateNavLink'; import classNames from 'classnames'; import FormPane from '../../../../elements/forms/elements/FormPane'; import { DashboardRoutes } from '../../../../../modules/state_router/RouterBuilder'; +import Label from '../../../../elements/image_cropper/Label'; export default function ProductDetailsBlockPropertiesPane({ title = null, @@ -52,7 +53,10 @@ export default function ProductDetailsBlockPropertiesPane({ )} - {product.expire_at ? product.expire_at_locale : 'Onbeperkt'} + + {product.expire_at ? product.expire_at_locale : 'Onbeperkt'} + {product.expired && } + {showStockAndReservations && ( diff --git a/react/src/dashboard/i18n/nl/pages/product.js b/react/src/dashboard/i18n/nl/pages/product.js index f05fea3e2..54a1aa23c 100644 --- a/react/src/dashboard/i18n/nl/pages/product.js +++ b/react/src/dashboard/i18n/nl/pages/product.js @@ -16,6 +16,7 @@ export default { ean_placeholder: 'Voeg een Europees artikelnummer toe', sku: 'SKU', sku_placeholder: 'Voeg een voorraadbeheereenheidnummer toe', + expired: 'Verlopen', }, tooltips: { ean: [ From 3f045a2edbe42eb815f8becde5a160c74af6b2af Mon Sep 17 00:00:00 2001 From: Yaroslav Kosterin Date: Thu, 12 Feb 2026 19:11:04 +0200 Subject: [PATCH 02/19] fix fund query filter in view all products on voucher page --- .../components/pages/vouchers-show/elements/VoucherActions.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/react/src/webshop/components/pages/vouchers-show/elements/VoucherActions.tsx b/react/src/webshop/components/pages/vouchers-show/elements/VoucherActions.tsx index 9ec454536..5f520ec03 100644 --- a/react/src/webshop/components/pages/vouchers-show/elements/VoucherActions.tsx +++ b/react/src/webshop/components/pages/vouchers-show/elements/VoucherActions.tsx @@ -183,7 +183,7 @@ export default function VoucherActions({ + query={{ fund_ids: [voucher.fund_id] }}> {translate('voucher.actions.view_all_products')} From 36cf0ecdd8dc141015da7fa307e21ff717254b00 Mon Sep 17 00:00:00 2001 From: Yaroslav Kosterin Date: Fri, 13 Feb 2026 15:29:51 +0200 Subject: [PATCH 03/19] show duplicates by csv primary key when upload prevalidation batch --- .../modals/ModalPrevalidationsUpload.tsx | 89 +++++++++++++++++-- 1 file changed, 83 insertions(+), 6 deletions(-) diff --git a/react/src/dashboard/components/modals/ModalPrevalidationsUpload.tsx b/react/src/dashboard/components/modals/ModalPrevalidationsUpload.tsx index 56dd8033d..f0ec6e839 100644 --- a/react/src/dashboard/components/modals/ModalPrevalidationsUpload.tsx +++ b/react/src/dashboard/components/modals/ModalPrevalidationsUpload.tsx @@ -766,6 +766,81 @@ export default function ModalPrevalidationsUpload({ ], ); + const showDuplicateRows = useCallback( + (rows = []) => { + const message = [ + `${rows.length} van ${data.length}`, + 'rij(en) uit het bulkbestand zijn niet', + 'geïmporteerd vanwege dubbele waarden.', + 'Bekijk het bestand bij welke rij(en) het mis gaat.', + ].join(' '); + + pushDanger('Waarschuwing', message); + setHideModal(true); + + openModal((modal) => ( + { + reset(); + setHideModal(false); + }} + onCancel={() => { + reset(); + setHideModal(false); + }} + /> + )); + }, + [data, openModal, pushDanger, reset], + ); + + const checkDuplicates = useCallback(() => { + return new Promise((resolve, reject) => { + const submitData: RowDataPropData[] = JSON.parse(JSON.stringify(data)); + const keyMap = new Map(); + const duplicates = []; + + submitData.forEach((item, index) => { + const primary_key = item?.[fund.csv_primary_key]; + + if (!primary_key) { + return; + } + + if (!keyMap.has(primary_key)) { + keyMap.set(primary_key, [index]); + } else { + keyMap.get(primary_key).push(index); + } + }); + + keyMap.forEach((indexes, primary_key) => { + if (indexes.length > 1) { + indexes.forEach((i) => { + duplicates.push({ + value: `Rij: ${i + 1}: ${fund?.csv_primary_key} - ${primary_key}`, + _uid: uniqueId('rand_'), + }); + }); + } + }); + + if (duplicates.length) { + showDuplicateRows(duplicates); + reject(); + } + + resolve(true); + }); + }, [data, fund?.csv_primary_key, showDuplicateRows]); + const submitCollectionCheck = useCallback(() => { setCsvProgress(CSVProgress.uploading); abortRef.current = false; @@ -854,14 +929,16 @@ export default function ModalPrevalidationsUpload({ ]); const onConfirmUpload = useCallback(() => { - setCsvComparing(true); + checkDuplicates().then(() => { + setCsvComparing(true); - pushSuccess('Inladen...', 'Inladen van gegevens voor controle op dubbele waarden!', { - icon: 'download-outline', - }); + pushSuccess('Inladen...', 'Inladen van gegevens voor controle op dubbele waarden!', { + icon: 'download-outline', + }); - submitCollectionCheck(); - }, [pushSuccess, submitCollectionCheck]); + submitCollectionCheck(); + }, console.error); + }, [checkDuplicates, pushSuccess, submitCollectionCheck]); const onDragEvent = useCallback((e: React.DragEvent, isDragOver: boolean) => { e?.preventDefault(); From 6662ffd86d7c2808cda27ffdd7204704c97c5706 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 14 Feb 2026 12:52:39 +0000 Subject: [PATCH 04/19] Bump qs in the npm_and_yarn group across 1 directory Bumps the npm_and_yarn group with 1 update in the / directory: [qs](https://github.com/ljharb/qs). Updates `qs` from 6.14.1 to 6.14.2 - [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md) - [Commits](https://github.com/ljharb/qs/compare/v6.14.1...v6.14.2) --- updated-dependencies: - dependency-name: qs dependency-version: 6.14.2 dependency-type: indirect dependency-group: npm_and_yarn ... Signed-off-by: dependabot[bot] --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index ff48229b1..80f2fe463 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11052,9 +11052,9 @@ } }, "node_modules/qs": { - "version": "6.14.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", - "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", "dev": true, "license": "BSD-3-Clause", "dependencies": { From 9c90dd77a423c1ba8c64899d68c0a72257c3d349 Mon Sep 17 00:00:00 2001 From: dev-rminds Date: Tue, 17 Feb 2026 08:12:58 +0200 Subject: [PATCH 05/19] add Label component on webshop and dashboards and cleanup unused label variants --- .eslintrc.js | 1 + .../scss/_common/includes/common.scss | 6 +- .../includes/blocks/block-fund-request.scss | 10 +-- .../scss/includes/components/_label.scss | 10 +-- .../forms/controls/MultiSelectControl.tsx | 10 ++- .../components/elements/label/Label.tsx | 62 ++++++++++++++ .../resource-states/FundFormStateLabels.tsx | 6 +- .../resource-states/FundRequestStateLabel.tsx | 81 ++++++------------- .../resource-states/FundStateLabels.tsx | 8 +- .../PrevalidationRequestStateLabels.tsx | 8 +- .../ReimbursementStateLabel.tsx | 10 +-- .../resource-states/ReservationStateLabel.tsx | 6 +- .../resource-states/TransactionStateLabel.tsx | 2 +- .../components/modals/ModalFundOffers.tsx | 2 +- .../bank-connections/BankConnections.tsx | 2 +- .../elements/FinancialFilters.tsx | 16 ++-- .../pages/fund-provider/FundProvider.tsx | 2 +- .../elements/FundProviderProductRowData.tsx | 4 +- .../elements/FundRequestGroupRecordRow.tsx | 2 +- .../FundRequestRecordsHasClarifications.tsx | 2 +- .../PreferencesEmails.tsx | 6 +- .../pages/identity-security/Security2FA.tsx | 2 +- .../identity-security/SecuritySessions.tsx | 4 +- .../ImplementationNotifications.tsx | 10 +-- .../elements/SystemNotificationEditor.tsx | 26 ++---- .../ImplementationCookies.tsx | 2 +- ...anizationsFundsShowImplementationsCard.tsx | 2 +- .../pages/payment-methods/PaymentMethods.tsx | 2 +- .../PrevalidationRequests.tsx | 27 +++++-- .../pages/prevalidations/Prevalidations.tsx | 26 +++--- .../pages/products-view/ProductView.tsx | 2 +- .../elements/ProviderFundInvitationsTable.tsx | 2 +- .../elements/ProviderFundsTable.tsx | 4 +- .../elements/ReimbursementsTable.tsx | 2 +- .../ReservationExtraPaymentRefundsCard.tsx | 2 +- .../ReservationExtraPaymentDetailsPane.tsx | 2 +- .../ProductMonitoredHistoryCardFunds.tsx | 2 +- .../elements/FundProviderTableItem.tsx | 21 ++--- .../elements/ProvidersTableItemFunds.tsx | 24 +++--- .../TransactionBulksView.tsx | 2 +- .../TransactionBulkTransactionsTable.tsx | 2 +- .../elements/TransactionBulksTableSection.tsx | 2 +- .../elements/TransactionsTableSection.tsx | 2 +- .../vouchers-view/VouchersViewComponent.tsx | 2 +- .../elements/VoucherTransactionsCard.tsx | 2 +- .../elements/cms-blocks/CmsBlocksItem.tsx | 7 +- .../elements/cms-blocks/CmsBlocksItemLink.tsx | 7 +- .../components/elements/label}/Label.tsx | 42 +++++----- .../templates/FundsListItemList.tsx | 21 ++--- .../templates/FundsListItemSearch.tsx | 9 +-- .../templates/ProvidersListItemList.tsx | 5 +- .../fund-requests-show/FundRequestsShow.tsx | 23 +++--- .../FundRequestClarificationsBlock.tsx | 5 +- .../elements/FundRequestRecordsBlockItem.tsx | 13 +-- .../elements/FundRequestCard.tsx | 32 +++----- .../webshop/components/pages/home/Home.tsx | 3 +- .../identity-emails/PreferencesEmails.tsx | 15 ++-- .../pages/identity-security/Security2FA.tsx | 9 +-- .../identity-security/SecuritySessions.tsx | 9 ++- .../payouts/elements/PayoutCardLabel.tsx | 7 +- .../providers-office/ProvidersOffice.tsx | 9 ++- .../pages/providers-show/ProvidersShow.tsx | 9 ++- .../elements/ReimbursementCard.tsx | 21 ++--- .../reservations-show/ReservationsShow.tsx | 53 ++++-------- .../reservations/elements/ReservationCard.tsx | 21 ++--- .../hooks/useComposeStateAndExpires.tsx | 5 +- .../pages/vouchers-show/VouchersShow.tsx | 10 +-- .../pages/vouchers/elements/VoucherCard.tsx | 12 ++- 68 files changed, 383 insertions(+), 394 deletions(-) create mode 100644 react/src/dashboard/components/elements/label/Label.tsx rename react/src/{dashboard/components/elements/image_cropper => webshop/components/elements/label}/Label.tsx (54%) diff --git a/.eslintrc.js b/.eslintrc.js index e092237b8..a5a6ff767 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -26,6 +26,7 @@ module.exports = { plugins: ['no-for-of-loops', 'no-function-declare-after-return', 'react', 'react-hooks', 'prettier'], rules: { // ... + // 'react/jsx-curly-brace-presence': ['error', { props: 'never', children: 'never' }], 'react-hooks/rules-of-hooks': 'error', // Checks rules of Hooks 'react-hooks/exhaustive-deps': 'warn', // Checks effect dependencies 'react/react-in-jsx-scope': 'off', diff --git a/react/assets/forus-platform/scss/_common/includes/common.scss b/react/assets/forus-platform/scss/_common/includes/common.scss index 5340feb92..935667024 100644 --- a/react/assets/forus-platform/scss/_common/includes/common.scss +++ b/react/assets/forus-platform/scss/_common/includes/common.scss @@ -150,10 +150,6 @@ img { transition: color 0.3s; } -.transition-background { - transition: background-color 0.3s; -} - .text-black { color: #000000; } @@ -1579,4 +1575,4 @@ img { } } } -} \ No newline at end of file +} diff --git a/react/assets/forus-webshop/scss/includes/blocks/block-fund-request.scss b/react/assets/forus-webshop/scss/includes/blocks/block-fund-request.scss index ed1080c22..546af94f9 100644 --- a/react/assets/forus-webshop/scss/includes/blocks/block-fund-request.scss +++ b/react/assets/forus-webshop/scss/includes/blocks/block-fund-request.scss @@ -96,14 +96,8 @@ } } - .label { - &:not(:last-child):not(:last-of-type) { - margin: 0; - } - - .label-text { - display: inline-block; - } + .label:not(:last-child):not(:last-of-type) { + margin: 0; } &:last-child { diff --git a/react/assets/forus-webshop/scss/includes/components/_label.scss b/react/assets/forus-webshop/scss/includes/components/_label.scss index 4205ca465..47f98536f 100644 --- a/react/assets/forus-webshop/scss/includes/components/_label.scss +++ b/react/assets/forus-webshop/scss/includes/components/_label.scss @@ -36,14 +36,6 @@ } } - .label-close { - color: #fff; - float: left; - font-size: 14px; - margin: 0 2.5px 0 -2.5px; - cursor: pointer; - } - &.label-success { color: var(--label-success-color); background: var(--label-success-background); @@ -109,4 +101,4 @@ border-radius: calc(var(--border-radius) / 2); } } -} \ No newline at end of file +} diff --git a/react/src/dashboard/components/elements/forms/controls/MultiSelectControl.tsx b/react/src/dashboard/components/elements/forms/controls/MultiSelectControl.tsx index 087ec0b6a..3b2236e08 100644 --- a/react/src/dashboard/components/elements/forms/controls/MultiSelectControl.tsx +++ b/react/src/dashboard/components/elements/forms/controls/MultiSelectControl.tsx @@ -1,7 +1,7 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { uniq, uniqueId } from 'lodash'; import SelectControl from '../../select-control/SelectControl'; -import Label from '../../image_cropper/Label'; +import Label from '../../label/Label'; export default function MultiSelectControl({ id = uniqueId('multiselect_'), @@ -70,9 +70,13 @@ export default function MultiSelectControl({ {value?.map((id) => ( -