From 1bf54c35443ea995ace076fb28560d78668a8318 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Wed, 22 Oct 2025 11:19:13 +0200 Subject: [PATCH 01/16] feat: add translations for "Expired Earnings" and "Payment History" in Italian --- src/locales/en/translation.json | 2 ++ src/locales/es/translation.json | 2 ++ src/locales/fr/translation.json | 2 ++ src/locales/it/translation.json | 2 ++ 4 files changed, 8 insertions(+) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 5e60fbf4..3794bd50 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -683,6 +683,8 @@ "__WALLET_CARD-REQUEST_DISCLAIMER-PROCESSING MAX: 150": "You can request only one payment at a time: you alreay have a payment in process, this may take up to 20 working days.", "__WALLET_CARD-REQUEST_TITLE MAX: 40": "Manage your payment", "__WALLET_CARD-YOUR_WALLET_MAX: 15": "Your wallet", + "__WALLET_EXPIRED_TAB": "", + "__WALLET_HISTORY_TAB": "", "__WALLET_HOME-EMPTY_STATE_MAX: 105": "Your payment history is now empty. When you start requesting your payments, you will view them here.", "__WALLET_TABLE-HEADER_CTA-ICON-DETAILS MAX:": "View details", "__WALLET_TABLE-HEADER_CTA-ICON-PDF MAX:": "Download receipt", diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index e6c67456..d0a0c39f 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -683,6 +683,8 @@ "__WALLET_CARD-REQUEST_DISCLAIMER-PROCESSING MAX: 150": "Solo puedes solicitar un pago a la vez: ya tienes una solicitud pendiente, ésta puede tardar hasta 20 días laborables.", "__WALLET_CARD-REQUEST_TITLE MAX: 40": "Gestiona el pago", "__WALLET_CARD-YOUR_WALLET_MAX: 15": "Tu monedero", + "__WALLET_EXPIRED_TAB": "", + "__WALLET_HISTORY_TAB": "", "__WALLET_HOME-EMPTY_STATE_MAX: 105": "Aún no has solicitado ningun pago. Cuando lo harás, podrás ver tus pagos aquí.", "__WALLET_TABLE-HEADER_CTA-ICON-DETAILS MAX:": "Ver detalles", "__WALLET_TABLE-HEADER_CTA-ICON-PDF MAX:": "Descargar recibo", diff --git a/src/locales/fr/translation.json b/src/locales/fr/translation.json index b44b5483..15b52785 100644 --- a/src/locales/fr/translation.json +++ b/src/locales/fr/translation.json @@ -683,6 +683,8 @@ "__WALLET_CARD-REQUEST_DISCLAIMER-PROCESSING MAX: 150": "Vous ne pouvez demander qu'un paiement à la fois : vous avez déjà un paiement en cours, cela peut prendre jusqu'à 20 jours ouvrables.", "__WALLET_CARD-REQUEST_TITLE MAX: 40": "Gérez votre paiement", "__WALLET_CARD-YOUR_WALLET_MAX: 15": "Votre portefeuille", + "__WALLET_EXPIRED_TAB": "", + "__WALLET_HISTORY_TAB": "", "__WALLET_HOME-EMPTY_STATE_MAX: 105": "Votre historique de paiement est actuellement vide. Lorsque vous commencerez à demander vos paiements, vous les verrez ici.", "__WALLET_TABLE-HEADER_CTA-ICON-DETAILS MAX:": "Voir les détails", "__WALLET_TABLE-HEADER_CTA-ICON-PDF MAX:": "Télécharger le reçu", diff --git a/src/locales/it/translation.json b/src/locales/it/translation.json index e183c5fe..91b4c5db 100644 --- a/src/locales/it/translation.json +++ b/src/locales/it/translation.json @@ -683,6 +683,8 @@ "__WALLET_CARD-REQUEST_DISCLAIMER-PROCESSING MAX: 150": "Puoi richiedere solo un pagamento alla volta: hai già una richiesta in lavorazione, la procedura può durare fino a 20 giorni lavorativi.", "__WALLET_CARD-REQUEST_TITLE MAX: 40": "Gestisci il pagamento", "__WALLET_CARD-YOUR_WALLET_MAX: 15": "Il tuo portafoglio", + "__WALLET_EXPIRED_TAB": "Guadagni scaduti", + "__WALLET_HISTORY_TAB": "Cronologia pagamenti", "__WALLET_HOME-EMPTY_STATE_MAX: 105": "Per ora non hai ancora richiesto un pagamento. Quando inizierai a richiederne, compariranno qui.", "__WALLET_TABLE-HEADER_CTA-ICON-DETAILS MAX:": "Vedi dettagli", "__WALLET_TABLE-HEADER_CTA-ICON-PDF MAX:": "Scarica ricevuta", From b473fc51f071bebeafca08c8ec8d0d46c797d3e8 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Wed, 22 Oct 2025 11:19:37 +0200 Subject: [PATCH 02/16] feat: implement useTabFragment hook for managing active tab state --- src/pages/Wallet/WalletTabFragment.tsx | 28 ++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/pages/Wallet/WalletTabFragment.tsx diff --git a/src/pages/Wallet/WalletTabFragment.tsx b/src/pages/Wallet/WalletTabFragment.tsx new file mode 100644 index 00000000..51b7e72a --- /dev/null +++ b/src/pages/Wallet/WalletTabFragment.tsx @@ -0,0 +1,28 @@ +import { useEffect, useState } from "react"; + +const useTabFragment = () => { + const urlParams = new URLSearchParams(window.location.search); + const tabParam = urlParams.get("tab") || "history"; + const currentTab = ["history", "expired"].includes(tabParam) + ? tabParam + : "history"; + + const [activeTab, setActiveTab] = useState(currentTab); + + useEffect(() => { + const currentParams = new URLSearchParams(window.location.search); + currentParams.set("tab", activeTab); + window.history.pushState( + {}, + "", + window.location.origin + + window.location.pathname + + "?" + + currentParams.toString() + ); + }, [activeTab]); + + return { activeTab, setActiveTab }; +}; + +export default useTabFragment; From 5682e1945d7419fa9bc27fef09f90653b21b603a Mon Sep 17 00:00:00 2001 From: Kariamos Date: Wed, 22 Oct 2025 11:20:01 +0200 Subject: [PATCH 03/16] feat: add tabbed interface for wallet history and expired payments --- src/pages/Wallet/WalletTable.tsx | 83 ++++++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 21 deletions(-) diff --git a/src/pages/Wallet/WalletTable.tsx b/src/pages/Wallet/WalletTable.tsx index 4f144105..5d706918 100644 --- a/src/pages/Wallet/WalletTable.tsx +++ b/src/pages/Wallet/WalletTable.tsx @@ -1,8 +1,10 @@ import { Pagination, SortTableSelect, + Tab, Table, TableType, + Tabs, } from "@appquality/appquality-design-system"; import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; @@ -21,6 +23,7 @@ import { openPaymentDetailsModal } from "src/redux/wallet/actions/openPaymentDet import { currencyTable, getPaidDate } from "src/redux/wallet/utils"; import { useGetUsersMePaymentsQuery } from "src/services/tryberApi"; import styled from "styled-components"; +import useTabFragment from "src/pages/Wallet/WalletTabFragment"; const ActionsCell = styled.div` display: flex; @@ -100,6 +103,7 @@ export const WalletTable = () => { const dispatch = useAppDispatch(); const [columns, setcolumns] = useState([]); const [rows, setRows] = useState([]); + const { activeTab, setActiveTab } = useTabFragment(); const { requestsList } = useSelector( (state: GeneralState) => state.wallet, @@ -228,27 +232,64 @@ export const WalletTable = () => { }; return ( <> - {columns.length > 0 && ( - - )} - + + {t("__WALLET_HISTORY_TAB")} + } + > + {columns.length > 0 && ( + + )} +
+ + {t("__WALLET_EXPIRED_TAB")} + } + > + {columns.length > 0 && ( + + )} +
+ + Date: Wed, 22 Oct 2025 16:18:07 +0200 Subject: [PATCH 04/16] feat: add expired tab columns for wallet with sortable options --- src/locales/en/translation.json | 4 +++ src/locales/es/translation.json | 4 +++ src/locales/fr/translation.json | 4 +++ src/locales/it/translation.json | 4 +++ src/pages/Wallet/expiredTabColumns.ts | 51 +++++++++++++++++++++++++++ 5 files changed, 67 insertions(+) create mode 100644 src/pages/Wallet/expiredTabColumns.ts diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 3794bd50..315268ac 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -216,6 +216,7 @@ "SignupFrom Step1": "Date of birth" }, "Dashboard": "Dashboard", + "Data attribuzione": "", "Date": "Date", "Delete": "Delete", "Delete account": "Delete account", @@ -244,6 +245,7 @@ "Employment": "Employment", "End Date": "End Date", "Experience Points": "Experience Points", + "Expired On": "", "Extra Award": "Extra Award", "FAQ": "FAQ", "Facebook": "Facebook", @@ -538,10 +540,12 @@ "This is an invalid format. Should be formatted as +11000000000 or 0011000000000": "This is an invalid format. Should be formatted as +11000000000 or 0011000000000", "This is your personal dashboard. From here you can check out your stats, keep an eye on the progress of your work and find new campaigns to apply for. Have fun!": "This is your personal dashboard. From here you can check out your stats, keep an eye on the progress of your work and find new campaigns to apply for. Have fun!", "This value is invalid, you need to select a city with a province": "This value is invalid, you need to select a city with a province", + "Tipo attività": "", "Title": "Title", "Top 3 | level {{level}}": { "__RANKING_TITLE_LABEL_TOP_LEVEL_MAX: 25": "Top 3 | {{level}} level" }, + "Tot. lordo": "", "Try again.": "Try again.", "Type": "Type", "Type to search your city": "Type to search your city", diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index d0a0c39f..45c5e00e 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -216,6 +216,7 @@ "SignupFrom Step1": "Fecha de nacimiento" }, "Dashboard": "Dashboard", + "Data attribuzione": "", "Date": "Fecha", "Delete": "Eliminar", "Delete account": "Elímina account", @@ -244,6 +245,7 @@ "Employment": "Empleo", "End Date": "Fecha Final", "Experience Points": "Puntos de Experiencia", + "Expired On": "", "Extra Award": "Recompensa Extra", "FAQ": "Preguntas Frecuentes", "Facebook": "Facebook", @@ -538,10 +540,12 @@ "This is an invalid format. Should be formatted as +11000000000 or 0011000000000": "Este es un formato no válido. Tiene que ser formateado como +11000000000 o 0011000000000", "This is your personal dashboard. From here you can check out your stats, keep an eye on the progress of your work and find new campaigns to apply for. Have fun!": "Este es tu dashboard personal. Desde aquí puedes consultar tus estadísticas, el progreso de tu trabajo y encontrar nuevas Campañas a las que postularte. ¡Diviértete!", "This value is invalid, you need to select a city with a province": "Este valor no es válido, es necesario seleccionar una ciudad con una provincia", + "Tipo attività": "", "Title": "Título", "Top 3 | level {{level}}": { "__RANKING_TITLE_LABEL_TOP_LEVEL_MAX: 25": "Top 3 | Nivel {{level}}" }, + "Tot. lordo": "", "Try again.": "Inténtelo de nuevo.", "Type": "Tipo", "Type to search your city": "Escriba para buscar tu ciudad", diff --git a/src/locales/fr/translation.json b/src/locales/fr/translation.json index 15b52785..768de788 100644 --- a/src/locales/fr/translation.json +++ b/src/locales/fr/translation.json @@ -216,6 +216,7 @@ "SignupFrom Step1": "Date de naissance" }, "Dashboard": "Tableau de bord", + "Data attribuzione": "", "Date": "Date", "Delete": "Supprimer", "Delete account": "Supprimer le compte", @@ -244,6 +245,7 @@ "Employment": "Emploi", "End Date": "Date de fin", "Experience Points": "Points d'expérience", + "Expired On": "", "Extra Award": "Récompense supplémentaire", "FAQ": "FAQ", "Facebook": "Facebook", @@ -538,10 +540,12 @@ "This is an invalid format. Should be formatted as +11000000000 or 0011000000000": "Ce format est invalide. Il doit être formaté comme +11000000000 ou 0011000000000", "This is your personal dashboard. From here you can check out your stats, keep an eye on the progress of your work and find new campaigns to apply for. Have fun!": "Ceci est votre tableau de bord personnel. D'ici, vous pouvez consulter vos statistiques, surveiller l'avancement de votre travail et trouver de nouvelles campagnes pour lesquelles postuler. Amusez-vous bien !", "This value is invalid, you need to select a city with a province": "Cette valeur est invalide, vous devez sélectionner une ville avec une province", + "Tipo attività": "", "Title": "Titre", "Top 3 | level {{level}}": { "__RANKING_TITLE_LABEL_TOP_LEVEL_MAX: 25": "Top 3 | niveau {{level}}" }, + "Tot. lordo": "", "Try again.": "Réessayez.", "Type": "Type", "Type to search your city": "Tapez pour rechercher votre ville", diff --git a/src/locales/it/translation.json b/src/locales/it/translation.json index 91b4c5db..43c06761 100644 --- a/src/locales/it/translation.json +++ b/src/locales/it/translation.json @@ -216,6 +216,7 @@ "SignupFrom Step1": "Data di nascita" }, "Dashboard": "Dashboard", + "Data attribuzione": "", "Date": "Data", "Delete": "Rimuovi", "Delete account": "Elimina account", @@ -244,6 +245,7 @@ "Employment": "Occupazione", "End Date": "Fine", "Experience Points": "Punti esperienza", + "Expired On": "", "Extra Award": "Premio extra", "FAQ": "Domande frequenti", "Facebook": "Facebook", @@ -538,10 +540,12 @@ "This is an invalid format. Should be formatted as +11000000000 or 0011000000000": "Formato invalido. Deve essere formattato come +11000000000 o 0011000000000", "This is your personal dashboard. From here you can check out your stats, keep an eye on the progress of your work and find new campaigns to apply for. Have fun!": "Questa è la tua dashboard personale. Da qui puoi controllare le tue statistiche, tenere d'occhio lo stato di avanzamento del tuo lavoro e trovare nuove campagne a cui candidarti. Divertiti!", "This value is invalid, you need to select a city with a province": "Questo valore è invalido, devi selezionare una città con una provincia", + "Tipo attività": "", "Title": "Titolo", "Top 3 | level {{level}}": { "__RANKING_TITLE_LABEL_TOP_LEVEL_MAX: 25": "Top 3 | Livello {{level}}" }, + "Tot. lordo": "", "Try again.": "Riprova", "Type": "Tipo", "Type to search your city": "Digita per cercare la tua città", diff --git a/src/pages/Wallet/expiredTabColumns.ts b/src/pages/Wallet/expiredTabColumns.ts new file mode 100644 index 00000000..19baa4c6 --- /dev/null +++ b/src/pages/Wallet/expiredTabColumns.ts @@ -0,0 +1,51 @@ +import { Column } from "@appquality/appquality-design-system/dist/stories/table/_types"; +import { TFunction } from "react-i18next"; +import { updateSortingOptions } from "src/redux/wallet/actionCreator"; + +export const expiredTabColumns = ( + dispatch: AppDispatch, + t: TFunction<"translation"> +): Column[] => { + return [ + { + title: "Nome attività", + dataIndex: "activityName", + key: "activityName", + maxWidth: "max-content", + }, + { + title: t("Tipo attività"), + dataIndex: "activityType", + key: "activityType", + role: "overline", + hideIndex: true, + }, + { + title: t("Data attribuzione"), + dataIndex: "attributionDate", + key: "attributionDate", + isSortable: true, + onSort: (newOrder) => { + // dispatch(updateSortingOptions(newOrder, "attributionDate")); + }, + }, + { + title: t("Tot. lordo"), + dataIndex: "gross", + key: "gross", + isSortable: true, + onSort: (newOrder) => { + dispatch(updateSortingOptions(newOrder, "gross")); + }, + }, + { + title: t("Expired On"), + dataIndex: "expiredDate", + key: "expiredDate", + isSortable: true, + onSort: (newOrder: OrderType) => { + // dispatch(updateSortingOptions(newOrder, "expiredDate")); + }, + }, + ]; +}; From 8d3a2e19e1f38f67fba24adbc1b5b987694a1480 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Wed, 22 Oct 2025 16:25:20 +0200 Subject: [PATCH 05/16] wip: implement expired tab --- src/pages/Wallet/WalletTable.tsx | 36 ++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/pages/Wallet/WalletTable.tsx b/src/pages/Wallet/WalletTable.tsx index 5d706918..35e6b5d7 100644 --- a/src/pages/Wallet/WalletTable.tsx +++ b/src/pages/Wallet/WalletTable.tsx @@ -21,9 +21,13 @@ import { useAppDispatch } from "src/redux/provider"; import { updatePagination } from "src/redux/wallet/actionCreator"; import { openPaymentDetailsModal } from "src/redux/wallet/actions/openPaymentDetailsModal"; import { currencyTable, getPaidDate } from "src/redux/wallet/utils"; -import { useGetUsersMePaymentsQuery } from "src/services/tryberApi"; +import { + useGetUsersMePaymentsQuery, + useGetUsersMePendingBootyQuery, +} from "src/services/tryberApi"; import styled from "styled-components"; import useTabFragment from "src/pages/Wallet/WalletTabFragment"; +import { expiredTabColumns } from "./expiredTabColumns"; const ActionsCell = styled.div` display: flex; @@ -102,7 +106,11 @@ export const WalletTable = () => { const { t } = useTranslation(); const dispatch = useAppDispatch(); const [columns, setcolumns] = useState([]); + const [expiredColumns, setExpiredColumns] = useState([]); + const [rows, setRows] = useState([]); + const [expiredRows, setExpiredRows] = useState([]); + const { activeTab, setActiveTab } = useTabFragment(); const { requestsList } = useSelector( @@ -116,10 +124,15 @@ export const WalletTable = () => { order, orderBy, }); + + const { data: expiredBootyData, isLoading: isExpiredBootyLoading } = + useGetUsersMePendingBootyQuery({ filterBy: { isExpired: 0 } }); // initial requests useEffect(() => { const cols = walletColumns(dispatch, t); setcolumns(cols); + const expiredCols = expiredTabColumns(dispatch, t); + setExpiredColumns(expiredCols); }, []); // update datasource for the table useEffect(() => { @@ -226,6 +239,21 @@ export const WalletTable = () => { ); } }, [data]); + + /* useEffect(() => { + if (typeof expiredBootyData?.results !== "undefined") { + setExpiredRows( + expiredBootyData.results.map((req) => { + return { + activity: req.activity, + amount: req.amount.gross.value, + attributionDate: req.attributionDate, + name: req.name, + }; + }) + ); + } + }, [data]); */ const changePagination = (newPage: number) => { const newStart = limit * (newPage - 1); dispatch(updatePagination(newStart)); @@ -271,14 +299,14 @@ export const WalletTable = () => { )}
Date: Thu, 23 Oct 2025 12:13:01 +0200 Subject: [PATCH 06/16] Implement code structure updates and remove redundant sections --- src/locales/en/translation.json | 1 + src/locales/es/translation.json | 1 + src/locales/fr/translation.json | 1 + src/locales/it/translation.json | 1 + .../BootyDetailsModal/BootyDetailsModal.tsx | 7 + src/pages/Wallet/BootyDetailsModal/columns.ts | 6 + src/pages/Wallet/WalletTable.tsx | 42 +- src/services/tryberApi/index.ts | 4 + src/utils/schema.ts | 3749 ++++++++++------- 9 files changed, 2336 insertions(+), 1476 deletions(-) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 315268ac..08a1e450 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -245,6 +245,7 @@ "Employment": "Employment", "End Date": "End Date", "Experience Points": "Experience Points", + "Expiration date": "", "Expired On": "", "Extra Award": "Extra Award", "FAQ": "FAQ", diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index 45c5e00e..b10e4fbf 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -245,6 +245,7 @@ "Employment": "Empleo", "End Date": "Fecha Final", "Experience Points": "Puntos de Experiencia", + "Expiration date": "", "Expired On": "", "Extra Award": "Recompensa Extra", "FAQ": "Preguntas Frecuentes", diff --git a/src/locales/fr/translation.json b/src/locales/fr/translation.json index 768de788..20ef7be8 100644 --- a/src/locales/fr/translation.json +++ b/src/locales/fr/translation.json @@ -245,6 +245,7 @@ "Employment": "Emploi", "End Date": "Date de fin", "Experience Points": "Points d'expérience", + "Expiration date": "", "Expired On": "", "Extra Award": "Récompense supplémentaire", "FAQ": "FAQ", diff --git a/src/locales/it/translation.json b/src/locales/it/translation.json index 43c06761..6fdf07b2 100644 --- a/src/locales/it/translation.json +++ b/src/locales/it/translation.json @@ -245,6 +245,7 @@ "Employment": "Occupazione", "End Date": "Fine", "Experience Points": "Punti esperienza", + "Expiration date": "", "Expired On": "", "Extra Award": "Premio extra", "FAQ": "Domande frequenti", diff --git a/src/pages/Wallet/BootyDetailsModal/BootyDetailsModal.tsx b/src/pages/Wallet/BootyDetailsModal/BootyDetailsModal.tsx index 679e8294..2c2c63c9 100644 --- a/src/pages/Wallet/BootyDetailsModal/BootyDetailsModal.tsx +++ b/src/pages/Wallet/BootyDetailsModal/BootyDetailsModal.tsx @@ -53,6 +53,9 @@ export const BootyDetailsModal = () => { if (typeof results !== "undefined") { setRows( results?.map((r) => { + const attributionDate = new Date(r.attributionDate); + const expiredDate = new Date(attributionDate); + expiredDate.setMonth(expiredDate.getMonth() + 12); const formattedAmount = `${ r.amount.net?.currency && r.amount.net?.currency in currencyTable ? currencyTable[r.amount.net?.currency] @@ -101,6 +104,10 @@ export const BootyDetailsModal = () => { ), }, + expirationDate: { + title: expiredDate.toISOString().split("T")[0], + content: {expiredDate.toLocaleDateString()}, + }, }; }) ); diff --git a/src/pages/Wallet/BootyDetailsModal/columns.ts b/src/pages/Wallet/BootyDetailsModal/columns.ts index f77ef3be..f9c95b8c 100644 --- a/src/pages/Wallet/BootyDetailsModal/columns.ts +++ b/src/pages/Wallet/BootyDetailsModal/columns.ts @@ -50,5 +50,11 @@ export const bootyDetailsColumns = ( dispatch(updateBootyDetailsSortingOptions(newOrder, "gross")); }, }, + { + title: t("Expiration date"), + dataIndex: "expirationDate", + key: "expirationDate", + hideIndex: true, + }, ]; }; diff --git a/src/pages/Wallet/WalletTable.tsx b/src/pages/Wallet/WalletTable.tsx index 35e6b5d7..68c5128f 100644 --- a/src/pages/Wallet/WalletTable.tsx +++ b/src/pages/Wallet/WalletTable.tsx @@ -126,7 +126,7 @@ export const WalletTable = () => { }); const { data: expiredBootyData, isLoading: isExpiredBootyLoading } = - useGetUsersMePendingBootyQuery({ filterBy: { isExpired: 0 } }); + useGetUsersMePendingBootyQuery({ filterBy: { isExpired: 1 } }); // initial requests useEffect(() => { const cols = walletColumns(dispatch, t); @@ -240,20 +240,48 @@ export const WalletTable = () => { } }, [data]); - /* useEffect(() => { + useEffect(() => { if (typeof expiredBootyData?.results !== "undefined") { setExpiredRows( expiredBootyData.results.map((req) => { + const attributionDate = new Date(req.attributionDate); + const expiredDate = new Date(attributionDate); + expiredDate.setMonth(expiredDate.getMonth() + 12); return { - activity: req.activity, - amount: req.amount.gross.value, - attributionDate: req.attributionDate, - name: req.name, + key: req.id, + activityName: { + title: req.name, + content: {req.name}, + }, + activityType: { + title: req.activity, + content: {req.activity}, + }, + attributionDate: { + title: req.attributionDate, + content: {req.attributionDate}, + }, + gross: { + title: "€ " + req.amount?.gross?.value, + content: ( + + {req.amount?.gross?.currency && + req.amount?.gross?.currency in currencyTable + ? currencyTable[req.amount?.gross?.currency] + : req.amount?.gross?.currency}{" "} + {req.amount?.gross?.value?.toFixed(2)} + + ), + }, + expiredDate: { + title: expiredDate.toISOString().split("T")[0], + content: {expiredDate.toLocaleDateString()}, + }, }; }) ); } - }, [data]); */ + }, [expiredBootyData]); const changePagination = (newPage: number) => { const newStart = limit * (newPage - 1); dispatch(updatePagination(newStart)); diff --git a/src/services/tryberApi/index.ts b/src/services/tryberApi/index.ts index 1af30aa3..597aceca 100644 --- a/src/services/tryberApi/index.ts +++ b/src/services/tryberApi/index.ts @@ -1082,6 +1082,7 @@ const injectedRtkApi = api.injectEndpoints({ limit: queryArg.limit, orderBy: queryArg.orderBy, order: queryArg.order, + filterBy: queryArg.filterBy, }, }), }), @@ -2038,6 +2039,7 @@ export type PostDossiersApiArg = { } & { autoApply?: number; bugLanguage?: BugLang; + hasBugForm?: number; hasBugParade?: number; pageVersion?: "v1" | "v2"; skipPagesAndTasks?: number; @@ -3190,6 +3192,8 @@ export type GetUsersMePendingBootyApiArg = { | "activity"; /** How to order values (ASC, DESC) */ order?: "ASC" | "DESC"; + /** Key-value Array for item filtering */ + filterBy?: object; }; export type GetUsersMePermissionsApiResponse = /** status 200 OK */ { appq_bug?: Olp; diff --git a/src/utils/schema.ts b/src/utils/schema.ts index 507b30bc..6e52f5c7 100644 --- a/src/utils/schema.ts +++ b/src/utils/schema.ts @@ -33,12 +33,54 @@ export interface paths { /** A request to login with your username and password */ post: operations["post-authenticate"]; }; + "/browsers": { + get: operations["get-browsers"]; + }; + "/bugs/{bugId}/status": { + patch: operations["patch-bugs-bugId-status"]; + parameters: { + path: { + bugId: string; + }; + }; + }; + "/campaignTypes": { + get: operations["get-campaign-types"]; + parameters: {}; + }; "/campaigns": { /** Get all the Campaigns you have access to */ get: operations["get-campaigns"]; /** Create a new Campaign if you have access to the creation */ post: operations["post-campaigns"]; }; + "/campaigns/forms": { + get: operations["get-campaigns-forms"]; + post: operations["post-campaigns-forms"]; + parameters: {}; + }; + "/campaigns/forms/{formId}": { + get: operations["get-campaigns-forms-formId"]; + put: operations["put-campaigns-forms-formId"]; + parameters: { + path: { + formId: string; + }; + }; + }; + "/campaigns/owners": { + /** Get all the owners of campaigns you have access to */ + get: operations["get-campaigns-owners"]; + parameters: {}; + }; + "/campaigns/{campaignId}/visibility": { + patch: operations["patch-campaigns-campaignId-visibility"]; + parameters: { + path: { + campaignId: string; + }; + }; + }; "/campaigns/{campaign}": { /** Get the data of a Campaign if you have access to it */ get: operations["get-campaigns-campaign"]; @@ -61,6 +103,28 @@ export interface paths { }; }; }; + "/campaigns/{campaign}/bugs/{bugId}": { + /** Get single bug of a Campaign if you have access to it */ + get: operations["get-campaigns-single-bug"]; + parameters: { + path: { + /** A campaign id */ + campaign: string; + bugId: string; + }; + }; + }; + "/campaigns/{campaign}/bugs/{bugId}/aiReview": { + /** Get ai review for a single bug of a Campaign if you have access to it */ + get: operations["get-campaigns-single-bug-ai-review"]; + parameters: { + path: { + /** A campaign id */ + campaign: string; + bugId: string; + }; + }; + }; "/campaigns/{campaign}/candidates": { get: operations["get-campaigns-campaign-candidates"]; /** The Tryber will be inserted as a candidate Tryber on a specific Campaign */ @@ -112,6 +176,7 @@ export interface paths { }; "/campaigns/{campaign}/payouts": { get: operations["get-campaigns-campaign-payouts"]; + put: operations["put-campaigns-campaign-payouts"]; parameters: { path: { /** A campaign id */ @@ -119,6 +184,14 @@ export interface paths { }; }; }; + "/campaigns/{campaign}/preview": { + post: operations["post-campaigns-campaign-preview"]; + parameters: { + path: { + campaign: string; + }; + }; + }; "/campaigns/{campaign}/prospect": { get: operations["get-campaigns-campaign-prospect"]; /** Make campaign perspective status done, and change exp points and tester payouts. */ @@ -185,29 +258,6 @@ export interface paths { }; }; }; - "/campaigns/forms": { - get: operations["get-campaigns-forms"]; - post: operations["post-campaigns-forms"]; - parameters: {}; - }; - "/campaigns/forms/{formId}": { - get: operations["get-campaigns-forms-formId"]; - put: operations["put-campaigns-forms-formId"]; - parameters: { - path: { - formId: string; - }; - }; - }; - "/campaigns/owners": { - /** Get all the owners of campaigns you have access to */ - get: operations["get-campaigns-owners"]; - parameters: {}; - }; - "/campaignTypes": { - get: operations["get-campaign-types"]; - parameters: {}; - }; "/certifications": { /** Get all certificatio */ get: operations["get-certifications"]; @@ -221,15 +271,24 @@ export interface paths { }; }; }; + "/custom_user_fields": { + get: operations["get-customUserFields"]; + parameters: {}; + }; "/customers": { /** Get all the customers you have access to */ get: operations["get-customers"]; post: operations["post-customers"]; parameters: {}; }; - "/custom_user_fields": { - get: operations["get-customUserFields"]; - parameters: {}; + "/customers/{customer}/projects": { + get: operations["get-customers-customer-projects"]; + post: operations["post-customers-customer-projects"]; + parameters: { + path: { + customer: string; + }; + }; }; "/devices/{device_type}/models": { /** Get all model of devices with theirs manufacturers */ @@ -258,16 +317,58 @@ export interface paths { }; }; }; - "/education": { - /** Get all education levels */ - get: operations["get-education"]; + "/dossiers": { + post: operations["post-dossiers"]; + parameters: {}; }; - "/employments": { - /** Get all employments */ - get: operations["get-employments"]; + "/dossiers/{campaign}": { + get: operations["get-dossiers-campaign"]; + put: operations["put-dossiers-campaign"]; + parameters: { + path: { + /** A campaign id */ + campaign: string; + }; + }; }; - "/jotforms/{campaign}": { - post: operations["post-jotforms-campaignId"]; + "/dossiers/{campaign}/availableTesters": { + /** */ + get: operations["get-dossiers-campaign-availableTesters"]; + parameters: { + path: { + campaign: string; + }; + }; + }; + "/dossiers/{campaign}/manual": { + post: operations["post-dossiers-campaign-manual"]; + parameters: { + path: { + /** A campaign id */ + campaign: components["parameters"]["campaign"]; + }; + }; + }; + "/dossiers/{campaign}/phases": { + put: operations["put-dossiers-campaign-phases"]; + parameters: { + path: { + /** A campaign id */ + campaign: string; + }; + }; + }; + "/dossiers/{campaign}/preview": { + post: operations["post-dossiers-campaign-preview"]; + parameters: { + path: { + /** A campaign id */ + campaign: components["parameters"]["campaign"]; + }; + }; + }; + "/dossiers/{campaign}/quotations": { + post: operations["post-dossiers-campaign-quotations"]; parameters: { path: { /** A campaign id */ @@ -275,6 +376,33 @@ export interface paths { }; }; }; + "/dossiers/{campaign}/quotations/{quote}": { + patch: operations["patch-dossiers-campaign-quotations-quote"]; + parameters: { + path: { + /** A campaign id */ + campaign: string; + quote: string; + }; + }; + }; + "/dossiers/{campaign}/quotesHistory": { + get: operations["get-dossiers-campaign-quotes-history"]; + parameters: { + path: { + /** A campaign id */ + campaign: string; + }; + }; + }; + "/education": { + /** Get all education levels */ + get: operations["get-education"]; + }; + "/employments": { + /** Get all employments */ + get: operations["get-employments"]; + }; "/jotforms/forms": { get: operations["get-jotforms"]; parameters: {}; @@ -287,6 +415,15 @@ export interface paths { }; }; }; + "/jotforms/{campaign}": { + post: operations["post-jotforms-campaignId"]; + parameters: { + path: { + /** A campaign id */ + campaign: string; + }; + }; + }; "/languages": { /** Get all languages */ get: operations["get-languages"]; @@ -316,6 +453,9 @@ export interface paths { }; }; }; + "/phases": { + get: operations["get-phases"]; + }; "/popups": { /** Retrieve all available popups for admin operations */ get: operations["get-popups"]; @@ -334,6 +474,10 @@ export interface paths { }; }; }; + "/productTypes": { + get: operations["get-productTypes"]; + parameters: {}; + }; "/users": { /** Get all users you have access to */ get: operations["get-users"]; @@ -348,6 +492,14 @@ export interface paths { }; }; }; + "/users/by-role/{role}": { + get: operations["get-users-by-role-role"]; + parameters: { + path: { + role: "tester_lead" | "quality_leader" | "ux_researcher" | "assistants"; + }; + }; + }; "/users/me": { /** Get your user data */ get: operations["get-users-me"]; @@ -391,15 +543,6 @@ export interface paths { }; }; }; - "/users/me/campaigns/{campaign}/compatible_devices": { - get: operations["get-users-me-campaigns-campaignId-compatible-devices"]; - parameters: { - path: { - /** A campaign id */ - campaign: string; - }; - }; - }; "/users/me/campaigns/{campaignId}/bugs": { /** Send a user bug on a specific campaign */ post: operations["post-users-me-campaigns-campaign-bugs"]; @@ -435,6 +578,71 @@ export interface paths { }; }; }; + "/users/me/campaigns/{campaignId}/payout_data": { + get: operations["get-users-me-campaigns-cid-payout-data"]; + parameters: { + path: { + campaignId: string; + }; + }; + }; + "/users/me/campaigns/{campaignId}/preview": { + get: operations["get-users-me-campaigns-cid-preview"]; + parameters: { + path: { + campaignId: string; + }; + }; + }; + "/users/me/campaigns/{campaignId}/tasks": { + get: operations["get-users-me-campaign-campaignId-tasks"]; + parameters: { + path: { + campaignId: string; + }; + }; + }; + "/users/me/campaigns/{campaignId}/tasks/{taskId}": { + post: operations["post-users-me-campaigns-campaign-tasks-task"]; + parameters: { + path: { + /** the campaign id */ + campaignId: string; + taskId: string; + }; + }; + }; + "/users/me/campaigns/{campaignId}/tasks/{taskId}/media": { + /** Return a list of tester media uploaded on a specific Usecase of a specific Campaign */ + get: operations["get-users-me-campaigns-campaignId-tasks-taskId-media"]; + post: operations["post-users-me-campaigns-campaignId-tasks-taskId-media"]; + parameters: { + path: { + campaignId: string; + taskId: string; + }; + }; + }; + "/users/me/campaigns/{campaignId}/tasks/{taskId}/media/{mediaId}": { + /** Delete a specific media of a specific campaign task if authorized */ + delete: operations["delete-users-me-campaigns-campaignId-tasks-taskId-media-mediaId"]; + parameters: { + path: { + campaignId: string; + taskId: string; + mediaId: string; + }; + }; + }; + "/users/me/campaigns/{campaign}/compatible_devices": { + get: operations["get-users-me-campaigns-campaignId-compatible-devices"]; + parameters: { + path: { + /** A campaign id */ + campaign: string; + }; + }; + }; "/users/me/certifications": { /** Add one certification to your profile */ post: operations["post-users-me-certifications"]; @@ -541,86 +749,45 @@ export interface paths { "/users/me/rank/list": { get: operations["get-users-me-rank-list"]; }; - "/dossiers": { - post: operations["post-dossiers"]; - parameters: {}; - }; - "/dossiers/{campaign}": { - get: operations["get-dossiers-campaign"]; - put: operations["put-dossiers-campaign"]; - parameters: { - path: { - /** A campaign id */ - campaign: string; - }; - }; - }; - "/customers/{customer}/projects": { - get: operations["get-customers-customer-projects"]; - post: operations["post-customers-customer-projects"]; - parameters: { - path: { - customer: string; - }; - }; - }; - "/users/by-role/{role}": { - get: operations["get-users-by-role-role"]; - parameters: { - path: { - role: "tester_lead" | "quality_leader" | "ux_researcher" | "assistants"; - }; - }; - }; - "/browsers": { - get: operations["get-browsers"]; - }; - "/productTypes": { - get: operations["get-productTypes"]; - parameters: {}; - }; - "/phases": { - get: operations["get-phases"]; - }; - "/dossiers/{campaign}/phases": { - put: operations["put-dossiers-campaign-phases"]; - parameters: { - path: { - /** A campaign id */ - campaign: string; - }; - }; - }; } export interface components { schemas: { AdditionalField: { field_id: number; + is_candidate?: boolean; name: string; - value: string; text?: string; - is_candidate?: boolean; + value: string; }; Agreement: { - title: string; - tokens: number; - unitPrice: number; - startDate: string; expirationDate: string; - note?: string; /** @default false */ isTokenBased?: boolean; + note?: string; + startDate: string; + title: string; + tokens: number; + unitPrice: number; + }; + /** AvailableDevice */ + AvailableDevice: { + name: string; }; /** Bug */ Bug: { - severity?: components["schemas"]["BugSeverity"]; - status?: components["schemas"]["BugStatus"]; campaign?: components["schemas"]["CampaignOptional"] & { id?: number; }; + severity?: components["schemas"]["BugSeverity"]; + status?: components["schemas"]["BugStatus"]; title?: string; }; + /** + * BugLang + * @enum {string} + */ + BugLang: "IT" | "GB" | "ES" | "FR" | "DE"; /** BugSeverity */ BugSeverity: { id?: number; @@ -628,9 +795,9 @@ export interface components { }; /** BugStatus */ BugStatus: { + description?: string; id?: number; name?: string; - description?: string; }; /** BugTag */ BugTag: { @@ -645,19 +812,19 @@ export interface components { components["schemas"]["CampaignRequired"]; /** CampaignAdditionalField */ CampaignAdditionalField: { + error: string; name: string; slug: string; - error: string; } & ( | { + options: string[]; /** @enum {string} */ type: "select"; - options: string[]; } | { + regex: string; /** @enum {string} */ type: "text"; - regex: string; } ); /** CampaignField */ @@ -665,43 +832,43 @@ export interface components { id?: number; }; CampaignOptional: { - name?: string; + additionalFields?: components["schemas"]["CampaignField"][]; + allowed?: { + bug_types?: components["schemas"]["BugType"][]; + replicabilities?: components["schemas"]["Replicability"][]; + severities?: components["schemas"]["BugSeverity"][]; + }; + /** @description True if you applied on this Campaign */ + applied?: boolean; + /** @description If bugform is deactivated is a boolean else contains URLs to bugforms for each languages */ + bugform_link?: boolean | components["schemas"]["TranslatablePage"]; + /** @default 0 */ + csm_effort?: number; + customerCanViewReviewing?: boolean; customer_title?: string; - internal_id?: string; dates?: { - start?: string; - end?: string; close?: string; + end?: string; + start?: string; }; - status?: boolean; - language?: string; - public?: boolean; - hasBugParade?: boolean; devices?: { id?: string; }[]; + hasBugParade?: boolean; + internal_id?: string; + language?: string; + manual_link?: components["schemas"]["TranslatablePage"]; minNumberOfMedia?: number; - titleRule?: boolean; - allowed?: { - severities?: components["schemas"]["BugSeverity"][]; - bug_types?: components["schemas"]["BugType"][]; - replicabilities?: components["schemas"]["Replicability"][]; - }; + name?: string; + preview_link?: components["schemas"]["TranslatablePage"]; projectManager?: components["schemas"]["User"]; - customerCanViewReviewing?: boolean; - additionalFields?: components["schemas"]["CampaignField"][]; + public?: boolean; + status?: boolean; + titleRule?: boolean; /** @default 0 */ tokens?: number; /** @default 0 */ - csm_effort?: number; - /** @default 0 */ ux_effort?: number; - preview_link?: components["schemas"]["TranslatablePage"]; - manual_link?: components["schemas"]["TranslatablePage"]; - /** @description If bugform is deactivated is a boolean else contains URLs to bugforms for each languages */ - bugform_link?: boolean | components["schemas"]["TranslatablePage"]; - /** @description True if you applied on this Campaign */ - applied?: boolean; visibility?: { freeSpots?: number; totalSpots?: number; @@ -710,32 +877,39 @@ export interface components { }; }; CampaignRequired: { - name: string; + campaign_type: components["schemas"]["CampaignType"]; dates: { - start: string; - end: string; close: string; + end: string; + start: string; }; - campaign_type: components["schemas"]["CampaignType"]; + name: string; }; CampaignType: string | number; Certification: { - id?: number; - name: string; - area: string; - institute: string; /** Format: date */ achievement_date: string; + area: string; + id?: number; + institute: string; + name: string; + }; + /** CountryCode */ + CountryCode: string; + /** Currency */ + Currency: { + currency: string; + value: number; }; /** CustomUserFieldsData */ CustomUserFieldsData: { - id: number; - type: components["schemas"]["CustomUserFieldsType"]; - placeholder?: components["schemas"]["TranslatablePage"]; allow_other?: boolean; - name: components["schemas"]["TranslatablePage"]; format?: string; + id: number; + name: components["schemas"]["TranslatablePage"]; options?: components["schemas"]["CustomUserFieldsDataOption"][]; + placeholder?: components["schemas"]["TranslatablePage"]; + type: components["schemas"]["CustomUserFieldsType"]; }; /** CustomUserFieldsDataOption */ CustomUserFieldsDataOption: { @@ -747,10 +921,57 @@ export interface components { * @enum {string} */ CustomUserFieldsType: "text" | "select" | "multiselect"; - /** Currency */ - Currency: { - value: number; - currency: string; + DossierCreationData: { + additionals?: ({ + showInStats?: boolean; + } & components["schemas"]["CampaignAdditionalField"])[]; + browsers?: number[]; + bugTypes?: number[]; + /** Format: date-time */ + closeDate?: string; + countries?: components["schemas"]["CountryCode"][]; + csm?: number; + description?: string; + deviceList: number[]; + deviceRequirements?: string; + /** Format: date-time */ + endDate?: string; + goal?: string; + languages?: string[]; + notes?: string; + outOfScope?: string; + productLink?: string; + productType?: number; + project: number; + roles?: { + role: number; + user: number; + }[]; + /** Format: date-time */ + startDate: string; + target?: { + cap?: number; + genderQuote?: string; + notes?: string; + size?: number; + }; + testType: number; + title: { + customer: string; + tester?: string; + }; + visibilityCriteria?: { + ageRanges?: { + max: number; + min: number; + }[]; + cuf?: { + cufId: number; + cufValueIds: number[]; + }[]; + gender?: number[]; + provinces?: string[]; + }; }; /** FiscalBirthCity */ FiscalBirthCity: @@ -772,19 +993,34 @@ export interface components { | "non-italian" | "vat" | "company"; + /** + * Gender + * @enum {string} + */ + Gender: "male" | "female" | "not-specified" | "other"; /** LevelDefinition */ LevelDefinition: { + hold?: number; id: number; name: string; reach?: number; - hold?: number; }; /** MonthlyLevel */ MonthlyLevel: { id: number; name: string; }; + Olp: number[] | boolean; + /** PaginationData */ + PaginationData: { + limit?: number; + size: number; + start: number; + total?: number; + }; Popup: { + content?: string; + once?: boolean; profiles?: | number[] | ( @@ -794,11 +1030,8 @@ export interface components { | "logged-in-year" | "not-logged-in-year" ); - once?: boolean; - content?: string; title?: string; }; - Olp: number[] | boolean; /** PreselectionFormQuestion */ PreselectionFormQuestion: { question: string; @@ -808,30 +1041,47 @@ export interface components { type: components["schemas"]["PreselectionQuestionSimple"]; } | { - type: components["schemas"]["PreselectionQuestionMultiple"]; options?: { - value: string; isInvalid?: boolean; + value: string; }[]; + type: components["schemas"]["PreselectionQuestionMultiple"]; } | { - type: components["schemas"]["PreselectionQuestionCuf"]; options?: { - value: number; isInvalid?: boolean; + value: number; }[]; + type: components["schemas"]["PreselectionQuestionCuf"]; } ); + /** PreselectionQuestionCuf */ + PreselectionQuestionCuf: string; + /** + * PreselectionQuestionMultiple + * @enum {string} + */ + PreselectionQuestionMultiple: "multiselect" | "select" | "radio"; + /** + * PreselectionQuestionSimple + * @enum {string} + */ + PreselectionQuestionSimple: "gender" | "text" | "phone_number" | "address"; /** Project */ Project: { name?: string; }; + /** + * ProspectStatus + * @enum {string} + */ + ProspectStatus: "draft" | "confirmed" | "done"; RankingItem: { - position: number; - image: string; id: number; - name: string; + image: string; monthly_exp: number; + name: string; + position: number; }; /** Replicability */ Replicability: { @@ -841,153 +1091,86 @@ export interface components { Task: components["schemas"]["TaskOptional"] & components["schemas"]["TaskRequired"]; TaskOptional: { - name?: string; - content?: string; + allow_media?: boolean; campaign_id?: number; + content?: string; group?: number; - allow_media?: boolean; + name?: string; }; TaskRequired: { - name: string; - content: string; campaign_id: number; + content: string; + name: string; }; /** TranslatablePage */ TranslatablePage: { en?: string; - it?: string; es?: string; + it?: string; }; /** User */ User: { - username?: string; - name?: string; - surname?: string; /** Format: email */ email?: string; + id?: number; /** Format: uri */ image?: string; - id?: number; - wp_user_id?: number; - role?: string; is_verified?: boolean; + name?: string; + role?: string; + surname?: string; + username?: string; + wp_user_id?: number; }; /** UserDevice */ UserDevice: { - type: string; - id: number; device: | { + id?: number; manufacturer: string; model: string; - id?: number; } | { pc_type: string; }; + id: number; operating_system: { id: number; platform: string; version: string; }; + type: string; }; - /** - * Gender - * @enum {string} - */ - Gender: "male" | "female" | "not-specified" | "other"; - /** PaginationData */ - PaginationData: { - start: number; - limit?: number; - size: number; - total?: number; - }; - /** - * ProspectStatus - * @enum {string} - */ - ProspectStatus: "draft" | "confirmed" | "done"; - /** CountryCode */ - CountryCode: string; - DossierCreationData: { - project: number; - testType: number; - title: { - customer: string; - tester?: string; - }; - /** Format: date-time */ - startDate: string; - /** Format: date-time */ - endDate?: string; - /** Format: date-time */ - closeDate?: string; - deviceList: number[]; - csm?: number; - roles?: { - role: number; - user: number; - }[]; - description?: string; - productLink?: string; - goal?: string; - outOfScope?: string; - deviceRequirements?: string; - target?: { - notes?: string; - size?: number; - cap?: number; - }; - countries?: components["schemas"]["CountryCode"][]; - languages?: string[]; - browsers?: number[]; - productType?: number; - notes?: string; - }; - /** - * PreselectionQuestionSimple - * @enum {string} - */ - PreselectionQuestionSimple: "gender" | "text" | "phone_number" | "address"; - /** - * PreselectionQuestionMultiple - * @enum {string} - */ - PreselectionQuestionMultiple: "multiselect" | "select" | "radio"; - /** PreselectionQuestionCuf */ - PreselectionQuestionCuf: string; }; responses: { - /** A user */ - UserData: { - content: { - "application/json": components["schemas"]["User"]; - }; - }; /** Authentication data. The token can be used to authenticate the protected requests */ Authentication: { content: { "application/json": { - id?: number; + exp?: number; firstName?: string; + iat?: number; + id?: number; lastName?: string; token?: string; username?: string; - iat?: number; - exp?: number; }; }; }; - /** A single Campaigns with the Campaign id and Project data */ - SingleCampaign: { + /** An error due to missing required parameters */ + MissingParameters: { content: { - "application/json": components["schemas"]["Campaign"] & { - id: number; - } & { - project?: components["schemas"]["Project"] & { - id?: number; - }; + "application/json": { + message: string; + }; + }; + }; + /** An error due to insufficient authorization to access the resource */ + NotAuthorized: { + content: { + "application/json": { + code?: string; + message?: string; }; }; }; @@ -995,54 +1178,55 @@ export interface components { NotFound: { content: { "application/json": { + code?: string; element: string; id: number; message: string; - code?: string; }; }; }; - /** An error due to missing required parameters */ - MissingParameters: { + /** A single Campaigns with the Campaign id and Project data */ + SingleCampaign: { content: { - "application/json": { - message: string; + "application/json": components["schemas"]["Campaign"] & { + id: number; + } & { + project?: components["schemas"]["Project"] & { + id?: number; + }; }; }; }; - /** An error due to insufficient authorization to access the resource */ - NotAuthorized: { + /** A user */ + UserData: { content: { - "application/json": { - message?: string; - code?: string; - }; + "application/json": components["schemas"]["User"]; }; }; }; parameters: { /** @description A campaign id */ campaign: string; - /** @description A task id */ - task: string; /** @description A customer id */ customer: string; - /** @description A project id */ - project: string; - /** @description Max items to retrieve */ - limit: number; - /** @description Items to skip for pagination */ - start: number; /** @description Key-value Array for item filtering */ filterBy: { [key: string]: unknown }; - /** @description How to order values (ASC, DESC) */ - order: "ASC" | "DESC"; + /** @description Max items to retrieve */ + limit: number; /** @description How to localize values */ locale: "en" | "it"; - /** @description A comma separated list of fields which will be searched */ - searchBy: string; + /** @description How to order values (ASC, DESC) */ + order: "ASC" | "DESC"; + /** @description A project id */ + project: string; /** @description The value to search for */ search: string; + /** @description A comma separated list of fields which will be searched */ + searchBy: string; + /** @description Items to skip for pagination */ + start: number; + /** @description A task id */ + task: string; testerId: string; }; requestBodies: {}; @@ -1082,8 +1266,8 @@ export interface operations { id: number; } & components["schemas"]["Agreement"] & { customer: { - id: number; company: string; + id: number; }; })[]; } & components["schemas"]["PaginationData"]; @@ -1131,8 +1315,8 @@ export interface operations { id: number; } & components["schemas"]["Agreement"] & { customer: { - id: number; company: string; + id: number; }; }; }; @@ -1157,8 +1341,8 @@ export interface operations { id: number; } & components["schemas"]["Agreement"] & { customer: { - id: number; company: string; + id: number; }; }; }; @@ -1212,8 +1396,68 @@ export interface operations { requestBody: { content: { "application/json": { - username: string; password: string; + username: string; + }; + }; + }; + }; + "get-browsers": { + responses: { + /** OK */ + 200: { + content: { + "application/json": { + results: { + id: number; + name: string; + }[]; + }; + }; + }; + }; + }; + "patch-bugs-bugId-status": { + parameters: { + path: { + bugId: string; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { [key: string]: unknown }; + }; + }; + /** Forbidden */ + 403: { + content: { + "application/json": { [key: string]: unknown }; + }; + }; + }; + requestBody: { + content: { + "application/json": { + status_id: number; + }; + }; + }; + }; + "get-campaign-types": { + parameters: {}; + responses: { + 200: { + content: { + "application/json": { + customRoles: { + roleId: number; + userIds: number[]; + }[]; + id: number; + name: string; + }[]; }; }; }; @@ -1244,22 +1488,6 @@ export interface operations { content: { "application/json": { items?: { - id?: number; - name?: string; - customerTitle?: string; - startDate?: string; - endDate?: string; - /** @enum {string} */ - status?: "running" | "closed" | "incoming"; - /** @enum {string} */ - visibility?: - | "admin" - | "smallgroup" - | "logged" - | "public" - | "target"; - /** @enum {string} */ - resultType?: "bug" | "bugparade" | "no"; csm?: { id: number; name: string; @@ -1269,19 +1497,25 @@ export interface operations { id?: number; name: string; }; - type?: { + customerTitle?: string; + endDate?: string; + id?: number; + name?: string; + phase?: { + id: number; name: string; - /** @enum {string} */ - area: "quality" | "experience"; }; project?: { id?: number; name: string; }; - phase?: { + quote?: { id: number; - name: string; + price: string; + status: string; }; + /** @enum {string} */ + resultType?: "bug" | "bugparade" | "no"; roles?: { role: { id: number; @@ -1293,10 +1527,25 @@ export interface operations { surname: string; }; }[]; - }[]; - } & components["schemas"]["PaginationData"]; - }; - }; + startDate?: string; + /** @enum {string} */ + status?: "running" | "closed" | "incoming"; + type?: { + /** @enum {string} */ + area: "quality" | "experience"; + name: string; + }; + /** @enum {string} */ + visibility?: + | "admin" + | "smallgroup" + | "logged" + | "public" + | "target"; + }[]; + } & components["schemas"]["PaginationData"]; + }; + }; 403: components["responses"]["NotAuthorized"]; 404: components["responses"]["NotFound"]; }; @@ -1317,6 +1566,180 @@ export interface operations { }; }; }; + "get-campaigns-forms": { + parameters: { + query: { + /** A comma separated list of fields which will be searched */ + searchBy?: components["parameters"]["searchBy"]; + /** The value to search for */ + search?: components["parameters"]["search"]; + /** Max items to retrieve */ + limit?: components["parameters"]["limit"]; + /** Items to skip for pagination */ + start?: components["parameters"]["start"]; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + limit?: number; + results: { + campaign?: number; + id: number; + name: string; + }[]; + size: number; + start: number; + total?: number; + }; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + "post-campaigns-forms": { + parameters: {}; + responses: { + /** Created */ + 201: { + content: { + "application/json": { + campaign?: { + id: number; + name: string; + }; + fields?: ({ + id: number; + } & components["schemas"]["PreselectionFormQuestion"])[]; + id: number; + name: string; + }; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + requestBody: { + content: { + "application/json": { + campaign?: number; + creationDate?: string; + fields: components["schemas"]["PreselectionFormQuestion"][]; + name: string; + }; + }; + }; + }; + "get-campaigns-forms-formId": { + parameters: { + path: { + formId: string; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + campaign?: { + id: number; + name: string; + }; + fields: ({ + id: number; + } & components["schemas"]["PreselectionFormQuestion"])[]; + id: number; + /** @example My form */ + name: string; + }; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + "put-campaigns-forms-formId": { + parameters: { + path: { + formId: string; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + campaign?: { + id: number; + name: string; + }; + fields: ({ + id: number; + } & components["schemas"]["PreselectionFormQuestion"])[]; + id: number; + name: string; + }; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + requestBody: { + content: { + "application/json": { + campaign?: number; + fields: ({ + id?: number; + } & components["schemas"]["PreselectionFormQuestion"])[]; + name: string; + }; + }; + }; + }; + /** Get all the owners of campaigns you have access to */ + "get-campaigns-owners": { + parameters: {}; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + id: number; + name: string; + surname: string; + }[]; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + "patch-campaigns-campaignId-visibility": { + parameters: { + path: { + campaignId: string; + }; + }; + responses: { + /** OK */ + 200: unknown; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + /** Internal Server Error */ + 500: unknown; + }; + requestBody: { + content: { + "application/json": { + /** @enum {undefined} */ + type: "internal" | "target"; + }; + }; + }; + }; /** Get the data of a Campaign if you have access to it */ "get-campaigns-campaign": { parameters: { @@ -1331,10 +1754,14 @@ export interface operations { content: { "application/json": { id: number; + plan?: { + id: number; + name: string; + }; + preselectionFormId?: number; title: string; type: string; typeDescription: string; - preselectionFormId?: number; }; }; }; @@ -1391,29 +1818,29 @@ export interface operations { content: { "application/json": { items: { + created: string; + /** @enum {string} */ + duplication: "father" | "unique" | "duplicated"; id: number; - title: string; internalId: string; - status: { + isFavourite: boolean; + severity: { id: number; name: string; }; - type: { + status: { id: number; name: string; }; - severity: { + tags?: components["schemas"]["BugTag"][]; + tester: { id: number; - name: string; }; - tester: { + title: string; + type: { id: number; + name: string; }; - tags?: components["schemas"]["BugTag"][]; - /** @enum {string} */ - duplication: "father" | "unique" | "duplicated"; - isFavourite: boolean; - created: string; updated: string; }[]; } & components["schemas"]["PaginationData"]; @@ -1423,31 +1850,13 @@ export interface operations { 404: components["responses"]["NotFound"]; }; }; - "get-campaigns-campaign-candidates": { + /** Get single bug of a Campaign if you have access to it */ + "get-campaigns-single-bug": { parameters: { path: { /** A campaign id */ campaign: string; - }; - query: { - /** Max items to retrieve */ - limit?: components["parameters"]["limit"]; - /** Items to skip for pagination */ - start?: components["parameters"]["start"]; - /** The fields to add to the results */ - fields?: string; - /** Key-value Array for item filtering */ - filterByInclude?: unknown; - /** Key-value Array for item filtering */ - filterByExclude?: unknown; - /** Array with min and max */ - filterByAge?: unknown; - /** Show accepted/candidates or both */ - show?: - | "onlyAccepted" - | "onlyCandidates" - | "all" - | "candidatesAndExcluded"; + bugId: string; }; }; responses: { @@ -1455,26 +1864,121 @@ export interface operations { 200: { content: { "application/json": { - results?: { + actual_result: string; + description: string; + expected_result: string; + id: number; + media: { + id: number; + type: string; + url: string; + }[]; + note: string; + reason: string; + replicability: { id: number; name: string; - surname: string; - gender: components["schemas"]["Gender"]; - age: number; - experience: number; - businessCps: number; - businessCpsLastMonth: number; - levels: { - bugHunting: string; - metal: string; - }; - devices: { + }; + severity: components["schemas"]["BugSeverity"]; + status: components["schemas"]["BugStatus"]; + status_history: { + date: string; + reason: string; + status: string; + }[]; + title: string; + type: { + id: number; + name: string; + }; + usecase: { + description: string; + id: number; + title: string; + }; + }; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + /** Get ai review for a single bug of a Campaign if you have access to it */ + "get-campaigns-single-bug-ai-review": { + parameters: { + path: { + /** A campaign id */ + campaign: string; + bugId: string; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + ai_notes?: string; + ai_reason: string; + ai_status: string; + score_percentage: number; + }; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + "get-campaigns-campaign-candidates": { + parameters: { + path: { + /** A campaign id */ + campaign: string; + }; + query: { + /** Max items to retrieve */ + limit?: components["parameters"]["limit"]; + /** Items to skip for pagination */ + start?: components["parameters"]["start"]; + /** The fields to add to the results */ + fields?: string; + /** Key-value Array for item filtering */ + filterByInclude?: unknown; + /** Key-value Array for item filtering */ + filterByExclude?: unknown; + /** Array with min and max */ + filterByAge?: unknown; + /** Show accepted/candidates or both */ + show?: + | "onlyAccepted" + | "onlyCandidates" + | "all" + | "candidatesAndExcluded"; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + results?: { + age: number; + businessCps: number; + businessCpsLastMonth: number; + devices: { + id: number; manufacturer?: string; model?: string; os: string; osVersion: string; - id: number; }[]; + experience: number; + gender: components["schemas"]["Gender"]; + id: number; + levels: { + bugHunting: string; + metal: string; + }; + name: string; questions?: { id?: number; title?: string; @@ -1482,6 +1986,7 @@ export interface operations { }[]; /** @enum {string} */ status?: "candidate" | "excluded" | "selected"; + surname: string; }[]; } & components["schemas"]["PaginationData"]; }; @@ -1504,9 +2009,9 @@ export interface operations { content: { "application/json": { results: { - tester_id: number; - device?: "any" | number; campaignId?: number; + device?: "any" | number; + tester_id: number; }[]; }; }; @@ -1515,12 +2020,12 @@ export interface operations { 207: { content: { "application/json": { + invalidTesters?: number[]; results: { - tester_id: number; - device?: "any" | number; campaignId?: number; + device?: "any" | number; + tester_id: number; }[]; - invalidTesters?: number[]; }; }; }; @@ -1531,12 +2036,12 @@ export interface operations { content: { "application/json": | { - tester_id: number; device?: number | "random"; + tester_id: number; }[] | { - tester_id: number; device?: number | "random"; + tester_id: number; }; }; }; @@ -1625,22 +2130,22 @@ export interface operations { content: { "application/json": { items: { - id: number; - name: string; - time: number; - tester: { - id: number; - name: string; - }; cluster: { id: number; name: string; }; + id: number; media: { id: number; - url: string; streamUrl: string; + url: string; + }; + name: string; + tester: { + id: number; + name: string; }; + time: number; }[]; }; }; @@ -1661,20 +2166,20 @@ export interface operations { 200: { content: { "application/json": { - maxBonusBug: number; completionRule: { bugs?: number; usecases?: number; }; - testSuccess: { + maxBonusBug: number; + testFailure: { + message: string; payout: number; points: number; - message: string; }; - testFailure: { + testSuccess: { + message: string; payout: number; points: number; - message: string; }; }; }; @@ -1683,6 +2188,89 @@ export interface operations { 404: components["responses"]["NotFound"]; }; }; + "put-campaigns-campaign-payouts": { + parameters: { + path: { + /** A campaign id */ + campaign: components["parameters"]["campaign"]; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + campaign_complete_bonus_eur?: number; + campaign_pts?: number; + critical_bug_payout?: number; + high_bug_payout?: number; + low_bug_payout?: number; + medium_bug_payout?: number; + minimum_bugs?: number; + payout_limit?: number; + percent_usecases?: number; + point_multiplier_critical?: number; + point_multiplier_high?: number; + point_multiplier_low?: number; + point_multiplier_medium?: number; + point_multiplier_perfect?: number; + point_multiplier_refused?: number; + top_tester_bonus?: number; + }; + }; + }; + 400: components["responses"]["MissingParameters"]; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + requestBody: { + content: { + "application/json": { + campaign_complete_bonus_eur?: number; + campaign_pts?: number; + critical_bug_payout?: number; + high_bug_payout?: number; + low_bug_payout?: number; + medium_bug_payout?: number; + minimum_bugs?: number; + payout_limit?: number; + percent_usecases?: number; + point_multiplier_critical?: number; + point_multiplier_high?: number; + point_multiplier_low?: number; + point_multiplier_medium?: number; + /** Format: float */ + point_multiplier_perfect?: number; + point_multiplier_refused?: number; + top_tester_bonus?: number; + }; + }; + }; + }; + "post-campaigns-campaign-preview": { + parameters: { + path: { + campaign: string; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { [key: string]: unknown }; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + requestBody: { + content: { + "application/json": { + content: string; + }; + }; + }; + }; "get-campaigns-campaign-prospect": { parameters: { path: { @@ -1701,38 +2289,38 @@ export interface operations { content: { "application/json": { items: { - tester: { - id: number; - name: string; - surname: string; - group: number; - }; - usecases: { - completed: number; - required: number; - }; bugs: { critical: number; high: number; - medium: number; low: number; + medium: number; }; - payout: { + experience: { completion: number; - bug: number; - refund: number; extra: number; }; - experience: { + isCompleted: boolean; + isTopTester: boolean; + note: string; + payout: { + bug: number; completion: number; extra: number; + refund: number; }; - note: string; /** @enum {string} */ status: "pending" | "done"; + tester: { + group: number; + id: number; + name: string; + surname: string; + }; + usecases: { + completed: number; + required: number; + }; weightedBugs: number; - isCompleted: boolean; - isTopTester: boolean; }[]; status: components["schemas"]["ProspectStatus"]; }; @@ -1762,24 +2350,24 @@ export interface operations { requestBody: { content: { "application/json": { - status: components["schemas"]["ProspectStatus"]; items: { - tester: { - id: number; - }; + completed: boolean; experience: { completion: number; extra: number; }; + note?: string; payout: { - completion: number; bug: number; + completion: number; extra: number; refund: number; }; - note?: string; - completed: boolean; + tester: { + id: number; + }; }[]; + status: components["schemas"]["ProspectStatus"]; }; }; }; @@ -1821,18 +2409,18 @@ export interface operations { 200: { content: { "application/json": { - payout: { + completed: boolean; + experience: { completion: number; - bugs: number; - refund: number; extra: number; }; - experience: { + note: string; + payout: { + bugs: number; completion: number; extra: number; + refund: number; }; - note: string; - completed: boolean; }; }; }; @@ -1840,18 +2428,18 @@ export interface operations { requestBody: { content: { "application/json": { - payout: { + completed: boolean; + experience: { completion: number; - bugs: number; - refund: number; extra: number; }; - experience: { + note: string; + payout: { + bugs: number; completion: number; extra: number; + refund: number; }; - note: string; - completed: boolean; }; }; }; @@ -1904,14 +2492,33 @@ export interface operations { }; responses: { /** Created */ - 201: unknown; + 201: { + content: { + "application/json": { + content: string; + id: number; + title: string; + }; + }; + }; 403: components["responses"]["NotAuthorized"]; 404: components["responses"]["NotFound"]; }; /** The data of the new UseCase to link to the Campaign */ requestBody: { content: { - "application/json": components["schemas"]["TaskOptional"]; + "application/json": { + content: string; + is_required: number; + position?: number; + prefix?: string; + title: string; + upload?: { + language: string; + /** @enum {string} */ + policy: "optimize" | "allow"; + }; + }; }; }; }; @@ -1977,26 +2584,26 @@ export interface operations { content: { "application/json": { goal: string; - usersNumber: number; - sentiments: { - id: number; - value: number; - comment: string; - cluster: { - id: number; - name: string; - }; - }[]; methodology: { + description: string; name: string; /** @enum {string} */ type: "qualitative" | "quantitative" | "quali-quantitative"; - description: string; }; questions: { id: number; name: string; }[]; + sentiments: { + cluster: { + id: number; + name: string; + }; + comment: string; + id: number; + value: number; + }[]; + usersNumber: number; visible: number; }; }; @@ -2026,37 +2633,32 @@ export interface operations { content: { "application/json": { goal?: string; - usersNumber?: number; - visible?: number; methodology?: { description: string; type: string; }; + questions?: { + id?: number; + name: string; + }[]; sentiments?: { clusterId: number; - value: number; comment: string; id?: number; + value: number; }[]; - questions?: { - name: string; - id?: number; - }[]; + usersNumber?: number; + visible?: number; }; }; }; }; - "get-campaigns-forms": { + /** Get all certificatio */ + "get-certifications": { parameters: { query: { - /** A comma separated list of fields which will be searched */ - searchBy?: components["parameters"]["searchBy"]; - /** The value to search for */ - search?: components["parameters"]["search"]; - /** Max items to retrieve */ - limit?: components["parameters"]["limit"]; - /** Items to skip for pagination */ - start?: components["parameters"]["start"]; + /** Key-value Array for item filtering */ + filterBy?: components["parameters"]["filterBy"]; }; }; responses: { @@ -2064,59 +2666,24 @@ export interface operations { 200: { content: { "application/json": { - results: { - id: number; - name: string; - campaign?: number; - }[]; - limit?: number; - start: number; - size: number; - total?: number; - }; - }; - }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; - }; - }; - "post-campaigns-forms": { - parameters: {}; - responses: { - /** Created */ - 201: { - content: { - "application/json": { + area: string; id: number; + institute: string; name: string; - campaign?: { - id: number; - name: string; - }; - fields?: ({ - id: number; - } & components["schemas"]["PreselectionFormQuestion"])[]; - }; + }[]; }; }; 403: components["responses"]["NotAuthorized"]; 404: components["responses"]["NotFound"]; }; - requestBody: { - content: { - "application/json": { - name: string; - fields: components["schemas"]["PreselectionFormQuestion"][]; - campaign?: number; - creationDate?: string; - }; - }; - }; }; - "get-campaigns-forms-formId": { + "get-regions": { parameters: { path: { - formId: string; + code: string; + }; + query: { + languageCode?: string; }; }; responses: { @@ -2124,127 +2691,72 @@ export interface operations { 200: { content: { "application/json": { - id: number; - /** @example My form */ name: string; - campaign?: { - id: number; - name: string; - }; - fields: ({ - id: number; - } & components["schemas"]["PreselectionFormQuestion"])[]; - }; + value: string; + }[]; }; }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; }; }; - "put-campaigns-forms-formId": { - parameters: { - path: { - formId: string; - }; - }; + "get-customUserFields": { + parameters: {}; responses: { /** OK */ 200: { content: { "application/json": { - id: number; - name: string; - fields: ({ - id: number; - } & components["schemas"]["PreselectionFormQuestion"])[]; - campaign?: { + fields?: components["schemas"]["CustomUserFieldsData"][]; + group: { + description?: components["schemas"]["TranslatablePage"]; id: number; - name: string; + name: components["schemas"]["TranslatablePage"]; }; - }; - }; - }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; - }; - requestBody: { - content: { - "application/json": { - name: string; - campaign?: number; - fields: ({ - id?: number; - } & components["schemas"]["PreselectionFormQuestion"])[]; + }[]; }; }; }; }; - /** Get all the owners of campaigns you have access to */ - "get-campaigns-owners": { + /** Get all the customers you have access to */ + "get-customers": { parameters: {}; responses: { - /** OK */ + /** An array of Customer objects */ 200: { content: { "application/json": { - id: number; - name: string; - surname: string; + id?: number; + name?: string; }[]; }; }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; + 403: components["responses"]["NotFound"]; }; }; - "get-campaign-types": { + "post-customers": { parameters: {}; responses: { + /** OK */ 200: { content: { "application/json": { id: number; name: string; - customRoles: { - roleId: number; - userIds: number[]; - }[]; - }[]; + }; }; }; }; - }; - /** Get all certificatio */ - "get-certifications": { - parameters: { - query: { - /** Key-value Array for item filtering */ - filterBy?: components["parameters"]["filterBy"]; - }; - }; - responses: { - /** OK */ - 200: { - content: { - "application/json": { - id: number; - name: string; - area: string; - institute: string; - }[]; + requestBody: { + content: { + "application/json": { + name: string; }; }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; }; }; - "get-regions": { + "get-customers-customer-projects": { parameters: { path: { - code: string; - }; - query: { - languageCode?: string; + customer: string; }; }; responses: { @@ -2252,31 +2764,21 @@ export interface operations { 200: { content: { "application/json": { - name: string; - value: string; - }[]; + results: { + id: number; + name: string; + }[]; + }; }; }; }; }; - /** Get all the customers you have access to */ - "get-customers": { - parameters: {}; - responses: { - /** An array of Customer objects */ - 200: { - content: { - "application/json": { - id?: number; - name?: string; - }[]; - }; + "post-customers-customer-projects": { + parameters: { + path: { + customer: string; }; - 403: components["responses"]["NotFound"]; }; - }; - "post-customers": { - parameters: {}; responses: { /** OK */ 200: { @@ -2296,24 +2798,6 @@ export interface operations { }; }; }; - "get-customUserFields": { - parameters: {}; - responses: { - /** OK */ - 200: { - content: { - "application/json": { - group: { - id: number; - name: components["schemas"]["TranslatablePage"]; - description?: components["schemas"]["TranslatablePage"]; - }; - fields?: components["schemas"]["CustomUserFieldsData"][]; - }[]; - }; - }; - }; - }; /** Get all model of devices with theirs manufacturers */ "get-devices-devices-type-model": { parameters: { @@ -2393,39 +2877,153 @@ export interface operations { 404: components["responses"]["NotFound"]; }; }; - /** Get all education levels */ - "get-education": { + "post-dossiers": { + parameters: {}; responses: { - /** OK */ - 200: { + /** Created */ + 201: { content: { "application/json": { id: number; - name: string; - }[]; + /** @enum {string} */ + message?: "HOOK_FAILED"; + }; + }; + }; + /** Partial Content */ + 206: { + content: { + "application/json": { + id?: number; + }; + }; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["DossierCreationData"] & { + duplicate?: { + campaign?: number; + fields?: number; + mailMerges?: number; + pages?: number; + testers?: number; + useCases?: number; + }; + } & { + autoApply?: number; + bugLanguage?: components["schemas"]["BugLang"]; + hasBugForm?: number; + hasBugParade?: number; + /** @enum {string} */ + pageVersion?: "v1" | "v2"; + /** @default 0 */ + skipPagesAndTasks?: number; }; }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; }; }; - /** Get all employments */ - "get-employments": { + "get-dossiers-campaign": { + parameters: { + path: { + /** A campaign id */ + campaign: string; + }; + }; responses: { /** OK */ 200: { content: { "application/json": { + autoApply: number; + browsers?: { + id: number; + name: string; + }[]; + /** Format: date-time */ + closeDate: string; + countries?: components["schemas"]["CountryCode"][]; + csm: { + id: number; + name: string; + }; + customer: { + id: number; + name: string; + }; + description?: string; + deviceList: { + id: number; + name: string; + }[]; + deviceRequirements?: string; + /** Format: date-time */ + endDate: string; + goal?: string; id: number; - name: string; - }[]; + languages?: { + name: string; + }[]; + notes?: string; + outOfScope?: string; + phase: { + id: number; + name: string; + }; + productLink?: string; + productType?: { + id: number; + name: string; + }; + project: { + id: number; + name: string; + }; + roles?: { + role?: { + id: number; + name: string; + }; + user?: { + id: number; + name: string; + surname: string; + }; + }[]; + /** Format: date-time */ + startDate: string; + target?: { + cap?: number; + genderQuote?: string; + notes?: string; + size?: number; + }; + testType: { + id: number; + name: string; + }; + title: { + customer: string; + tester: string; + }; + visibilityCriteria?: { + ageRanges?: { + max: number; + min: number; + }[]; + cuf?: { + cufId: number; + cufValueIds: number[]; + }[]; + gender?: number[]; + province?: string[]; + }; + }; }; }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; }; }; - "post-jotforms-campaignId": { + "put-dossiers-campaign": { parameters: { path: { /** A campaign id */ @@ -2439,61 +3037,70 @@ export interface operations { "application/json": { [key: string]: unknown }; }; }; - /** Forbidden */ - 403: unknown; }; requestBody: { content: { - "application/json": { - formId: string; - testerIdColumn: string; + "application/json": components["schemas"]["DossierCreationData"] & { + autoApply?: number; + bugLanguage?: components["schemas"]["BugLang"] | boolean; + hasBugParade?: number; }; }; }; }; - "get-jotforms": { - parameters: {}; + /** */ + "get-dossiers-campaign-availableTesters": { + parameters: { + path: { + campaign: string; + }; + query: { + refresh?: "1" | "0"; + }; + }; responses: { /** OK */ 200: { content: { "application/json": { - id: string; - name: string; - createdAt: string; - }[]; + count: number; + /** Format: date-time */ + lastUpdate: string; + }; }; }; - /** Forbidden */ - 403: unknown; }; }; - "get-jotforms-forms-formId-questions": { + "post-dossiers-campaign-manual": { parameters: { path: { - formId: string; + /** A campaign id */ + campaign: components["parameters"]["campaign"]; }; }; responses: { /** OK */ 200: { content: { - "application/json": { - id: string; - name: string; - title: string; - description?: string; - type: string; - }[]; + "application/json": { [key: string]: unknown }; + }; + }; + }; + requestBody: { + content: { + "application/json": { + importFrom: number; }; }; - /** Forbidden */ - 403: unknown; }; }; - /** Get all languages */ - "get-languages": { - parameters: {}; + "put-dossiers-campaign-phases": { + parameters: { + path: { + /** A campaign id */ + campaign: string; + }; + }; responses: { /** OK */ 200: { @@ -2501,83 +3108,311 @@ export interface operations { "application/json": { id: number; name: string; - }[]; + }; + }; + }; + }; + requestBody: { + content: { + "application/json": { + phase: number; }; }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; }; }; - /** Get all levels */ - "get-levels": { - parameters: {}; + "post-dossiers-campaign-preview": { + parameters: { + path: { + /** A campaign id */ + campaign: components["parameters"]["campaign"]; + }; + }; responses: { /** OK */ 200: { content: { - "application/json": components["schemas"]["LevelDefinition"][]; + "application/json": { [key: string]: unknown }; + }; + }; + }; + requestBody: { + content: { + "application/json": { + importFrom: number; }; }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; }; }; - /** Send a media for my bug to AppQuality Bucket. */ - "post-media": { - parameters: {}; + "post-dossiers-campaign-quotations": { + parameters: { + path: { + /** A campaign id */ + campaign: string; + }; + }; responses: { - /** OK */ - 200: { + /** Created */ + 201: { content: { "application/json": { - files: { - name: string; - path: string; - }[]; - failed?: { - name: string; - errorCode: string; - }[]; + id?: number; }; }; }; + /** Not Found */ + 404: unknown; }; requestBody: { content: { - "multipart/form-data": { - media?: string | string[]; + "application/json": { + notes?: string; + quote?: string; }; }; }; }; - "delete-media": { - parameters: {}; + "patch-dossiers-campaign-quotations-quote": { + parameters: { + path: { + /** A campaign id */ + campaign: string; + quote: string; + }; + }; responses: { /** OK */ - 200: unknown; + 200: { + content: { + "application/json": { [key: string]: unknown }; + }; + }; + 403: components["responses"]["NotAuthorized"]; 404: components["responses"]["NotFound"]; }; requestBody: { content: { "application/json": { - /** Format: uri */ - url: string; + amount?: string; }; }; }; }; - "get-payments": { + "get-dossiers-campaign-quotes-history": { parameters: { - query: { - /** The status of the payment */ - status?: "pending" | "failed"; - /** How to order values (ASC, DESC) */ - order?: components["parameters"]["order"]; - /** The value to order by */ - orderBy?: "created" | "updated" | "id"; - /** Items to skip for pagination */ - start?: components["parameters"]["start"]; - /** Max items to retrieve */ + path: { + /** A campaign id */ + campaign: string; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + items: { + campaign: { + id: number; + phase_id: number; + phase_name: string; + title: string; + }; + quote: { + amount: string; + id: number; + /** @enum {string} */ + status: "pending" | "proposed" | "approved" | "rejected"; + }; + }[]; + }; + }; + }; + }; + }; + /** Get all education levels */ + "get-education": { + responses: { + /** OK */ + 200: { + content: { + "application/json": { + id: number; + name: string; + }[]; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + /** Get all employments */ + "get-employments": { + responses: { + /** OK */ + 200: { + content: { + "application/json": { + id: number; + name: string; + }[]; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + "get-jotforms": { + parameters: {}; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + createdAt: string; + id: string; + name: string; + }[]; + }; + }; + /** Forbidden */ + 403: unknown; + }; + }; + "get-jotforms-forms-formId-questions": { + parameters: { + path: { + formId: string; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + description?: string; + id: string; + name: string; + title: string; + type: string; + }[]; + }; + }; + /** Forbidden */ + 403: unknown; + }; + }; + "post-jotforms-campaignId": { + parameters: { + path: { + /** A campaign id */ + campaign: string; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { [key: string]: unknown }; + }; + }; + /** Forbidden */ + 403: unknown; + }; + requestBody: { + content: { + "application/json": { + formId: string; + testerIdColumn: string; + }; + }; + }; + }; + /** Get all languages */ + "get-languages": { + parameters: {}; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + id: number; + name: string; + }[]; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + /** Get all levels */ + "get-levels": { + parameters: {}; + responses: { + /** OK */ + 200: { + content: { + "application/json": components["schemas"]["LevelDefinition"][]; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + /** Send a media for my bug to AppQuality Bucket. */ + "post-media": { + parameters: {}; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + failed?: { + errorCode: string; + name: string; + }[]; + files: { + name: string; + path: string; + }[]; + }; + }; + }; + }; + requestBody: { + content: { + "multipart/form-data": { + media?: string | string[]; + }; + }; + }; + }; + "delete-media": { + parameters: {}; + responses: { + /** OK */ + 200: unknown; + 404: components["responses"]["NotFound"]; + }; + requestBody: { + content: { + "application/json": { + /** Format: uri */ + url: string; + }; + }; + }; + }; + "get-payments": { + parameters: { + query: { + /** The status of the payment */ + status?: "pending" | "failed"; + /** How to order values (ASC, DESC) */ + order?: components["parameters"]["order"]; + /** The value to order by */ + orderBy?: "created" | "updated" | "id"; + /** Items to skip for pagination */ + start?: components["parameters"]["start"]; + /** Max items to retrieve */ limit?: components["parameters"]["limit"]; /** Key-value Array for item filtering */ filterBy?: components["parameters"]["filterBy"]; @@ -2588,29 +3423,29 @@ export interface operations { 200: { content: { "application/json": { - limit?: number; - size: number; - start: number; - total?: number; items: { - /** @description The timestamp (GMT) of the request creation */ - created: string; - /** @description The timestamp (GMT) of the request last update */ - updated: string; - id: number; amount: { - value: number; currency: string; + value: number; }; - /** @enum {string} */ - type: "paypal" | "transferwise"; + /** @description The timestamp (GMT) of the request creation */ + created: string; + error?: string; + id: number; tryber: { id: number; name: string; surname: string; }; - error?: string; + /** @enum {string} */ + type: "paypal" | "transferwise"; + /** @description The timestamp (GMT) of the request last update */ + updated: string; }[]; + limit?: number; + size: number; + start: number; + total?: number; }; }; }; @@ -2681,6 +3516,25 @@ export interface operations { 404: components["responses"]["NotFound"]; }; }; + "get-phases": { + responses: { + /** OK */ + 200: { + content: { + "application/json": { + results: { + id: number; + name: string; + type: { + id: number; + name: string; + }; + }[]; + }; + }; + }; + }; + }; /** Retrieve all available popups for admin operations */ "get-popups": { parameters: { @@ -2767,9 +3621,25 @@ export interface operations { }; }; }; - /** Get all users you have access to */ - "get-users": { - responses: { + "get-productTypes": { + parameters: {}; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + results: { + id: number; + name: string; + }[]; + }; + }; + }; + }; + }; + /** Get all users you have access to */ + "get-users": { + responses: { /** OK */ 200: { content: { @@ -2801,19 +3671,19 @@ export interface operations { requestBody: { content: { "application/json": { - name: string; - surname: string; + /** Format: date */ + birthDate: string; + country: string; /** Format: email */ email: string; + name: string; password: string; - country: string; - /** Format: date */ - birthDate: string; /** * @description A referral code (formatted as TESTER_ID-CAMPAIGN_ID) * @example 555-1234 */ referral?: string; + surname: string; }; }; }; @@ -2833,6 +3703,27 @@ export interface operations { 404: unknown; }; }; + "get-users-by-role-role": { + parameters: { + path: { + role: "tester_lead" | "quality_leader" | "ux_researcher" | "assistants"; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + results: { + id: number; + name: string; + surname: string; + }[]; + }; + }; + }; + }; + }; /** Get your user data */ "get-users-me": { parameters: { @@ -2846,53 +3737,53 @@ export interface operations { 200: { content: { "application/json": { - username?: string; - name?: string; - surname?: string; - /** Format: email */ - email?: string; - image?: string; - id: number; - wp_user_id?: number; - role?: string; - is_verified?: boolean; - rank?: string; - total_exp_pts?: number; + additional?: components["schemas"]["AdditionalField"][]; + approved_bugs?: number; + attended_cp?: number; + /** Format: date */ + birthDate?: string; booty?: { - net?: components["schemas"]["Currency"]; gross: components["schemas"]["Currency"]; - }; - pending_booty?: { net?: components["schemas"]["Currency"]; - gross: components["schemas"]["Currency"]; }; + booty_threshold?: { + isOver: boolean; + value: number; + }; + certifications?: components["schemas"]["Certification"][] | boolean; + city?: string; + completionPercent?: number; + country?: string; + education?: { + id: number; + name: string; + }; + /** Format: email */ + email?: string; + gender?: components["schemas"]["Gender"]; + id: number; + image?: string; + is_verified?: boolean; languages?: { name?: string; }[]; + name?: string; onboarding_completed?: boolean; - additional?: components["schemas"]["AdditionalField"][]; - gender?: components["schemas"]["Gender"]; - /** Format: date */ - birthDate?: string; - phone?: string; - education?: { - id: number; - name: string; + pending_booty?: { + gross: components["schemas"]["Currency"]; + net?: components["schemas"]["Currency"]; }; + phone?: string; profession?: { id: number; name: string; }; - certifications?: components["schemas"]["Certification"][] | boolean; - completionPercent?: number; - country?: string; - city?: string; - attended_cp?: number; - approved_bugs?: number; - booty_threshold?: { - value: number; - isOver: boolean; - }; + rank?: string; + role?: string; + surname?: string; + total_exp_pts?: number; + username?: string; + wp_user_id?: number; }; }; }; @@ -2911,10 +3802,10 @@ export interface operations { requestBody: { content: { "application/json": { + email?: string; name?: string; - surname?: string; password?: string; - email?: string; + surname?: string; }; }; }; @@ -2940,50 +3831,50 @@ export interface operations { 200: { content: { "application/json": { - username?: string; - name?: string; - surname?: string; - email?: string; - image?: string; - id: number; - wp_user_id?: number; - role?: string; - is_verified?: boolean; - rank?: string; - total_exp_pts?: number; + additional?: components["schemas"]["AdditionalField"][]; + approved_bugs?: number; + attended_cp?: number; + /** Format: date */ + birthDate?: string; booty?: { gross: components["schemas"]["Currency"]; net?: components["schemas"]["Currency"]; }; - pending_booty?: { - gross: components["schemas"]["Currency"]; - net?: components["schemas"]["Currency"]; + certifications?: components["schemas"]["Certification"][] | boolean; + city?: string; + completionPercent?: number; + country?: string; + education?: { + id: number; + name: string; }; + email?: string; + /** @enum {string} */ + gender?: "male" | "female" | "not-specified" | "other"; + id: number; + image?: string; + is_verified?: boolean; languages?: { id?: number; name?: string; }[]; + name?: string; onboarding_completed?: boolean; - additional?: components["schemas"]["AdditionalField"][]; - /** @enum {string} */ - gender?: "male" | "female" | "not-specified" | "other"; - /** Format: date */ - birthDate?: string; - phone?: string; - education?: { - id: number; - name: string; + pending_booty?: { + gross: components["schemas"]["Currency"]; + net?: components["schemas"]["Currency"]; }; + phone?: string; profession?: { id: number; name: string; }; - certifications?: components["schemas"]["Certification"][] | boolean; - completionPercent?: number; - country?: string; - city?: string; - attended_cp?: number; - approved_bugs?: number; + rank?: string; + role?: string; + surname?: string; + total_exp_pts?: number; + username?: string; + wp_user_id?: number; }; }; }; @@ -2994,21 +3885,21 @@ export interface operations { requestBody: { content: { "application/json": { - name?: string; + birthDate?: string; + city?: string; + country?: string; + education?: number; /** Format: email */ email?: string; - onboarding_completed?: boolean; - surname?: string; /** @enum {string} */ gender?: "male" | "female" | "not-specified" | "other"; - birthDate?: string; + name?: string; + oldPassword?: string; + onboarding_completed?: boolean; + password?: string; phone?: string; - education?: number; profession?: number; - country?: string; - city?: string; - password?: string; - oldPassword?: string; + surname?: string; }; }; }; @@ -3037,12 +3928,12 @@ export interface operations { content: { "application/json": | { - value: string; is_candidate?: boolean; + value: string; }[] | { - value: string; is_candidate?: boolean; + value: string; }; }; }; @@ -3068,10 +3959,10 @@ export interface operations { 200: { content: { "application/json": { + limit?: number; results: ({ id: number; } & components["schemas"]["Bug"])[]; - limit?: number; size?: number; start?: number; total?: number; @@ -3117,10 +4008,10 @@ export interface operations { 200: { content: { "application/json": { + limit?: number; results?: ({ id: number; } & components["schemas"]["Campaign"])[]; - limit?: number; size?: number; start?: number; total?: number; @@ -3144,65 +4035,55 @@ export interface operations { 200: { content: { "application/json": { - id: number; - title: string; - language?: { - code: string; - message: string; - }; - titleRule?: boolean; - minimumMedia: number; - useCases: { - id: number; - name: string; - }[]; additionalFields?: components["schemas"]["CampaignAdditionalField"][]; - bugTypes: { - valid: string[]; + bugReplicability: { invalid: string[]; + valid: string[]; }; bugSeverity: { - valid: string[]; invalid: string[]; - }; - bugReplicability: { valid: string[]; + }; + bugTypes: { invalid: string[]; + valid: string[]; + }; + campaign_type: { + icon: string; + id: number; + name: string; }; - hasBugForm: boolean; devices?: ({ id: number; } & components["schemas"]["UserDevice"])[]; + end_date: string; + goal: string; + hasBugForm: boolean; + hasBugParade: number; + id: number; + language?: { + code: string; + message: string; + }; + minimumMedia: number; + title: string; + titleRule?: boolean; + useCases: { + id: number; + name: string; + }[]; validFileExtensions: string[]; }; }; }; }; }; - "get-users-me-campaigns-campaignId-compatible-devices": { + /** Send a user bug on a specific campaign */ + "post-users-me-campaigns-campaign-bugs": { parameters: { path: { - /** A campaign id */ - campaign: string; - }; - }; - responses: { - /** OK */ - 200: { - content: { - "application/json": components["schemas"]["UserDevice"][]; - }; - }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; - }; - }; - /** Send a user bug on a specific campaign */ - "post-users-me-campaigns-campaign-bugs": { - parameters: { - path: { - /** the campaign id */ - campaignId: string; + /** the campaign id */ + campaignId: string; }; }; responses: { @@ -3210,37 +4091,28 @@ export interface operations { 200: { content: { "application/json": { + additional?: { + slug: string; + value: string; + }[]; + current: string; + description: string; + device: components["schemas"]["UserDevice"]; + expected: string; id: number; internalId?: string; - testerId: number; - title: string; - description: string; + media: string[]; + notes: string; /** @enum {string} */ - status: "PENDING" | "APPROVED" | "REFUSED" | "NEED-REVIEW"; - expected: string; - current: string; + replicability: "ONCE" | "SOMETIMES" | "ALWAYS"; /** @enum {string} */ severity: "LOW" | "MEDIUM" | "HIGH" | "CRITICAL"; /** @enum {string} */ - replicability: "ONCE" | "SOMETIMES" | "ALWAYS"; - /** @enum {string} */ - type: - | "CRASH" - | "GRAPHIC" - | "MALFUNCTION" - | "OTHER" - | "PERFORMANCE" - | "SECURITY" - | "TYPO" - | "USABILITY"; - notes: string; + status: "PENDING" | "APPROVED" | "REFUSED" | "NEED-REVIEW"; + testerId: number; + title: string; + type: string; usecase: string; - device: components["schemas"]["UserDevice"]; - media: string[]; - additional?: { - slug: string; - value: string; - }[]; }; }; }; @@ -3250,33 +4122,24 @@ export interface operations { requestBody: { content: { "application/json": { - title: string; + additional?: { + slug: string; + value: string; + }[]; + current: string; description: string; + device: number; expected: string; - current: string; - /** @enum {string} */ - severity: "LOW" | "MEDIUM" | "HIGH" | "CRITICAL"; + lastSeen: string; + media: string[]; + notes: string; /** @enum {string} */ replicability: "ONCE" | "SOMETIMES" | "ALWAYS"; /** @enum {string} */ - type: - | "CRASH" - | "GRAPHIC" - | "MALFUNCTION" - | "OTHER" - | "PERFORMANCE" - | "SECURITY" - | "TYPO" - | "USABILITY"; - notes: string; - lastSeen: string; + severity: "LOW" | "MEDIUM" | "HIGH" | "CRITICAL"; + title: string; + type: string; usecase: number; - device: number; - media: string[]; - additional?: { - slug: string; - value: string; - }[]; }; }; }; @@ -3309,8 +4172,13 @@ export interface operations { 200: { content: { "application/json": ({ + id: number; question: string; short_name?: string; + validation?: { + error?: string; + regex: string; + }; value?: | number | { @@ -3319,22 +4187,17 @@ export interface operations { } | number[] | string; - validation?: { - regex: string; - error?: string; - }; - id: number; } & ( | { type: components["schemas"]["PreselectionQuestionSimple"]; } | { - type: components["schemas"]["PreselectionQuestionMultiple"]; options: string[]; + type: components["schemas"]["PreselectionQuestionMultiple"]; } | { - type: components["schemas"]["PreselectionQuestionCuf"]; options?: number[]; + type: components["schemas"]["PreselectionQuestionCuf"]; } ))[]; }; @@ -3358,7 +4221,9 @@ export interface operations { requestBody: { content: { "application/json": { + device?: number[]; form?: { + question: number; value: { id?: number | number[]; serialized?: @@ -3369,9 +4234,7 @@ export interface operations { country: string; }; }; - question: number; }[]; - device?: number[]; }; }; }; @@ -3387,17 +4250,17 @@ export interface operations { 200: { content: { "application/json": { - files?: { - name: string; - path: string; - }[]; failed?: { - name: string; /** @enum {string} */ errorCode: | "FILE_TOO_BIG" | "INVALID_FILE_EXTENSION" | "GENERIC_ERROR"; + name: string; + }[]; + files?: { + name: string; + path: string; }[]; }; }; @@ -3411,41 +4274,44 @@ export interface operations { }; }; }; - /** Add one certification to your profile */ - "post-users-me-certifications": { + "get-users-me-campaigns-cid-payout-data": { + parameters: { + path: { + campaignId: string; + }; + }; responses: { - /** Created */ - 201: { + /** OK */ + 200: { content: { - "application/json": - | components["schemas"]["Certification"] - | { - message: string; - }; + "application/json": { + campaign_complete_bonus_eur: number; + campaign_pts: number; + critical_bug_payout: number; + high_bug_payout: number; + low_bug_payout: number; + medium_bug_payout: number; + minimum_bugs: number; + payout_limit: number; + percent_usecases: number; + point_multiplier_critical: number; + point_multiplier_high: number; + point_multiplier_low: number; + point_multiplier_medium: number; + point_multiplier_perfect: number; + point_multiplier_refused: number; + top_tester_bonus: number; + }; }; }; 403: components["responses"]["NotAuthorized"]; - }; - requestBody: { - content: { - "application/json": - | { - certifications: boolean; - } - | { - certification_id: number; - /** Format: date */ - achievement_date: string; - }; - }; + 404: components["responses"]["NotFound"]; }; }; - /** The certification will be removed */ - "delete-users-me-certifications-certificationId": { + "get-users-me-campaigns-cid-preview": { parameters: { path: { - /** The id of the certification */ - certificationId: number; + campaignId: string; }; }; responses: { @@ -3453,7 +4319,39 @@ export interface operations { 200: { content: { "application/json": { - message?: string; + acceptedDevices: { + console?: components["schemas"]["AvailableDevice"][] | "all"; + pc?: components["schemas"]["AvailableDevice"][] | "all"; + smartTv?: components["schemas"]["AvailableDevice"][] | "all"; + smartphone?: components["schemas"]["AvailableDevice"][] | "all"; + smartwatch?: components["schemas"]["AvailableDevice"][] | "all"; + tablet?: components["schemas"]["AvailableDevice"][] | "all"; + }; + cap?: { + free: number; + value: number; + }; + content: string; + endDate: string; + /** @enum {string} */ + selectionStatus?: + | "starting" + | "excluded" + | "ready" + | "complete" + | "not-started"; + startDate: string; + /** @enum {string} */ + status: "available" | "applied" | "excluded" | "selected"; + title: string; + tl?: { + email: string; + name: string; + }; + type: { + icon: string; + name: string; + }; }; }; }; @@ -3461,58 +4359,60 @@ export interface operations { 404: components["responses"]["NotFound"]; }; }; - /** Get all your device data */ - "get-users-me-devices": { + "get-users-me-campaign-campaignId-tasks": { + parameters: { + path: { + campaignId: string; + }; + }; responses: { /** OK */ 200: { content: { - "application/json": ({ - id?: number; - } & components["schemas"]["UserDevice"] & { - [key: string]: unknown; - })[]; + "application/json": { + can_upload_media: boolean; + content: string; + id: number; + is_required: number; + name: string; + /** @enum {string} */ + status: "completed" | "pending"; + }[]; }; }; 403: components["responses"]["NotAuthorized"]; 404: components["responses"]["NotFound"]; }; }; - /** Add a new device to your user */ - "post-users-me-devices": { - responses: { - /** Created */ - 201: { - content: { - "application/json": { - id?: number; - } & components["schemas"]["UserDevice"]; - }; + "post-users-me-campaigns-campaign-tasks-task": { + parameters: { + path: { + /** the campaign id */ + campaignId: string; + taskId: string; }; + }; + responses: { + /** OK */ + 200: unknown; 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; }; requestBody: { content: { "application/json": { - device: - | number - | ( - | "Notebook" - | "Desktop" - | "Ultrabook" - | "Gaming PC" - | "Tablet PC / Hybrid" - ); - operating_system: number; + /** @enum {undefined} */ + status: "completed"; }; }; }; }; - /** Retrieve a single device */ - "get-users-me-devices-deviceId": { + /** Return a list of tester media uploaded on a specific Usecase of a specific Campaign */ + "get-users-me-campaigns-campaignId-tasks-taskId-media": { parameters: { path: { - deviceId: number; + campaignId: string; + taskId: string; }; }; responses: { @@ -3520,19 +4420,22 @@ export interface operations { 200: { content: { "application/json": { - id?: number; - } & components["schemas"]["UserDevice"]; + items: { + id: number; + location: string; + name: string; + }[]; + }; }; }; 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; }; }; - /** The device will be disabled and won't be available for selections and bugs submission. You can't remove a device currently involved in a campaign */ - "delete-users-me-devices-deviceId": { + "post-users-me-campaigns-campaignId-tasks-taskId-media": { parameters: { path: { - deviceId: number; + campaignId: string; + taskId: string; }; }; responses: { @@ -3540,47 +4443,239 @@ export interface operations { 200: { content: { "application/json": { - message?: string; + failed?: { + /** @enum {string} */ + errorCode: + | "FILE_TOO_BIG" + | "INVALID_FILE_EXTENSION" + | "GENERIC_ERROR"; + name: string; + }[]; + files?: { + name: string; + path: string; + }[]; }; }; }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; + }; + requestBody: { + content: { + "multipart/form-data": { + media?: string | string[]; + }; + }; }; }; - /** You can change only operating system version */ - "patch-users-me-devices-deviceId": { + /** Delete a specific media of a specific campaign task if authorized */ + "delete-users-me-campaigns-campaignId-tasks-taskId-media-mediaId": { parameters: { path: { - deviceId: number; + campaignId: string; + taskId: string; + mediaId: string; }; }; responses: { /** OK */ 200: { content: { - "application/json": { - id?: number; - } & components["schemas"]["UserDevice"]; - }; - }; - /** Not Modified */ - 304: { - content: { - "application/json": { - id?: number; - } & components["schemas"]["UserDevice"]; + "application/json": { [key: string]: unknown }; }; }; - 403: components["responses"]["NotAuthorized"]; + /** Forbidden */ + 403: unknown; 404: components["responses"]["NotFound"]; }; - requestBody: { - content: { - "application/json": { - operating_system: number; - }; - }; + }; + "get-users-me-campaigns-campaignId-compatible-devices": { + parameters: { + path: { + /** A campaign id */ + campaign: string; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": components["schemas"]["UserDevice"][]; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + /** Add one certification to your profile */ + "post-users-me-certifications": { + responses: { + /** Created */ + 201: { + content: { + "application/json": + | components["schemas"]["Certification"] + | { + message: string; + }; + }; + }; + 403: components["responses"]["NotAuthorized"]; + }; + requestBody: { + content: { + "application/json": + | { + certifications: boolean; + } + | { + /** Format: date */ + achievement_date: string; + certification_id: number; + }; + }; + }; + }; + /** The certification will be removed */ + "delete-users-me-certifications-certificationId": { + parameters: { + path: { + /** The id of the certification */ + certificationId: number; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + message?: string; + }; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + /** Get all your device data */ + "get-users-me-devices": { + responses: { + /** OK */ + 200: { + content: { + "application/json": ({ + id?: number; + } & components["schemas"]["UserDevice"] & { + [key: string]: unknown; + })[]; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + /** Add a new device to your user */ + "post-users-me-devices": { + responses: { + /** Created */ + 201: { + content: { + "application/json": { + id?: number; + } & components["schemas"]["UserDevice"]; + }; + }; + 403: components["responses"]["NotAuthorized"]; + }; + requestBody: { + content: { + "application/json": { + device: + | number + | ( + | "Notebook" + | "Desktop" + | "Ultrabook" + | "Gaming PC" + | "Tablet PC / Hybrid" + ); + operating_system: number; + }; + }; + }; + }; + /** Retrieve a single device */ + "get-users-me-devices-deviceId": { + parameters: { + path: { + deviceId: number; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + id?: number; + } & components["schemas"]["UserDevice"]; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + /** The device will be disabled and won't be available for selections and bugs submission. You can't remove a device currently involved in a campaign */ + "delete-users-me-devices-deviceId": { + parameters: { + path: { + deviceId: number; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + message?: string; + }; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + }; + /** You can change only operating system version */ + "patch-users-me-devices-deviceId": { + parameters: { + path: { + deviceId: number; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + id?: number; + } & components["schemas"]["UserDevice"]; + }; + }; + /** Not Modified */ + 304: { + content: { + "application/json": { + id?: number; + } & components["schemas"]["UserDevice"]; + }; + }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; + }; + requestBody: { + content: { + "application/json": { + operating_system: number; + }; + }; }; }; /** Get all the experience points earned in AppQuality. */ @@ -3608,27 +4703,27 @@ export interface operations { 200: { content: { "application/json": { + limit?: number; results: { - id: number; activity: { id: number; }; + amount: number; campaign: { id: number; title?: string; }; /** Format: date */ date: string; - amount: number; + id: number; note?: string; }[]; - limit?: number; size?: number; start?: number; - /** @description The total number of experience entries */ - total?: number; /** @description The total sum of experience */ sum: number; + /** @description The total number of experience entries */ + total?: number; }; }; }; @@ -3644,14 +4739,13 @@ export interface operations { content: { "application/json": { address: { + city: string; + cityCode: string; country: string; province: string; - city: string; street: string; streetNumber?: string; - cityCode: string; }; - type: components["schemas"]["FiscalType"] | "internal"; birthPlace: { city?: string; province?: string; @@ -3661,6 +4755,7 @@ export interface operations { fiscalStatus: "Verified" | "Unverified"; /** @enum {string} */ gender: "male" | "female"; + type: components["schemas"]["FiscalType"] | "internal"; }; }; }; @@ -3676,14 +4771,13 @@ export interface operations { content: { "application/json": { address: { + city: string; + cityCode: string; country: string; province: string; - city: string; street: string; streetNumber?: string; - cityCode: string; }; - type: components["schemas"]["FiscalType"]; birthPlace?: { city?: string; province?: string; @@ -3693,6 +4787,7 @@ export interface operations { fiscalStatus: "Verified" | "Unverified"; /** @enum {string} */ gender: "male" | "female"; + type: components["schemas"]["FiscalType"]; }; }; }; @@ -3702,18 +4797,18 @@ export interface operations { content: { "application/json": { address: { + city: string; + cityCode: string; country: string; province: string; - city: string; street: string; streetNumber: string; - cityCode: string; }; - type: components["schemas"]["FiscalType"]; birthPlace?: components["schemas"]["FiscalBirthCity"]; fiscalId: string; /** @enum {string} */ gender: "male" | "female"; + type: components["schemas"]["FiscalType"]; }; }; }; @@ -3726,14 +4821,13 @@ export interface operations { content: { "application/json": { address: { + city: string; + cityCode: string; country: string; province: string; - city: string; street: string; streetNumber?: string; - cityCode: string; }; - type: components["schemas"]["FiscalType"]; birthPlace?: { city?: string; province?: string; @@ -3743,6 +4837,7 @@ export interface operations { fiscalStatus: "Verified" | "Unverified"; /** @enum {string} */ gender: "male" | "female"; + type: components["schemas"]["FiscalType"]; }; }; }; @@ -3752,18 +4847,18 @@ export interface operations { content: { "application/json": { address: { + city: string; + cityCode: string; country: string; province: string; - city: string; street: string; streetNumber: string; - cityCode: string; }; - type: components["schemas"]["FiscalType"]; birthPlace?: components["schemas"]["FiscalBirthCity"]; fiscalId: string; /** @enum {string} */ gender: "male" | "female"; + type: components["schemas"]["FiscalType"]; }; }; }; @@ -3799,462 +4894,48 @@ export interface operations { }; }; 403: components["responses"]["NotAuthorized"]; - }; - requestBody: { - content: { - "application/json": { - language_name?: string; - }; - }; - }; - }; - /** The language will be removed from your profile */ - "delete-users-me-languages-languageId": { - parameters: { - path: { - /** The id of the language */ - languageId: number; - }; - }; - responses: { - /** OK */ - 200: { - content: { - "application/json": { - message?: string; - }; - }; - }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; - }; - }; - /** Return all payment requests */ - "get-users-me-payments": { - parameters: { - query: { - /** Items to skip for pagination */ - start?: components["parameters"]["start"]; - /** Max items to retrieve */ - limit?: components["parameters"]["limit"]; - /** The field for item order */ - orderBy?: string; - /** How to order values (ASC, DESC) */ - order?: components["parameters"]["order"]; - }; - }; - responses: { - /** OK */ - 200: { - content: { - "application/json": { - results?: ({ - id: number; - } & { - /** @enum {string} */ - status: "paid" | "processing"; - amount: { - net: components["schemas"]["Currency"]; - gross: components["schemas"]["Currency"]; - }; - paidDate: string; - method: { - /** @enum {string} */ - type: "paypal" | "iban"; - note: string; - }; - /** Format: uri-reference */ - receipt?: string; - })[]; - limit?: number; - size: number; - start: number; - total?: number; - }; - }; - }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; - }; - }; - "post-users-me-payments": { - parameters: {}; - responses: { - /** OK */ - 200: { - content: { - "application/json": { - id?: number; - amount?: number; - }; - }; - }; - 403: components["responses"]["NotAuthorized"]; - }; - requestBody: { - content: { - "application/json": { - method: - | { - /** @enum {string} */ - type: "paypal"; - email: string; - } - | { - /** @enum {string} */ - type: "iban"; - accountHolderName: string; - iban: string; - }; - }; - }; - }; - }; - /** Return all attributions of a specific request */ - "get-users-me-payments-payment": { - parameters: { - path: { - payment: string; - }; - query: { - /** Max items to retrieve */ - limit?: components["parameters"]["limit"]; - /** Items to skip for pagination */ - start?: components["parameters"]["start"]; - /** How to order values (ASC, DESC) */ - order?: components["parameters"]["order"]; - /** The value to order by */ - orderBy?: "type" | "date" | "activity" | "net" | "gross"; - }; - }; - responses: { - /** OK */ - 200: { - content: { - "application/json": { - results: ({ - id: number; - } & { - type: string; - amount: { - net?: components["schemas"]["Currency"]; - gross: components["schemas"]["Currency"]; - }; - /** Format: date */ - date: string; - activity: string; - })[]; - limit?: number; - size: number; - total?: number; - start: number; - }; - }; - }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; - }; - }; - /** Return all single attributions that dials the pending booty */ - "get-users-me-pending-booty": { - parameters: { - query: { - /** Items to skip for pagination */ - start?: components["parameters"]["start"]; - /** Max items to retrieve */ - limit?: components["parameters"]["limit"]; - /** The field for item order */ - orderBy?: - | "id" - | "attributionDate" - | "activityName" - | "net" - | "gross" - | "activity"; - /** How to order values (ASC, DESC) */ - order?: components["parameters"]["order"]; - }; - }; - responses: { - /** OK */ - 200: { - content: { - "application/json": { - results?: ({ - id: number; - } & { - name: string; - amount: { - net?: components["schemas"]["Currency"]; - gross: components["schemas"]["Currency"]; - }; - /** Format: date */ - attributionDate: string; - activity: string; - })[]; - limit?: number; - size: number; - start: number; - total?: number; - }; - }; - }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; - }; - }; - /** Return all user permissions */ - "get-users-me-permissions": { - parameters: {}; - responses: { - /** OK */ - 200: { - content: { - "application/json": { - appq_bug?: components["schemas"]["Olp"]; - appq_campaign?: components["schemas"]["Olp"]; - appq_message_center?: components["schemas"]["Olp"]; - appq_prospect?: components["schemas"]["Olp"]; - appq_tester_selection?: components["schemas"]["Olp"]; - }; - }; - }; - 403: components["responses"]["NotAuthorized"]; - /** Internal Server Error */ - 500: unknown; - }; - }; - /** Get all popup defined for your user */ - "get-users-me-popups": { - parameters: { - query: { - /** Show all popup history, expired popups included */ - showExpired?: boolean; - /** How to order values (ASC, DESC) */ - order?: components["parameters"]["order"]; - }; - }; - responses: { - /** OK */ - 200: { - content: { - "application/json": { - id?: number; - title?: string; - content?: string; - once?: boolean; - }[]; - }; - }; - 404: components["responses"]["NotFound"]; - }; - }; - /** Get a single popup. Will set the retrieved popup as expired */ - "get-users-me-popups-popup": { - parameters: { - path: { - popup: number; - }; - }; - responses: { - /** OK */ - 200: { - content: { - "application/json": { - id?: number; - } & components["schemas"]["Popup"]; - }; - }; - }; - }; - "get-users-me-rank": { - parameters: {}; - responses: { - /** OK */ - 200: { - content: { - "application/json": { - level: components["schemas"]["MonthlyLevel"]; - previousLevel: components["schemas"]["MonthlyLevel"]; - rank: number; - points: number; - prospect: { - level: components["schemas"]["MonthlyLevel"]; - maintenance?: number; - next?: { - points: number; - level: components["schemas"]["MonthlyLevel"]; - }; - }; - }; - }; - }; - 403: components["responses"]["NotAuthorized"]; - }; - }; - "get-users-me-rank-list": { - responses: { - /** OK */ - 200: { - content: { - "application/json": { - tops: components["schemas"]["RankingItem"][]; - peers: components["schemas"]["RankingItem"][]; - }; - }; - }; - 403: components["responses"]["NotAuthorized"]; - 404: components["responses"]["NotFound"]; - }; - }; - "post-dossiers": { - parameters: {}; - responses: { - /** Created */ - 201: { - content: { - "application/json": { - id: number; - /** @enum {string} */ - message?: "HOOK_FAILED"; - }; - }; - }; - /** Partial Content */ - 206: { - content: { - "application/json": { - id?: number; - }; - }; - }; - }; - requestBody: { - content: { - "application/json": components["schemas"]["DossierCreationData"] & { - duplicate?: { - fields?: number; - useCases?: number; - mailMerges?: number; - pages?: number; - testers?: number; - campaign?: number; - }; - }; - }; - }; - }; - "get-dossiers-campaign": { - parameters: { - path: { - /** A campaign id */ - campaign: string; - }; - }; - responses: { - /** OK */ - 200: { - content: { - "application/json": { - id: number; - title: { - customer: string; - tester: string; - }; - /** Format: date-time */ - startDate: string; - /** Format: date-time */ - endDate: string; - /** Format: date-time */ - closeDate: string; - customer: { - id: number; - name: string; - }; - project: { - id: number; - name: string; - }; - testType: { - id: number; - name: string; - }; - deviceList: { - id: number; - name: string; - }[]; - csm: { - id: number; - name: string; - }; - roles?: { - role?: { - id: number; - name: string; - }; - user?: { - id: number; - name: string; - surname: string; - }; - }[]; - description?: string; - productLink?: string; - goal?: string; - outOfScope?: string; - deviceRequirements?: string; - target?: { - notes?: string; - size?: number; - cap?: number; - }; - countries?: components["schemas"]["CountryCode"][]; - languages?: { - name: string; - }[]; - browsers?: { - id: number; - name: string; - }[]; - productType?: { - id: number; - name: string; - }; - phase: { - id: number; - name: string; - }; - notes?: string; - }; + }; + requestBody: { + content: { + "application/json": { + language_name?: string; }; }; }; }; - "put-dossiers-campaign": { + /** The language will be removed from your profile */ + "delete-users-me-languages-languageId": { parameters: { path: { - /** A campaign id */ - campaign: string; + /** The id of the language */ + languageId: number; }; }; responses: { /** OK */ 200: { content: { - "application/json": { [key: string]: unknown }; + "application/json": { + message?: string; + }; }; }; - }; - requestBody: { - content: { - "application/json": components["schemas"]["DossierCreationData"]; - }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; }; }; - "get-customers-customer-projects": { + /** Return all payment requests */ + "get-users-me-payments": { parameters: { - path: { - customer: string; + query: { + /** Items to skip for pagination */ + start?: components["parameters"]["start"]; + /** Max items to retrieve */ + limit?: components["parameters"]["limit"]; + /** The field for item order */ + orderBy?: string; + /** How to order values (ASC, DESC) */ + order?: components["parameters"]["order"]; }; }; responses: { @@ -4262,44 +4943,83 @@ export interface operations { 200: { content: { "application/json": { - results: { + limit?: number; + results?: ({ id: number; - name: string; - }[]; + } & { + amount: { + gross: components["schemas"]["Currency"]; + net: components["schemas"]["Currency"]; + }; + method: { + note: string; + /** @enum {string} */ + type: "paypal" | "iban"; + }; + paidDate: string; + /** Format: uri-reference */ + receipt?: string; + /** @enum {string} */ + status: "paid" | "processing"; + })[]; + size: number; + start: number; + total?: number; }; }; }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; }; }; - "post-customers-customer-projects": { - parameters: { - path: { - customer: string; - }; - }; + "post-users-me-payments": { + parameters: {}; responses: { /** OK */ 200: { content: { "application/json": { - id: number; - name: string; + amount?: number; + id?: number; }; }; }; + 403: components["responses"]["NotAuthorized"]; }; requestBody: { content: { "application/json": { - name: string; + method: + | { + email: string; + /** @enum {string} */ + type: "paypal"; + } + | { + accountHolderName: string; + iban: string; + /** @enum {string} */ + type: "iban"; + }; }; }; }; }; - "get-users-by-role-role": { + /** Return all attributions of a specific request */ + "get-users-me-payments-payment": { parameters: { path: { - role: "tester_lead" | "quality_leader" | "ux_researcher" | "assistants"; + payment: string; + }; + query: { + /** Max items to retrieve */ + limit?: components["parameters"]["limit"]; + /** Items to skip for pagination */ + start?: components["parameters"]["start"]; + /** How to order values (ASC, DESC) */ + order?: components["parameters"]["order"]; + /** The value to order by */ + orderBy?: "type" | "date" | "activity" | "net" | "gross"; }; }; responses: { @@ -4307,71 +5027,130 @@ export interface operations { 200: { content: { "application/json": { - results: { + limit?: number; + results: ({ id: number; - name: string; - surname: string; - }[]; + } & { + activity: string; + amount: { + gross: components["schemas"]["Currency"]; + net?: components["schemas"]["Currency"]; + }; + /** Format: date */ + date: string; + type: string; + })[]; + size: number; + start: number; + total?: number; }; }; }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; }; }; - "get-browsers": { + /** Return all single attributions that dials the pending booty */ + "get-users-me-pending-booty": { + parameters: { + query: { + /** Items to skip for pagination */ + start?: components["parameters"]["start"]; + /** Max items to retrieve */ + limit?: components["parameters"]["limit"]; + /** The field for item order */ + orderBy?: + | "id" + | "attributionDate" + | "activityName" + | "net" + | "gross" + | "activity"; + /** How to order values (ASC, DESC) */ + order?: components["parameters"]["order"]; + /** Key-value Array for item filtering */ + filterBy?: components["parameters"]["filterBy"]; + }; + }; responses: { /** OK */ 200: { content: { "application/json": { - results: { + limit?: number; + results?: ({ id: number; + } & { + activity: string; + amount: { + gross: components["schemas"]["Currency"]; + net?: components["schemas"]["Currency"]; + }; + /** Format: date */ + attributionDate: string; name: string; - }[]; + })[]; + size: number; + start: number; + total?: number; }; }; }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; }; }; - "get-productTypes": { + /** Return all user permissions */ + "get-users-me-permissions": { parameters: {}; responses: { /** OK */ 200: { content: { "application/json": { - results: { - id: number; - name: string; - }[]; + appq_bug?: components["schemas"]["Olp"]; + appq_campaign?: components["schemas"]["Olp"]; + appq_message_center?: components["schemas"]["Olp"]; + appq_prospect?: components["schemas"]["Olp"]; + appq_tester_selection?: components["schemas"]["Olp"]; }; }; }; + 403: components["responses"]["NotAuthorized"]; + /** Internal Server Error */ + 500: unknown; }; }; - "get-phases": { + /** Get all popup defined for your user */ + "get-users-me-popups": { + parameters: { + query: { + /** Show all popup history, expired popups included */ + showExpired?: boolean; + /** How to order values (ASC, DESC) */ + order?: components["parameters"]["order"]; + }; + }; responses: { /** OK */ 200: { content: { "application/json": { - results: { - id: number; - name: string; - type: { - id: number; - name: string; - }; - }[]; - }; + content?: string; + id?: number; + once?: boolean; + title?: string; + }[]; }; }; + 404: components["responses"]["NotFound"]; }; }; - "put-dossiers-campaign-phases": { + /** Get a single popup. Will set the retrieved popup as expired */ + "get-users-me-popups-popup": { parameters: { path: { - /** A campaign id */ - campaign: string; + popup: number; }; }; responses: { @@ -4379,18 +5158,50 @@ export interface operations { 200: { content: { "application/json": { - id: number; - name: string; + id?: number; + } & components["schemas"]["Popup"]; + }; + }; + }; + }; + "get-users-me-rank": { + parameters: {}; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + level: components["schemas"]["MonthlyLevel"]; + points: number; + previousLevel: components["schemas"]["MonthlyLevel"]; + prospect: { + level: components["schemas"]["MonthlyLevel"]; + maintenance?: number; + next?: { + level: components["schemas"]["MonthlyLevel"]; + points: number; + }; + }; + rank: number; }; }; }; + 403: components["responses"]["NotAuthorized"]; }; - requestBody: { - content: { - "application/json": { - phase: number; + }; + "get-users-me-rank-list": { + responses: { + /** OK */ + 200: { + content: { + "application/json": { + peers: components["schemas"]["RankingItem"][]; + tops: components["schemas"]["RankingItem"][]; + }; }; }; + 403: components["responses"]["NotAuthorized"]; + 404: components["responses"]["NotFound"]; }; }; } From b6a3a55a725d90a08114dba51ea76680108ad0be Mon Sep 17 00:00:00 2001 From: Kariamos Date: Thu, 23 Oct 2025 17:38:39 +0200 Subject: [PATCH 07/16] feat: update translation keys for wallet expired tab and improve localization --- src/locales/en/translation.json | 10 +++++----- src/locales/es/translation.json | 10 +++++----- src/locales/fr/translation.json | 10 +++++----- src/locales/it/translation.json | 6 +++--- src/pages/Wallet/expiredTabColumns.ts | 8 ++++---- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 08a1e450..bf232a60 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -76,6 +76,7 @@ "Approved bugs": "Approved bugs", "Area is a required field.": "Area is a required field.", "As first step to be done, complete your profile with authentic and real data. This is the only way to be selected for the Campaigns and get your reward.": "Enter your details in the Profile section: they are important to be selected for suitable campaign and to request the payments.", + "Attribution date": "Attribution date", "Available booty": "Available booty", "Available tags \n - Link to help article for fiscal type": { "@@Description for fiscal type@@": "Click here for more info" @@ -216,7 +217,6 @@ "SignupFrom Step1": "Date of birth" }, "Dashboard": "Dashboard", - "Data attribuzione": "", "Date": "Date", "Delete": "Delete", "Delete account": "Delete account", @@ -288,6 +288,7 @@ }, "Gross": "Gross", "Gross amount": "Gross amount", + "Gross total": "Gross total", "Have fun!": "Don't forget to have a good time!", "Here is the list of your all devices. Make sure to keep it updated in order to boost your chances to be selected for further projects.": "Here is the list of your all devices. Make sure to keep it updated in order to boost your chances to be selected for further projects.", "Here you can only change the version of your operating system. If you want to add another device click on \"Add device\"": "Here you can only change the version of your operating system. If you want to add another device click on \"Add device\"", @@ -541,12 +542,10 @@ "This is an invalid format. Should be formatted as +11000000000 or 0011000000000": "This is an invalid format. Should be formatted as +11000000000 or 0011000000000", "This is your personal dashboard. From here you can check out your stats, keep an eye on the progress of your work and find new campaigns to apply for. Have fun!": "This is your personal dashboard. From here you can check out your stats, keep an eye on the progress of your work and find new campaigns to apply for. Have fun!", "This value is invalid, you need to select a city with a province": "This value is invalid, you need to select a city with a province", - "Tipo attività": "", "Title": "Title", "Top 3 | level {{level}}": { "__RANKING_TITLE_LABEL_TOP_LEVEL_MAX: 25": "Top 3 | {{level}} level" }, - "Tot. lordo": "", "Try again.": "Try again.", "Type": "Type", "Type to search your city": "Type to search your city", @@ -688,8 +687,8 @@ "__WALLET_CARD-REQUEST_DISCLAIMER-PROCESSING MAX: 150": "You can request only one payment at a time: you alreay have a payment in process, this may take up to 20 working days.", "__WALLET_CARD-REQUEST_TITLE MAX: 40": "Manage your payment", "__WALLET_CARD-YOUR_WALLET_MAX: 15": "Your wallet", - "__WALLET_EXPIRED_TAB": "", - "__WALLET_HISTORY_TAB": "", + "__WALLET_EXPIRED_TAB": "Expired booties", + "__WALLET_HISTORY_TAB": "Payment history", "__WALLET_HOME-EMPTY_STATE_MAX: 105": "Your payment history is now empty. When you start requesting your payments, you will view them here.", "__WALLET_TABLE-HEADER_CTA-ICON-DETAILS MAX:": "View details", "__WALLET_TABLE-HEADER_CTA-ICON-PDF MAX:": "Download receipt", @@ -799,6 +798,7 @@ "BUGFORM_UPLOAD_PROGRESS": "{{num}} uploaded", "BUGFORM_UPLOAD_PROGRESS_plural": "{{num}} uploaded" }, + "Tipo attività": "", "Report a Bug": "", "Page Preview": "", "/my-account/": "/my-account/", diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index b10e4fbf..aaca07c3 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -76,6 +76,7 @@ "Approved bugs": "Bugs aprobados", "Area is a required field.": "El área / La esfera es un campo obligatorio", "As first step to be done, complete your profile with authentic and real data. This is the only way to be selected for the Campaigns and get your reward.": "Añade todos tus datos en la sección Perfil: los necesitaremos para seleccionarte cuando haya una campaña adecuada y para que puedas solicitar los pagos.", + "Attribution date": "Fecha de atribución", "Available booty": "Saldo Disponible", "Available tags \n - Link to help article for fiscal type": { "@@Description for fiscal type@@": "Haga clic aquí para obtener más información" @@ -216,7 +217,6 @@ "SignupFrom Step1": "Fecha de nacimiento" }, "Dashboard": "Dashboard", - "Data attribuzione": "", "Date": "Fecha", "Delete": "Eliminar", "Delete account": "Elímina account", @@ -288,6 +288,7 @@ }, "Gross": "Bruto", "Gross amount": "Cantidad bruta", + "Gross total": "Total bruto", "Have fun!": "¡No te olvides de pasarlo bien!", "Here is the list of your all devices. Make sure to keep it updated in order to boost your chances to be selected for further projects.": "Aquí está la lista de todos tus dispositivos. Asegúrete de mantenerla actualizada para aumentar tus posibilidades de ser seleccionado para proyectos futuros.", "Here you can only change the version of your operating system. If you want to add another device click on \"Add device\"": "Aquí solo puedes cambiar la versión de tu sistema operativo. Si deseas agregar otro dispositivo, haga clic en \"Agregar dispositivo\"", @@ -541,12 +542,10 @@ "This is an invalid format. Should be formatted as +11000000000 or 0011000000000": "Este es un formato no válido. Tiene que ser formateado como +11000000000 o 0011000000000", "This is your personal dashboard. From here you can check out your stats, keep an eye on the progress of your work and find new campaigns to apply for. Have fun!": "Este es tu dashboard personal. Desde aquí puedes consultar tus estadísticas, el progreso de tu trabajo y encontrar nuevas Campañas a las que postularte. ¡Diviértete!", "This value is invalid, you need to select a city with a province": "Este valor no es válido, es necesario seleccionar una ciudad con una provincia", - "Tipo attività": "", "Title": "Título", "Top 3 | level {{level}}": { "__RANKING_TITLE_LABEL_TOP_LEVEL_MAX: 25": "Top 3 | Nivel {{level}}" }, - "Tot. lordo": "", "Try again.": "Inténtelo de nuevo.", "Type": "Tipo", "Type to search your city": "Escriba para buscar tu ciudad", @@ -688,8 +687,8 @@ "__WALLET_CARD-REQUEST_DISCLAIMER-PROCESSING MAX: 150": "Solo puedes solicitar un pago a la vez: ya tienes una solicitud pendiente, ésta puede tardar hasta 20 días laborables.", "__WALLET_CARD-REQUEST_TITLE MAX: 40": "Gestiona el pago", "__WALLET_CARD-YOUR_WALLET_MAX: 15": "Tu monedero", - "__WALLET_EXPIRED_TAB": "", - "__WALLET_HISTORY_TAB": "", + "__WALLET_EXPIRED_TAB": "Ingresos caducados", + "__WALLET_HISTORY_TAB": "Historial de pagos", "__WALLET_HOME-EMPTY_STATE_MAX: 105": "Aún no has solicitado ningun pago. Cuando lo harás, podrás ver tus pagos aquí.", "__WALLET_TABLE-HEADER_CTA-ICON-DETAILS MAX:": "Ver detalles", "__WALLET_TABLE-HEADER_CTA-ICON-PDF MAX:": "Descargar recibo", @@ -799,6 +798,7 @@ "BUGFORM_UPLOAD_PROGRESS": "{{num}} subido", "BUGFORM_UPLOAD_PROGRESS_plural": "{{num}} subidos" }, + "Tipo attività": "", "Report a Bug": "", "Page Preview": "Page Preview", "/my-account/": "/perfil/", diff --git a/src/locales/fr/translation.json b/src/locales/fr/translation.json index 20ef7be8..aa825f64 100644 --- a/src/locales/fr/translation.json +++ b/src/locales/fr/translation.json @@ -76,6 +76,7 @@ "Approved bugs": "Bugs approuvés", "Area is a required field.": "Le domaine est un champ obligatoire.", "As first step to be done, complete your profile with authentic and real data. This is the only way to be selected for the Campaigns and get your reward.": "Indiquez vos coordonnées dans la section Profil : elles sont importantes pour être sélectionné pour des campagnes adaptées et pour demander les paiements.", + "Attribution date": "Date d'attribution", "Available booty": "Butin disponible", "Available tags \n - Link to help article for fiscal type": { "@@Description for fiscal type@@": "Cliquez ici pour plus d'infos" @@ -216,7 +217,6 @@ "SignupFrom Step1": "Date de naissance" }, "Dashboard": "Tableau de bord", - "Data attribuzione": "", "Date": "Date", "Delete": "Supprimer", "Delete account": "Supprimer le compte", @@ -288,6 +288,7 @@ }, "Gross": "Brut", "Gross amount": "Montant brut", + "Gross total": "Total brut", "Have fun!": "N'oubliez pas de vous amuser !", "Here is the list of your all devices. Make sure to keep it updated in order to boost your chances to be selected for further projects.": "Voici la liste de tous vos appareils. Assurez-vous de la tenir à jour pour augmenter vos chances d'être sélectionné pour d'autres projets.", "Here you can only change the version of your operating system. If you want to add another device click on \"Add device\"": "Ici, vous ne pouvez changer que la version de votre système d'exploitation. Si vous souhaitez ajouter un autre appareil, cliquez sur \"Ajouter un appareil\"", @@ -541,12 +542,10 @@ "This is an invalid format. Should be formatted as +11000000000 or 0011000000000": "Ce format est invalide. Il doit être formaté comme +11000000000 ou 0011000000000", "This is your personal dashboard. From here you can check out your stats, keep an eye on the progress of your work and find new campaigns to apply for. Have fun!": "Ceci est votre tableau de bord personnel. D'ici, vous pouvez consulter vos statistiques, surveiller l'avancement de votre travail et trouver de nouvelles campagnes pour lesquelles postuler. Amusez-vous bien !", "This value is invalid, you need to select a city with a province": "Cette valeur est invalide, vous devez sélectionner une ville avec une province", - "Tipo attività": "", "Title": "Titre", "Top 3 | level {{level}}": { "__RANKING_TITLE_LABEL_TOP_LEVEL_MAX: 25": "Top 3 | niveau {{level}}" }, - "Tot. lordo": "", "Try again.": "Réessayez.", "Type": "Type", "Type to search your city": "Tapez pour rechercher votre ville", @@ -688,8 +687,8 @@ "__WALLET_CARD-REQUEST_DISCLAIMER-PROCESSING MAX: 150": "Vous ne pouvez demander qu'un paiement à la fois : vous avez déjà un paiement en cours, cela peut prendre jusqu'à 20 jours ouvrables.", "__WALLET_CARD-REQUEST_TITLE MAX: 40": "Gérez votre paiement", "__WALLET_CARD-YOUR_WALLET_MAX: 15": "Votre portefeuille", - "__WALLET_EXPIRED_TAB": "", - "__WALLET_HISTORY_TAB": "", + "__WALLET_EXPIRED_TAB": "Butin expiré", + "__WALLET_HISTORY_TAB": "Historique des paiements", "__WALLET_HOME-EMPTY_STATE_MAX: 105": "Votre historique de paiement est actuellement vide. Lorsque vous commencerez à demander vos paiements, vous les verrez ici.", "__WALLET_TABLE-HEADER_CTA-ICON-DETAILS MAX:": "Voir les détails", "__WALLET_TABLE-HEADER_CTA-ICON-PDF MAX:": "Télécharger le reçu", @@ -799,6 +798,7 @@ "BUGFORM_UPLOAD_PROGRESS": "{{num}} téléchargé", "BUGFORM_UPLOAD_PROGRESS_plural": "{{num}} téléchargés" }, + "Tipo attività": "", "Report a Bug": "", "{{date}} {{at_time}} {{time}}": "", "Page Preview": "Page Preview", diff --git a/src/locales/it/translation.json b/src/locales/it/translation.json index 6fdf07b2..0b0a7771 100644 --- a/src/locales/it/translation.json +++ b/src/locales/it/translation.json @@ -76,6 +76,7 @@ "Approved bugs": "Bug approvati", "Area is a required field.": "L'area è un campo obbligatorio", "As first step to be done, complete your profile with authentic and real data. This is the only way to be selected for the Campaigns and get your reward.": "Inserisci tutti i tuoi dati nella sezione Profilo: servirà a noi per selezionarti quando c'è una campagna adatta e a te per richiedere il pagamento.", + "Attribution date": "Data di attribuzione", "Available booty": "Guadagni disponibili", "Available tags \n - Link to help article for fiscal type": { "@@Description for fiscal type@@": "Clicca qui per maggiori informazioni" @@ -216,7 +217,6 @@ "SignupFrom Step1": "Data di nascita" }, "Dashboard": "Dashboard", - "Data attribuzione": "", "Date": "Data", "Delete": "Rimuovi", "Delete account": "Elimina account", @@ -288,6 +288,7 @@ }, "Gross": "Lordo", "Gross amount": "Lordo", + "Gross total": "Tot. Lordo", "Have fun!": "Ricordati di divertirti!", "Here is the list of your all devices. Make sure to keep it updated in order to boost your chances to be selected for further projects.": "Ecco la lista dei tuoi dispositivi. Assicurati di tenerla sempre aggiornata per aumentare le possibilità di essere selezionat* nei prossimi progetti.", "Here you can only change the version of your operating system. If you want to add another device click on \"Add device\"": "Qui puoi solo cambiare la versione del tuo sistema operativo. Se vuoi aggiungere un altro dispositivo clicca su \"Aggiungi dispositivo\"", @@ -541,12 +542,10 @@ "This is an invalid format. Should be formatted as +11000000000 or 0011000000000": "Formato invalido. Deve essere formattato come +11000000000 o 0011000000000", "This is your personal dashboard. From here you can check out your stats, keep an eye on the progress of your work and find new campaigns to apply for. Have fun!": "Questa è la tua dashboard personale. Da qui puoi controllare le tue statistiche, tenere d'occhio lo stato di avanzamento del tuo lavoro e trovare nuove campagne a cui candidarti. Divertiti!", "This value is invalid, you need to select a city with a province": "Questo valore è invalido, devi selezionare una città con una provincia", - "Tipo attività": "", "Title": "Titolo", "Top 3 | level {{level}}": { "__RANKING_TITLE_LABEL_TOP_LEVEL_MAX: 25": "Top 3 | Livello {{level}}" }, - "Tot. lordo": "", "Try again.": "Riprova", "Type": "Tipo", "Type to search your city": "Digita per cercare la tua città", @@ -799,6 +798,7 @@ "BUGFORM_UPLOAD_PROGRESS": "{{num}} caricato", "BUGFORM_UPLOAD_PROGRESS_plural": "{{num}} caricati" }, + "Tipo attività": "", "Report a Bug": "Carica un Bug", "Page Preview": "Pagina di preview", "/my-account/": "/it/il-mio-account/", diff --git a/src/pages/Wallet/expiredTabColumns.ts b/src/pages/Wallet/expiredTabColumns.ts index 19baa4c6..fb0a015c 100644 --- a/src/pages/Wallet/expiredTabColumns.ts +++ b/src/pages/Wallet/expiredTabColumns.ts @@ -8,20 +8,20 @@ export const expiredTabColumns = ( ): Column[] => { return [ { - title: "Nome attività", + title: t("Activity name"), dataIndex: "activityName", key: "activityName", maxWidth: "max-content", }, { - title: t("Tipo attività"), + title: t("Activity"), dataIndex: "activityType", key: "activityType", role: "overline", hideIndex: true, }, { - title: t("Data attribuzione"), + title: t("Attribution date"), dataIndex: "attributionDate", key: "attributionDate", isSortable: true, @@ -30,7 +30,7 @@ export const expiredTabColumns = ( }, }, { - title: t("Tot. lordo"), + title: t("Gross total"), dataIndex: "gross", key: "gross", isSortable: true, From b2c0f70465749b71cd43d1a6fa701c253a7db6a0 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Thu, 23 Oct 2025 17:51:04 +0200 Subject: [PATCH 08/16] feat: add wallet card expiration disclaimer to localization and UI --- src/locales/en/translation.json | 1 + src/locales/es/translation.json | 1 + src/locales/fr/translation.json | 1 + src/locales/it/translation.json | 1 + src/pages/Wallet/WalletManagment.tsx | 4 ++++ 5 files changed, 8 insertions(+) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index bf232a60..f9cb658c 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -677,6 +677,7 @@ "__RANKING_TITLE_LABEL_POSITION_MAX: 15": "Position", "__RANKING_TITLE_WELCOM_MAX: 20": "Ranking", "__SELECT_DEFAULT_NO_OPTION": "No options", + "__WALLET_CARD-EXPIRATION_DISCLAIMER": "Keep in mind: every booty is valid for 12 months", "__WALLET_CARD-GUIDES_CTA MAX: 20": "Read our guides", "__WALLET_CARD-GUIDES_PARAGRAPH MAX: 60": "Discover how we manage your payment requests.", "__WALLET_CARD-GUIDES_TITLE MAX: 35": "Any questions on payment process?", diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index aaca07c3..d58ff176 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -677,6 +677,7 @@ "__RANKING_TITLE_LABEL_POSITION_MAX: 15": "Posición", "__RANKING_TITLE_WELCOM_MAX: 20": "Clasificación", "__SELECT_DEFAULT_NO_OPTION": "sin opciones", + "__WALLET_CARD-EXPIRATION_DISCLAIMER": "Cada en cuenta: cada ingreso es válido por 12 meses", "__WALLET_CARD-GUIDES_CTA MAX: 20": "Nuestras guías", "__WALLET_CARD-GUIDES_PARAGRAPH MAX: 60": "Descubre cómo gestionamos tus solicitudes de pago", "__WALLET_CARD-GUIDES_TITLE MAX: 35": "¿Dudas sobre el proceso de pago?", diff --git a/src/locales/fr/translation.json b/src/locales/fr/translation.json index aa825f64..ca75c432 100644 --- a/src/locales/fr/translation.json +++ b/src/locales/fr/translation.json @@ -677,6 +677,7 @@ "__RANKING_TITLE_LABEL_POSITION_MAX: 15": "Position", "__RANKING_TITLE_WELCOM_MAX: 20": "Classement", "__SELECT_DEFAULT_NO_OPTION": "Aucune option", + "__WALLET_CARD-EXPIRATION_DISCLAIMER": "Notez bien: chaque butin est valable pendant 12 mois.", "__WALLET_CARD-GUIDES_CTA MAX: 20": "Lisez nos guides", "__WALLET_CARD-GUIDES_PARAGRAPH MAX: 60": "Découvrez comment nous gérons vos demandes de paiement.", "__WALLET_CARD-GUIDES_TITLE MAX: 35": "Des questions sur le processus de paiement ?", diff --git a/src/locales/it/translation.json b/src/locales/it/translation.json index 0b0a7771..6bc68c99 100644 --- a/src/locales/it/translation.json +++ b/src/locales/it/translation.json @@ -677,6 +677,7 @@ "__RANKING_TITLE_LABEL_POSITION_MAX: 15": "Posizione", "__RANKING_TITLE_WELCOM_MAX: 20": "Classifica", "__SELECT_DEFAULT_NO_OPTION": "Nessuna opzione", + "__WALLET_CARD-EXPIRATION_DISCLAIMER": "Ricorda: ogni guadagno è valido per 12 mesi.", "__WALLET_CARD-GUIDES_CTA MAX: 20": "Le nostre guide", "__WALLET_CARD-GUIDES_PARAGRAPH MAX: 60": "Scopri come gestiamo le richieste di pagamenti", "__WALLET_CARD-GUIDES_TITLE MAX: 35": "Domande o dubbi sui pagamenti?", diff --git a/src/pages/Wallet/WalletManagment.tsx b/src/pages/Wallet/WalletManagment.tsx index 89bfa899..18593cd1 100644 --- a/src/pages/Wallet/WalletManagment.tsx +++ b/src/pages/Wallet/WalletManagment.tsx @@ -183,6 +183,10 @@ export const WalletManagment = () => { {getInfoText()} + + + + ); }; From 39c3da93e77a5dc070de0a300ab990157da37d28 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Thu, 23 Oct 2025 17:53:08 +0200 Subject: [PATCH 09/16] feat: update localization for "Expired On" in English, Spanish, French, and Italian --- src/locales/en/translation.json | 2 +- src/locales/es/translation.json | 2 +- src/locales/fr/translation.json | 2 +- src/locales/it/translation.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index f9cb658c..2d3e1199 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -246,7 +246,7 @@ "End Date": "End Date", "Experience Points": "Experience Points", "Expiration date": "", - "Expired On": "", + "Expired On": "Expired on", "Extra Award": "Extra Award", "FAQ": "FAQ", "Facebook": "Facebook", diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index d58ff176..a9785067 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -246,7 +246,7 @@ "End Date": "Fecha Final", "Experience Points": "Puntos de Experiencia", "Expiration date": "", - "Expired On": "", + "Expired On": "Caducado el", "Extra Award": "Recompensa Extra", "FAQ": "Preguntas Frecuentes", "Facebook": "Facebook", diff --git a/src/locales/fr/translation.json b/src/locales/fr/translation.json index ca75c432..1c06eb20 100644 --- a/src/locales/fr/translation.json +++ b/src/locales/fr/translation.json @@ -246,7 +246,7 @@ "End Date": "Date de fin", "Experience Points": "Points d'expérience", "Expiration date": "", - "Expired On": "", + "Expired On": "Expiré le", "Extra Award": "Récompense supplémentaire", "FAQ": "FAQ", "Facebook": "Facebook", diff --git a/src/locales/it/translation.json b/src/locales/it/translation.json index 6bc68c99..f8a7f738 100644 --- a/src/locales/it/translation.json +++ b/src/locales/it/translation.json @@ -246,7 +246,7 @@ "End Date": "Fine", "Experience Points": "Punti esperienza", "Expiration date": "", - "Expired On": "", + "Expired On": "Scaduto il", "Extra Award": "Premio extra", "FAQ": "Domande frequenti", "Facebook": "Facebook", From bb9ac11e1a38b1a5ecd3034abf61ab20b81b23d9 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Thu, 23 Oct 2025 18:04:13 +0200 Subject: [PATCH 10/16] feat: add description for expired wallet tab in English, Spanish, French, and Italian --- src/locales/en/translation.json | 1 + src/locales/es/translation.json | 1 + src/locales/fr/translation.json | 1 + src/locales/it/translation.json | 1 + src/pages/Wallet/WalletTable.tsx | 8 +++++++- 5 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 2d3e1199..151782ec 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -689,6 +689,7 @@ "__WALLET_CARD-REQUEST_TITLE MAX: 40": "Manage your payment", "__WALLET_CARD-YOUR_WALLET_MAX: 15": "Your wallet", "__WALLET_EXPIRED_TAB": "Expired booties", + "__WALLET_EXPIRED_TAB-DESCRIPTION": "List of expired booty, for which more than 12 months have passed and it is no longer possible to request payment", "__WALLET_HISTORY_TAB": "Payment history", "__WALLET_HOME-EMPTY_STATE_MAX: 105": "Your payment history is now empty. When you start requesting your payments, you will view them here.", "__WALLET_TABLE-HEADER_CTA-ICON-DETAILS MAX:": "View details", diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index a9785067..83a9ed37 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -689,6 +689,7 @@ "__WALLET_CARD-REQUEST_TITLE MAX: 40": "Gestiona el pago", "__WALLET_CARD-YOUR_WALLET_MAX: 15": "Tu monedero", "__WALLET_EXPIRED_TAB": "Ingresos caducados", + "__WALLET_EXPIRED_TAB-DESCRIPTION": "Lista de ingresos caducados, para los cuales han pasado más de 12 meses y ya no es posible solicitar el pago", "__WALLET_HISTORY_TAB": "Historial de pagos", "__WALLET_HOME-EMPTY_STATE_MAX: 105": "Aún no has solicitado ningun pago. Cuando lo harás, podrás ver tus pagos aquí.", "__WALLET_TABLE-HEADER_CTA-ICON-DETAILS MAX:": "Ver detalles", diff --git a/src/locales/fr/translation.json b/src/locales/fr/translation.json index 1c06eb20..35246972 100644 --- a/src/locales/fr/translation.json +++ b/src/locales/fr/translation.json @@ -689,6 +689,7 @@ "__WALLET_CARD-REQUEST_TITLE MAX: 40": "Gérez votre paiement", "__WALLET_CARD-YOUR_WALLET_MAX: 15": "Votre portefeuille", "__WALLET_EXPIRED_TAB": "Butin expiré", + "__WALLET_EXPIRED_TAB-DESCRIPTION": "Liste du butin expiré, pour lequel plus de 12 mois se sont écoulés et il n’est plus possible de demander le paiement", "__WALLET_HISTORY_TAB": "Historique des paiements", "__WALLET_HOME-EMPTY_STATE_MAX: 105": "Votre historique de paiement est actuellement vide. Lorsque vous commencerez à demander vos paiements, vous les verrez ici.", "__WALLET_TABLE-HEADER_CTA-ICON-DETAILS MAX:": "Voir les détails", diff --git a/src/locales/it/translation.json b/src/locales/it/translation.json index f8a7f738..385cceb3 100644 --- a/src/locales/it/translation.json +++ b/src/locales/it/translation.json @@ -689,6 +689,7 @@ "__WALLET_CARD-REQUEST_TITLE MAX: 40": "Gestisci il pagamento", "__WALLET_CARD-YOUR_WALLET_MAX: 15": "Il tuo portafoglio", "__WALLET_EXPIRED_TAB": "Guadagni scaduti", + "__WALLET_EXPIRED_TAB-DESCRIPTION": "Elenco dei guadagni scaduti, per i quali sono trascorsi più di 12 mesi e non è più possibile richiedere il pagamento", "__WALLET_HISTORY_TAB": "Cronologia pagamenti", "__WALLET_HOME-EMPTY_STATE_MAX: 105": "Per ora non hai ancora richiesto un pagamento. Quando inizierai a richiederne, compariranno qui.", "__WALLET_TABLE-HEADER_CTA-ICON-DETAILS MAX:": "Vedi dettagli", diff --git a/src/pages/Wallet/WalletTable.tsx b/src/pages/Wallet/WalletTable.tsx index 68c5128f..6d8019fd 100644 --- a/src/pages/Wallet/WalletTable.tsx +++ b/src/pages/Wallet/WalletTable.tsx @@ -5,9 +5,10 @@ import { Table, TableType, Tabs, + Text, } from "@appquality/appquality-design-system"; import { useEffect, useState } from "react"; -import { useTranslation } from "react-i18next"; +import { Trans, useTranslation } from "react-i18next"; import { shallowEqual, useSelector } from "react-redux"; import detailsIcon from "src/pages/Wallet/assets/details.svg"; import detailsHoverIcon from "src/pages/Wallet/assets/detailsHover.svg"; @@ -331,6 +332,11 @@ export const WalletTable = () => { label={t("Order By", { context: "Sort Table Select" })} /> )} +
+ + + +
Date: Thu, 23 Oct 2025 18:06:37 +0200 Subject: [PATCH 11/16] feat: disable expired tab when there are no expired rows --- src/pages/Wallet/WalletTable.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/Wallet/WalletTable.tsx b/src/pages/Wallet/WalletTable.tsx index 6d8019fd..4b9278c0 100644 --- a/src/pages/Wallet/WalletTable.tsx +++ b/src/pages/Wallet/WalletTable.tsx @@ -320,6 +320,7 @@ export const WalletTable = () => { {t("__WALLET_EXPIRED_TAB")} } From 5adb63c784d231f9f4c7d009b2f069f114914ce4 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Thu, 23 Oct 2025 18:07:03 +0200 Subject: [PATCH 12/16] feat: disable expired tab based on loading state --- src/pages/Wallet/WalletTable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Wallet/WalletTable.tsx b/src/pages/Wallet/WalletTable.tsx index 4b9278c0..67877fe6 100644 --- a/src/pages/Wallet/WalletTable.tsx +++ b/src/pages/Wallet/WalletTable.tsx @@ -320,7 +320,7 @@ export const WalletTable = () => { {t("__WALLET_EXPIRED_TAB")} } From 65a00ee444496e0f3ac0bba8b1594c95fad7ca07 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Thu, 23 Oct 2025 18:53:09 +0200 Subject: [PATCH 13/16] feat: format query parameters for pending booty data retrieval --- src/pages/Wallet/WalletTable.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pages/Wallet/WalletTable.tsx b/src/pages/Wallet/WalletTable.tsx index 67877fe6..cbd50f21 100644 --- a/src/pages/Wallet/WalletTable.tsx +++ b/src/pages/Wallet/WalletTable.tsx @@ -127,7 +127,9 @@ export const WalletTable = () => { }); const { data: expiredBootyData, isLoading: isExpiredBootyLoading } = - useGetUsersMePendingBootyQuery({ filterBy: { isExpired: 1 } }); + useGetUsersMePendingBootyQuery({ + filterBy: { isExpired: 1 }, + }); // initial requests useEffect(() => { const cols = walletColumns(dispatch, t); From eb56b8e53e24e096a7dd887f8104c15fa4bb1ee7 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Thu, 23 Oct 2025 18:57:14 +0200 Subject: [PATCH 14/16] feat: refine parameter serialization for filterBy object in API queries --- src/services/tryberApi/api.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/services/tryberApi/api.ts b/src/services/tryberApi/api.ts index 16b88cde..ee5005a4 100644 --- a/src/services/tryberApi/api.ts +++ b/src/services/tryberApi/api.ts @@ -14,14 +14,14 @@ export const api = createApi({ return; } // iterate over nested objects - if (typeof value === "object") { - Object.entries(params[key]).forEach(([key, value]) => { - if (typeof value === "string") { - urlps.set(`filterBy[${key}]`, value); - } - }); - return; - } + if (key === "filterBy" && value && typeof value === "object") { + Object.entries(value as Record).forEach(([fk, fv]) => { + if (fv != null) { + urlps.set(`filterBy[${fk}]`, String(fv)); + } + }); + return; + } // or just set url param urlps.set(key, value); }); From 5a70ab9ba5e766cd1e50bce99424e4cedfb2e33f Mon Sep 17 00:00:00 2001 From: Davide Bizzi Date: Fri, 24 Oct 2025 10:07:21 +0200 Subject: [PATCH 15/16] feat: Use param serializer for api --- package.json | 2 + .../BootyDetailsModal/BootyDetailsModal.tsx | 3 + src/services/tryberApi/api.ts | 24 +-- yarn.lock | 145 ++++++++++++++++++ 4 files changed, 153 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index ee50c1bb..f80536fb 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "i18next": "^20.2.2", "i18next-browser-languagedetector": "^6.1.0", "lzutf8": "^0.6.0", + "qs": "^6.14.0", "query-string": "^7.0.0", "react": "17.0.2", "react-app-polyfill": "^2.0.0", @@ -102,6 +103,7 @@ "@rtk-query/codegen-openapi": "^1.0.0-alpha.1", "@sentry/cli": "^2.23.0", "@types/node": "^14.14.41", + "@types/qs": "^6.14.0", "@types/react": "17.0.9", "@types/react-dom": "17.0.9", "@types/react-gtm-module": "^2.0.0", diff --git a/src/pages/Wallet/BootyDetailsModal/BootyDetailsModal.tsx b/src/pages/Wallet/BootyDetailsModal/BootyDetailsModal.tsx index 2c2c63c9..84381bdd 100644 --- a/src/pages/Wallet/BootyDetailsModal/BootyDetailsModal.tsx +++ b/src/pages/Wallet/BootyDetailsModal/BootyDetailsModal.tsx @@ -40,6 +40,9 @@ export const BootyDetailsModal = () => { start, order, orderBy, + filterBy: { + isExpired: 0, + }, }); const { results, total } = data || {}; diff --git a/src/services/tryberApi/api.ts b/src/services/tryberApi/api.ts index ee5005a4..f3baa4f9 100644 --- a/src/services/tryberApi/api.ts +++ b/src/services/tryberApi/api.ts @@ -1,32 +1,14 @@ // Need to use the React-specific entry point to import createApi import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"; +import { stringify } from "qs"; // Define a service using a base URL and expected endpoints export const api = createApi({ reducerPath: "tryberApi", baseQuery: fetchBaseQuery({ baseUrl: process.env.REACT_APP_API_URL, - paramsSerializer: (params) => { - let urlps = new URLSearchParams(); - Object.entries(params).forEach(([key, value]) => { - // remove undefined values - if (typeof value === "undefined") { - return; - } - // iterate over nested objects - if (key === "filterBy" && value && typeof value === "object") { - Object.entries(value as Record).forEach(([fk, fv]) => { - if (fv != null) { - urlps.set(`filterBy[${fk}]`, String(fv)); - } - }); - return; - } - // or just set url param - urlps.set(key, value); - }); - return urlps.toString(); - }, + paramsSerializer: (params) => stringify(params, { encodeValuesOnly: true }), + prepareHeaders: (headers, { getState }) => { const { publicUserPages } = getState() as { publicUserPages: { isPublic: boolean; token?: string }; diff --git a/yarn.lock b/yarn.lock index 01f4dd34..20c6cf3d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3592,6 +3592,11 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.7.tgz#5fe8cf91556bfb310d17f2e2b4263a7c12c2c2ca" integrity sha512-HBPgtzp44867rkL+IzQ3560/E/BlobwCjeXsuKqogrcE99SKgZR4tvBBCuNJZMhUFMz26M7cjKWZg785lllwpA== +"@types/qs@^6.14.0": + version "6.14.0" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.14.0.tgz#d8b60cecf62f2db0fb68e5e006077b9178b85de5" + integrity sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ== + "@types/react-dom@*", "@types/react-dom@17.0.9": version "17.0.9" resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.9.tgz#441a981da9d7be117042e1a6fd3dac4b30f55add" @@ -5162,6 +5167,14 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -5170,6 +5183,14 @@ call-bind@^1.0.0, call-bind@^1.0.2: function-bind "^1.1.1" get-intrinsic "^1.0.2" +call-bound@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" + integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== + dependencies: + call-bind-apply-helpers "^1.0.2" + get-intrinsic "^1.3.0" + call-me-maybe@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.2.tgz#03f964f19522ba643b1b0693acb9152fe2074baa" @@ -6482,6 +6503,15 @@ draft-js@^0.11.7: immutable "~3.7.4" object-assign "^4.1.1" +dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + duplexer@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" @@ -6675,6 +6705,16 @@ es-array-method-boxes-properly@^1.0.0: resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== +es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + es-iterator-helpers@^1.0.12, es-iterator-helpers@^1.0.15: version "1.0.15" resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz#bd81d275ac766431d19305923707c3efd9f1ae40" @@ -6695,6 +6735,13 @@ es-iterator-helpers@^1.0.12, es-iterator-helpers@^1.0.15: iterator.prototype "^1.1.2" safe-array-concat "^1.0.1" +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" + integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== + dependencies: + es-errors "^1.3.0" + es-set-tostringtag@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" @@ -7706,6 +7753,22 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@ has-proto "^1.0.1" has-symbols "^1.0.3" +get-intrinsic@^1.2.5, get-intrinsic@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" @@ -7716,6 +7779,14 @@ get-package-type@^0.1.0: resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== +get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + get-stream@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -7885,6 +7956,11 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" +gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" @@ -7957,6 +8033,11 @@ has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== +has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + has-tostringtag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" @@ -8024,6 +8105,13 @@ hasown@^2.0.0: dependencies: function-bind "^1.1.2" +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -9990,6 +10078,11 @@ markdown-it@^14.0.0: punycode.js "^2.3.1" uc.micro "^2.1.0" +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -10632,6 +10725,11 @@ object-inspect@^1.12.3, object-inspect@^1.9.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.0.tgz#42695d3879e1cd5bda6df5062164d80c996e23e2" integrity sha512-HQ4J+ic8hKrgIt3mqk6cVOVrW2ozL4KdvHlqpBv9vDYWx9ysAgENAdvy4FoGF+KFdhR7nQTNm5J0ctAeOwn+3g== +object-inspect@^1.13.3: + version "1.13.4" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" + integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== + object-is@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" @@ -12267,6 +12365,13 @@ qs@^6.11.2: dependencies: side-channel "^1.0.4" +qs@^6.14.0: + version "6.14.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.14.0.tgz#c63fa40680d2c5c941412a0e899c89af60c0a930" + integrity sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w== + dependencies: + side-channel "^1.1.0" + query-string@^4.1.0: version "4.3.4" resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" @@ -13528,6 +13633,35 @@ should@^13.2.1: should-type-adaptors "^1.0.1" should-util "^1.0.0" +side-channel-list@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" + integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + +side-channel-map@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" + integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + +side-channel-weakmap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" + integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + side-channel-map "^1.0.1" + side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" @@ -13537,6 +13671,17 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" +side-channel@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" + integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + side-channel-list "^1.0.0" + side-channel-map "^1.0.1" + side-channel-weakmap "^1.0.2" + signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" From 8d4aaaaeb820f4871ba94222243da75aa1c417a6 Mon Sep 17 00:00:00 2001 From: Davide Bizzi Date: Fri, 24 Oct 2025 11:28:11 +0200 Subject: [PATCH 16/16] fix: Fix pagination and remove order --- src/pages/Wallet/ExpiredAttributionTable.tsx | 118 ++++++++++++++++++ src/pages/Wallet/WalletTable.tsx | 110 +++++----------- ...dTabColumns.ts => useExpiredTabColumns.ts} | 26 ++-- 3 files changed, 157 insertions(+), 97 deletions(-) create mode 100644 src/pages/Wallet/ExpiredAttributionTable.tsx rename src/pages/Wallet/{expiredTabColumns.ts => useExpiredTabColumns.ts} (53%) diff --git a/src/pages/Wallet/ExpiredAttributionTable.tsx b/src/pages/Wallet/ExpiredAttributionTable.tsx new file mode 100644 index 00000000..1ef4b84c --- /dev/null +++ b/src/pages/Wallet/ExpiredAttributionTable.tsx @@ -0,0 +1,118 @@ +import { Pagination, Table } from "@appquality/appquality-design-system"; +import { useTranslation } from "react-i18next"; +import { currencyTable } from "src/redux/wallet/utils"; +import { useGetUsersMePendingBootyQuery } from "src/services/tryberApi"; +import { useExpiredTabColumns } from "./useExpiredTabColumns"; + +const useExpiredRows = ({ start, limit }: { start: number; limit: number }) => { + const { data: expiredBootyData, isLoading: isExpiredBootyLoading } = + useGetUsersMePendingBootyQuery({ + filterBy: { isExpired: 1 }, + start, + limit, + }); + return { + expiredBootyData: (expiredBootyData?.results || []).map((req) => { + const attributionDate = new Date(req.attributionDate); + const expiredDate = new Date(attributionDate); + expiredDate.setMonth(expiredDate.getMonth() + 12); + return { + key: req.id, + activityName: { + title: req.name, + content: {req.name}, + }, + activityType: { + title: req.activity, + content: {req.activity}, + }, + attributionDate: { + title: req.attributionDate, + content: {req.attributionDate}, + }, + gross: { + title: "€ " + req.amount?.gross?.value, + content: ( + + {req.amount?.gross?.currency && + req.amount?.gross?.currency in currencyTable + ? currencyTable[req.amount?.gross?.currency] + : req.amount?.gross?.currency}{" "} + {req.amount?.gross?.value?.toFixed(2)} + + ), + }, + expiredDate: { + title: expiredDate.toISOString().split("T")[0], + content: {expiredDate.toLocaleDateString()}, + }, + }; + }), + isExpiredBootyLoading, + }; +}; + +const ExpiredAttributionTable = ({ + className, + start, + limit, +}: { + className?: string; + start: number; + limit: number; +}) => { + const { t } = useTranslation(); + + const expiredColumns = useExpiredTabColumns(); + + const { expiredBootyData: expiredRows, isExpiredBootyLoading } = + useExpiredRows({ + start, + limit, + }); + return ( +
+ ); +}; + +const ExpiredAttributionTablePagination = ({ + className, + start, + limit, + maxPages, + changePagination, +}: { + className?: string; + start: number; + limit: number; + maxPages: number; + changePagination: (newPage: number) => void; +}) => { + const { t } = useTranslation(); + + return ( + + t(`Page %current% / %total%`) + .replace("%current%", current.toString()) + .replace("%total%", total ? total.toString() : "0") + } + /> + ); +}; +export { ExpiredAttributionTablePagination }; +export default ExpiredAttributionTable; diff --git a/src/pages/Wallet/WalletTable.tsx b/src/pages/Wallet/WalletTable.tsx index cbd50f21..f51cf260 100644 --- a/src/pages/Wallet/WalletTable.tsx +++ b/src/pages/Wallet/WalletTable.tsx @@ -18,6 +18,7 @@ import pdfDisabledIcon from "src/pages/Wallet/assets/pdfDisabled.svg"; import pdfHoverIcon from "src/pages/Wallet/assets/pdfHover.svg"; import twIcon from "src/pages/Wallet/assets/transferwise.svg"; import { walletColumns } from "src/pages/Wallet/columns"; +import useTabFragment from "src/pages/Wallet/WalletTabFragment"; import { useAppDispatch } from "src/redux/provider"; import { updatePagination } from "src/redux/wallet/actionCreator"; import { openPaymentDetailsModal } from "src/redux/wallet/actions/openPaymentDetailsModal"; @@ -27,8 +28,9 @@ import { useGetUsersMePendingBootyQuery, } from "src/services/tryberApi"; import styled from "styled-components"; -import useTabFragment from "src/pages/Wallet/WalletTabFragment"; -import { expiredTabColumns } from "./expiredTabColumns"; +import ExpiredAttributionTable, { + ExpiredAttributionTablePagination, +} from "./ExpiredAttributionTable"; const ActionsCell = styled.div` display: flex; @@ -107,10 +109,10 @@ export const WalletTable = () => { const { t } = useTranslation(); const dispatch = useAppDispatch(); const [columns, setcolumns] = useState([]); - const [expiredColumns, setExpiredColumns] = useState([]); + const expirationTableLimit = 10; + const [expirationTableStart, setExpirationTableStart] = useState(0); const [rows, setRows] = useState([]); - const [expiredRows, setExpiredRows] = useState([]); const { activeTab, setActiveTab } = useTabFragment(); @@ -134,8 +136,6 @@ export const WalletTable = () => { useEffect(() => { const cols = walletColumns(dispatch, t); setcolumns(cols); - const expiredCols = expiredTabColumns(dispatch, t); - setExpiredColumns(expiredCols); }, []); // update datasource for the table useEffect(() => { @@ -243,48 +243,6 @@ export const WalletTable = () => { } }, [data]); - useEffect(() => { - if (typeof expiredBootyData?.results !== "undefined") { - setExpiredRows( - expiredBootyData.results.map((req) => { - const attributionDate = new Date(req.attributionDate); - const expiredDate = new Date(attributionDate); - expiredDate.setMonth(expiredDate.getMonth() + 12); - return { - key: req.id, - activityName: { - title: req.name, - content: {req.name}, - }, - activityType: { - title: req.activity, - content: {req.activity}, - }, - attributionDate: { - title: req.attributionDate, - content: {req.attributionDate}, - }, - gross: { - title: "€ " + req.amount?.gross?.value, - content: ( - - {req.amount?.gross?.currency && - req.amount?.gross?.currency in currencyTable - ? currencyTable[req.amount?.gross?.currency] - : req.amount?.gross?.currency}{" "} - {req.amount?.gross?.value?.toFixed(2)} - - ), - }, - expiredDate: { - title: expiredDate.toISOString().split("T")[0], - content: {expiredDate.toLocaleDateString()}, - }, - }; - }) - ); - } - }, [expiredBootyData]); const changePagination = (newPage: number) => { const newStart = limit * (newPage - 1); dispatch(updatePagination(newStart)); @@ -319,53 +277,47 @@ export const WalletTable = () => { empty: t("__WALLET_HOME-EMPTY_STATE_MAX: 105"), }} /> + + t(`Page %current% / %total%`) + .replace("%current%", current.toString()) + .replace("%total%", total ? total.toString() : "0") + } + /> {t("__WALLET_EXPIRED_TAB")} } > - {columns.length > 0 && ( - - )}

-
+ { + const newStart = expirationTableLimit * (page - 1); + setExpirationTableStart(newStart); }} + start={expirationTableStart} + limit={expirationTableLimit} + maxPages={Math.ceil((data?.total || 0) / expirationTableLimit)} /> - - t(`Page %current% / %total%`) - .replace("%current%", current.toString()) - .replace("%total%", total ? total.toString() : "0") - } - /> ); }; diff --git a/src/pages/Wallet/expiredTabColumns.ts b/src/pages/Wallet/useExpiredTabColumns.ts similarity index 53% rename from src/pages/Wallet/expiredTabColumns.ts rename to src/pages/Wallet/useExpiredTabColumns.ts index fb0a015c..f8a92831 100644 --- a/src/pages/Wallet/expiredTabColumns.ts +++ b/src/pages/Wallet/useExpiredTabColumns.ts @@ -1,16 +1,14 @@ import { Column } from "@appquality/appquality-design-system/dist/stories/table/_types"; -import { TFunction } from "react-i18next"; -import { updateSortingOptions } from "src/redux/wallet/actionCreator"; +import { useTranslation } from "react-i18next"; -export const expiredTabColumns = ( - dispatch: AppDispatch, - t: TFunction<"translation"> -): Column[] => { +export const useExpiredTabColumns = (): Column[] => { + const { t } = useTranslation(); return [ { title: t("Activity name"), dataIndex: "activityName", key: "activityName", + isSortable: false, maxWidth: "max-content", }, { @@ -18,34 +16,26 @@ export const expiredTabColumns = ( dataIndex: "activityType", key: "activityType", role: "overline", + isSortable: false, hideIndex: true, }, { title: t("Attribution date"), dataIndex: "attributionDate", key: "attributionDate", - isSortable: true, - onSort: (newOrder) => { - // dispatch(updateSortingOptions(newOrder, "attributionDate")); - }, + isSortable: false, }, { title: t("Gross total"), dataIndex: "gross", key: "gross", - isSortable: true, - onSort: (newOrder) => { - dispatch(updateSortingOptions(newOrder, "gross")); - }, + isSortable: false, }, { title: t("Expired On"), dataIndex: "expiredDate", key: "expiredDate", - isSortable: true, - onSort: (newOrder: OrderType) => { - // dispatch(updateSortingOptions(newOrder, "expiredDate")); - }, + isSortable: false, }, ]; };