diff --git a/README.md b/README.md index eb0f86049..e56b08383 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,9 @@ Watch releases of this repository to be notified about future updates: ## Contributors ✨ + [![All Contributors](https://img.shields.io/badge/all_contributors-68-orange.svg?style=flat-square)](#contributors-) + Please check [contributors guide](https://github.com/podkrepi-bg/frontend/blob/master/CONTRIBUTING.md) for: diff --git a/public/locales/bg/donations.json b/public/locales/bg/donations.json index eb9ca550f..ac865b20c 100644 --- a/public/locales/bg/donations.json +++ b/public/locales/bg/donations.json @@ -55,6 +55,10 @@ "from": "От", "to": "До", "status": "Статус", - "type": "Тип" + "type": "Тип", + "provider": "Платено по", + "sortBy": "Сортиране", + "minAmount": "Мин сума", + "maxAmount": "Макс сума" } } diff --git a/public/locales/bg/expenses.json b/public/locales/bg/expenses.json index 14ca6b5a4..2913740fd 100644 --- a/public/locales/bg/expenses.json +++ b/public/locales/bg/expenses.json @@ -29,18 +29,18 @@ "internal": "Вътрешен", "operating": "Оперативен", "administrative": "Административен", - "medical" : "Медицински", - "services" : "Услуги", - "groceries" : "Хранителни", - "transport" : "Транспорт", - "accommodation" : "Жилищни", - "shipping" : "Доставки", - "utility" : "Комунални", - "rental" : "Наеми", - "legal" : "Юридически", - "bank" : "Банкови", - "advertising" : "Рекламни", - "other" : "Други" + "medical": "Медицински", + "services": "Услуги", + "groceries": "Хранителни", + "transport": "Транспорт", + "accommodation": "Жилищни", + "shipping": "Доставки", + "utility": "Комунални", + "rental": "Наеми", + "legal": "Юридически", + "bank": "Банкови", + "advertising": "Рекламни", + "other": "Други" }, "alerts": { "new-row": { diff --git a/public/locales/en/donations.json b/public/locales/en/donations.json index f0efdd541..61282c3fe 100644 --- a/public/locales/en/donations.json +++ b/public/locales/en/donations.json @@ -55,6 +55,10 @@ "from": "From", "to": "To", "status": "Status", - "type": "Type" + "type": "Type", + "provider": "Payment", + "sortBy": "Sort By", + "minAmount": "Min amount", + "maxAmount": "Max amount" } } diff --git a/src/common/theme.ts b/src/common/theme.ts index 57d101de2..8641fef99 100644 --- a/src/common/theme.ts +++ b/src/common/theme.ts @@ -1,203 +1,203 @@ -import { - createTheme, - darken, - lighten, - responsiveFontSizes, - Theme, - ThemeOptions, -} from '@mui/material/styles' - -import { Montserrat } from '@next/font/google' - -export const montserrat = Montserrat({ - display: 'auto', - subsets: ['latin', 'cyrillic'], -}) - -const colors = { - blue: { - light: '#4AC3FF', - main: '#32A9FE', - mainDark: darken('#32A9FE', 0.2), - dark: '#294E85', - }, - yellow: { - main: '#FFCB57', - dark: '#F6992B', - }, - gray: { - main: '#F5F5F5', - background: '#FAFAFA', - }, - white: { - main: '#ffffff', - }, -} - -const borders = { - dark: colors.blue.dark, - light: colors.blue.main, - round: '60px', - semiRound: '20px', -} - -export const themeOptions: ThemeOptions = { - palette: { - mode: 'light', - primary: { - light: colors.blue.light, - main: colors.blue.main, - dark: colors.blue.dark, - }, - secondary: { - main: colors.yellow.main, - light: colors.gray.main, - }, - background: { - default: colors.white.main, - }, - info: { - main: colors.blue.dark, - light: colors.blue.mainDark, - dark: darken(colors.blue.dark, 0.2), - }, - }, - shape: { - borderRadius: 3, - }, - components: { - MuiLink: { - defaultProps: { - underline: 'none', - }, - }, - MuiButton: { - defaultProps: { - disableElevation: true, - }, - styleOverrides: { - root: { - lineHeight: 2, - borderRadius: '25px', - borderWidth: 2, - '&:hover': { - borderWidth: 2, - }, - }, - textPrimary: { - color: colors.blue.dark, - '&:hover': { - color: colors.blue.mainDark, - }, - }, - outlined: { - backgroundColor: colors.white.main, - }, - outlinedPrimary: { - color: colors.blue.dark, - '&:hover': { - backgroundColor: lighten(colors.blue.main, 0.85), - }, - }, - outlinedSecondary: { - color: darken(colors.yellow.dark, 0.4), - borderColor: colors.yellow.main, - '&:hover': { - backgroundColor: lighten(colors.yellow.main, 0.85), - borderColor: darken(colors.yellow.main, 0.15), - }, - }, - containedPrimary: { - backgroundColor: colors.blue.main, - '&:hover': { - backgroundColor: darken(colors.blue.main, 0.15), - }, - }, - containedSecondary: { - backgroundColor: colors.yellow.main, - '&:hover': { - backgroundColor: darken(colors.yellow.main, 0.15), - }, - }, - }, - }, - MuiButtonBase: { - defaultProps: { - disableRipple: true, - }, - }, - MuiInputBase: { - styleOverrides: { - root: { - fontSize: '1rem', - borderRadius: borders.round, - }, - multiline: { - borderRadius: borders.semiRound, - }, - }, - }, - MuiFilledInput: { - styleOverrides: { - root: { - borderRadius: borders.round, - }, - multiline: { - borderRadius: borders.semiRound, - }, - }, - }, - MuiOutlinedInput: { - styleOverrides: { - root: { - borderRadius: borders.round, - }, - multiline: { - borderRadius: borders.semiRound, - }, - }, - }, - MuiInputLabel: { - styleOverrides: { - root: { - fontSize: '1rem', - }, - }, - }, - MuiAppBar: { - styleOverrides: { - root: { - paddingLeft: 15, - paddingRight: 15, - }, - }, - }, - - MuiMenuItem: { - defaultProps: { - sx: { py: 1.5 }, - }, - }, - }, - - typography: { - fontFamily: montserrat.style.fontFamily, - h3: { color: colors.blue.dark }, - - body1: { - fontSize: '0.875rem', - lineHeight: '1.43', - letterSpacing: '0.01071em', - }, - button: { textTransform: 'initial' }, - }, -} - -const theme: Theme = createTheme(themeOptions) -const materialTheme = responsiveFontSizes(theme) -const podkrepiTheme = { - borders, - ...materialTheme, -} - -export default podkrepiTheme +import { + createTheme, + darken, + lighten, + responsiveFontSizes, + Theme, + ThemeOptions, +} from '@mui/material/styles' + +import { Montserrat } from '@next/font/google' + +export const montserrat = Montserrat({ + display: 'auto', + subsets: ['latin', 'cyrillic'], +}) + +const colors = { + blue: { + light: '#4AC3FF', + main: '#32A9FE', + mainDark: darken('#32A9FE', 0.2), + dark: '#294E85', + }, + yellow: { + main: '#FFCB57', + dark: '#F6992B', + }, + gray: { + main: '#F5F5F5', + background: '#FAFAFA', + }, + white: { + main: '#ffffff', + }, +} + +const borders = { + dark: colors.blue.dark, + light: colors.blue.main, + round: '60px', + semiRound: '20px', +} + +export const themeOptions: ThemeOptions = { + palette: { + mode: 'light', + primary: { + light: colors.blue.light, + main: colors.blue.main, + dark: colors.blue.dark, + }, + secondary: { + main: colors.yellow.main, + light: colors.gray.main, + }, + background: { + default: colors.white.main, + }, + info: { + main: colors.blue.dark, + light: colors.blue.mainDark, + dark: darken(colors.blue.dark, 0.2), + }, + }, + shape: { + borderRadius: 3, + }, + components: { + MuiLink: { + defaultProps: { + underline: 'none', + }, + }, + MuiButton: { + defaultProps: { + disableElevation: true, + }, + styleOverrides: { + root: { + lineHeight: 2, + borderRadius: '25px', + borderWidth: 2, + '&:hover': { + borderWidth: 2, + }, + }, + textPrimary: { + color: colors.blue.dark, + '&:hover': { + color: colors.blue.mainDark, + }, + }, + outlined: { + backgroundColor: colors.white.main, + }, + outlinedPrimary: { + color: colors.blue.dark, + '&:hover': { + backgroundColor: lighten(colors.blue.main, 0.85), + }, + }, + outlinedSecondary: { + color: darken(colors.yellow.dark, 0.4), + borderColor: colors.yellow.main, + '&:hover': { + backgroundColor: lighten(colors.yellow.main, 0.85), + borderColor: darken(colors.yellow.main, 0.15), + }, + }, + containedPrimary: { + backgroundColor: colors.blue.main, + '&:hover': { + backgroundColor: darken(colors.blue.main, 0.15), + }, + }, + containedSecondary: { + backgroundColor: colors.yellow.main, + '&:hover': { + backgroundColor: darken(colors.yellow.main, 0.15), + }, + }, + }, + }, + MuiButtonBase: { + defaultProps: { + disableRipple: true, + }, + }, + MuiInputBase: { + styleOverrides: { + root: { + fontSize: '1rem', + borderRadius: borders.round, + }, + multiline: { + borderRadius: borders.semiRound, + }, + }, + }, + MuiFilledInput: { + styleOverrides: { + root: { + borderRadius: borders.round, + }, + multiline: { + borderRadius: borders.semiRound, + }, + }, + }, + MuiOutlinedInput: { + styleOverrides: { + root: { + borderRadius: borders.round, + }, + multiline: { + borderRadius: borders.semiRound, + }, + }, + }, + MuiInputLabel: { + styleOverrides: { + root: { + fontSize: '1rem', + }, + }, + }, + MuiAppBar: { + styleOverrides: { + root: { + paddingLeft: 15, + paddingRight: 15, + }, + }, + }, + + MuiMenuItem: { + defaultProps: { + sx: { py: 1.5 }, + }, + }, + }, + + typography: { + fontFamily: montserrat.style.fontFamily, + h3: { color: colors.blue.dark }, + + body1: { + fontSize: '0.875rem', + lineHeight: '1.43', + letterSpacing: '0.01071em', + }, + button: { textTransform: 'initial' }, + }, +} + +const theme: Theme = createTheme(themeOptions) +const materialTheme = responsiveFontSizes(theme) +const podkrepiTheme = { + borders, + ...materialTheme, +} + +export default podkrepiTheme diff --git a/src/components/admin/donations/grid/Grid.tsx b/src/components/admin/donations/grid/Grid.tsx index eaeb371a2..6abb6fe22 100644 --- a/src/components/admin/donations/grid/Grid.tsx +++ b/src/components/admin/donations/grid/Grid.tsx @@ -50,7 +50,7 @@ export default observer(function Grid() { const campaignId = router.query.campaignId as string | undefined const { - data: { items: donations, total: all_rows } = { items: [], total: 0 }, + data: { items: donations, total: allDonationsCount } = { items: [], total: 0 }, error: donationHistoryError, isLoading: isDonationHistoryLoading, refetch, @@ -210,7 +210,7 @@ export default observer(function Grid() { onPageChange={(pageIndex) => setPaginationData({ ...paginationData, pageIndex })} onPageSizeChange={(pageSize) => setPaginationData({ ...paginationData, pageSize })} paginationMode="server" - rowCount={all_rows} + rowCount={allDonationsCount} disableSelectionOnClick isCellEditable={() => true} /> diff --git a/src/components/admin/donations/grid/GridAppbar.tsx b/src/components/admin/donations/grid/GridAppbar.tsx index 881e6831e..da6f31fa4 100644 --- a/src/components/admin/donations/grid/GridAppbar.tsx +++ b/src/components/admin/donations/grid/GridAppbar.tsx @@ -25,7 +25,7 @@ export default function GridAppbar() { const { donationStore } = useStores() const { t } = useTranslation() const exportToExcel = useMutation({ - mutationFn: useExportToExcel(), + mutationFn: useExportToExcel(donationStore.donationFilters, donationStore.donationSearch), onError: () => AlertStore.show(t('common:alerts.error'), 'error'), onSuccess: ({ data }) => { downloadFile('Donations.xlsx', data) diff --git a/src/components/admin/donations/grid/GridFilters.tsx b/src/components/admin/donations/grid/GridFilters.tsx index 19fa001e0..31a044646 100644 --- a/src/components/admin/donations/grid/GridFilters.tsx +++ b/src/components/admin/donations/grid/GridFilters.tsx @@ -2,11 +2,12 @@ import { Box, TextField } from '@mui/material' import Filter from './Filter' import { useStores } from '../../../../common/hooks/useStores' import { observer } from 'mobx-react' -import { DonationStatus, DonationType } from 'gql/donations.enums' +import { DonationStatus, PaymentProvider } from 'gql/donations.enums' import { DateTimePicker, enUS, LocalizationProvider } from '@mui/x-date-pickers' import { useTranslation } from 'react-i18next' import { bg } from 'date-fns/locale' import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns' +import { fromMoney, toMoney } from 'common/util/money' export default observer(function GridFilters() { const { donationStore } = useStores() @@ -18,17 +19,18 @@ export default observer(function GridFilters() { const donationStatusMenuItems = Object.values(DonationStatus) - const donationTypeOptions = { - name: 'type', - label: 'donations:cta.type', + const paymentProviderOptions = { + name: 'paymentProvider', + label: 'donations:cta.provider', } - const donationTypeMenuItems = Object.values(DonationType) + const paymentProviderMenuItems = Object.values(PaymentProvider) const handleChange = ( filterName: string, - filterValue: string | null | { from: Date; to: Date }, + filterValue: string | number | null | { from: Date; to: Date }, ) => { + console.log('Setting filter:', filterName, filterValue) donationStore.setDonationFilters(filterName, filterValue) } @@ -64,6 +66,26 @@ export default observer(function GridFilters() { minDate={donationStore.donationFilters.date?.from} /> + { + handleChange('minAmount', event.target.value ? toMoney(Number(event.target.value)) : null) + }} + variant="outlined" + size="small" + /> + { + handleChange('maxAmount', event.target.value ? toMoney(Number(event.target.value)) : null) + }} + variant="outlined" + size="small" + /> + ) diff --git a/src/components/client/about/helpers/activeMembersData.tsx b/src/components/client/about/helpers/activeMembersData.tsx index 34c58ec30..35a05b7ee 100644 --- a/src/components/client/about/helpers/activeMembersData.tsx +++ b/src/components/client/about/helpers/activeMembersData.tsx @@ -1,117 +1,117 @@ -export type TeamData = { - img: string - name: string - description?: string - linkedInProfile?: string -} - -export const data: TeamData[] = [ - { - img: '/img/team-photos/GratsielaShtereva.jpg', - name: 'Грациела Щeрева', - description: 'Проектен мениджмънт', - linkedInProfile: 'https://www.linkedin.com/in/gratsiela-shtereva-2a9596100/', - }, - { - img: '/img/team-photos/IlkoKacharov.jpg', - name: 'Илко Качаров', - description: 'Софтуерна разработка, Технически лийд', - linkedInProfile: 'https://www.linkedin.com/in/ilko-kacharov/', - }, - { - img: '/img/team-photos/RadianaKoleva.jpg', - name: 'Радиана Колева', - description: 'Маркетинг', - linkedInProfile: 'https://www.linkedin.com/in/radiana-koleva/', - }, - { - img: '/img/team-photos/AniKalpachka.jpg', - name: 'Ани Калпачка', - description: 'Софтуерна разработка, Фронтенд', - linkedInProfile: 'https://www.linkedin.com/in/ani-kalpachka-937170105/', - }, - { - img: '/img/team-photos/NeliRadkova.jpg', - name: 'Нели Радкова', - description: 'Софтуерна разработка', - linkedInProfile: 'https://www.linkedin.com/in/neli-radkova-8771041b6/', - }, - { - img: '/img/team-photos/MarianaGeorgieva.png', - name: 'Мариана Георгиева', - description: 'Дизайн', - linkedInProfile: 'https://www.linkedin.com/in/mariana-georgieva-45302615a', - }, - { - img: '/img/team-photos/AlexanderAlexandrov.jpg', - name: 'Александър Александров', - description: 'PR', - linkedInProfile: 'https://www.linkedin.com/in/alexanderalexandrov/', - }, - { - img: '/img/team-photos/DimitarNizamov.png', - name: 'Димитър Низамов', - description: 'Софтуерна разработка', - linkedInProfile: 'https://www.linkedin.com/in/dimitar-nizamov-9180121a2/', - }, - { - img: '/img/team-photos/JanetaDimitrova.png', - name: 'Жанета Димитрова', - description: 'Кампании', - linkedInProfile: 'https://www.linkedin.com/in/janetadimitrova/', - }, - { - img: '/img/team-photos/NeliTancheva.png', - name: 'Нели Танчева', - description: 'Маркетинг', - linkedInProfile: 'https://www.linkedin.com/in/neli-tancheva-703193169/', - }, - { - img: '/img/team-photos/SlavchoIvanov.png', - name: 'Славчо Иванов', - description: 'Софтуерна разработка', - linkedInProfile: 'https://www.linkedin.com/in/slavchoivanov/', - }, - { - img: '/img/team-photos/HristiyanHristov.png', - name: 'Християн Христов', - description: 'Финанси', - linkedInProfile: 'https://www.linkedin.com/in/християн-христов-hristiyan-hristov-433757238/', - }, - { - img: '/img/team-photos/ChavdarChenkov.png', - name: 'Чавдар Ченков', - description: 'Продуктов мениджмънт', - linkedInProfile: 'https://www.linkedin.com/in/chenkov/', - }, - { - img: '/img/team-photos/AndreyPetrov.png', - name: 'Андрей Петров', - description: 'Маркетинг', - linkedInProfile: 'https://www.linkedin.com/in/andrey-petrov-977887110/', - }, - { - img: '/img/team-photos/YanitaYurukova.png', - name: 'Янина Юрукова', - description: 'Графичен дизайн', - linkedInProfile: 'https://www.linkedin.com/in/yanina-yurukova/', - }, - { - img: '/img/team-photos/LianaZafiri.png', - name: 'Лиана Зафири', - description: 'Дизайн', - linkedInProfile: 'https://www.linkedin.com/in/liana-zafiri-612348239/', - }, - { - img: '/img/team-photos/GeorgiOvcharov.png', - name: 'Георги Овчаров', - description: 'Продуктов мениджмънт', - linkedInProfile: 'https://www.linkedin.com/in/georgi-ovcharov/', - }, - { - img: '/img/team-photos/DilyanaKalinova.png', - name: 'Диляна Калинова', - description: 'Маркетинг', - linkedInProfile: 'https://www.linkedin.com/in/dilyana-kalinova-544762226/', - }, -] +export type TeamData = { + img: string + name: string + description?: string + linkedInProfile?: string +} + +export const data: TeamData[] = [ + { + img: '/img/team-photos/GratsielaShtereva.jpg', + name: 'Грациела Щeрева', + description: 'Проектен мениджмънт', + linkedInProfile: 'https://www.linkedin.com/in/gratsiela-shtereva-2a9596100/', + }, + { + img: '/img/team-photos/IlkoKacharov.jpg', + name: 'Илко Качаров', + description: 'Софтуерна разработка, Технически лийд', + linkedInProfile: 'https://www.linkedin.com/in/ilko-kacharov/', + }, + { + img: '/img/team-photos/RadianaKoleva.jpg', + name: 'Радиана Колева', + description: 'Маркетинг', + linkedInProfile: 'https://www.linkedin.com/in/radiana-koleva/', + }, + { + img: '/img/team-photos/AniKalpachka.jpg', + name: 'Ани Калпачка', + description: 'Софтуерна разработка, Фронтенд', + linkedInProfile: 'https://www.linkedin.com/in/ani-kalpachka-937170105/', + }, + { + img: '/img/team-photos/NeliRadkova.jpg', + name: 'Нели Радкова', + description: 'Софтуерна разработка', + linkedInProfile: 'https://www.linkedin.com/in/neli-radkova-8771041b6/', + }, + { + img: '/img/team-photos/MarianaGeorgieva.png', + name: 'Мариана Георгиева', + description: 'Дизайн', + linkedInProfile: 'https://www.linkedin.com/in/mariana-georgieva-45302615a', + }, + { + img: '/img/team-photos/AlexanderAlexandrov.jpg', + name: 'Александър Александров', + description: 'PR', + linkedInProfile: 'https://www.linkedin.com/in/alexanderalexandrov/', + }, + { + img: '/img/team-photos/DimitarNizamov.png', + name: 'Димитър Низамов', + description: 'Софтуерна разработка', + linkedInProfile: 'https://www.linkedin.com/in/dimitar-nizamov-9180121a2/', + }, + { + img: '/img/team-photos/JanetaDimitrova.png', + name: 'Жанета Димитрова', + description: 'Кампании', + linkedInProfile: 'https://www.linkedin.com/in/janetadimitrova/', + }, + { + img: '/img/team-photos/NeliTancheva.png', + name: 'Нели Танчева', + description: 'Маркетинг', + linkedInProfile: 'https://www.linkedin.com/in/neli-tancheva-703193169/', + }, + { + img: '/img/team-photos/SlavchoIvanov.png', + name: 'Славчо Иванов', + description: 'Софтуерна разработка', + linkedInProfile: 'https://www.linkedin.com/in/slavchoivanov/', + }, + { + img: '/img/team-photos/HristiyanHristov.png', + name: 'Християн Христов', + description: 'Финанси', + linkedInProfile: 'https://www.linkedin.com/in/християн-христов-hristiyan-hristov-433757238/', + }, + { + img: '/img/team-photos/ChavdarChenkov.png', + name: 'Чавдар Ченков', + description: 'Продуктов мениджмънт', + linkedInProfile: 'https://www.linkedin.com/in/chenkov/', + }, + { + img: '/img/team-photos/AndreyPetrov.png', + name: 'Андрей Петров', + description: 'Маркетинг', + linkedInProfile: 'https://www.linkedin.com/in/andrey-petrov-977887110/', + }, + { + img: '/img/team-photos/YanitaYurukova.png', + name: 'Янина Юрукова', + description: 'Графичен дизайн', + linkedInProfile: 'https://www.linkedin.com/in/yanina-yurukova/', + }, + { + img: '/img/team-photos/LianaZafiri.png', + name: 'Лиана Зафири', + description: 'Дизайн', + linkedInProfile: 'https://www.linkedin.com/in/liana-zafiri-612348239/', + }, + { + img: '/img/team-photos/GeorgiOvcharov.png', + name: 'Георги Овчаров', + description: 'Продуктов мениджмънт', + linkedInProfile: 'https://www.linkedin.com/in/georgi-ovcharov/', + }, + { + img: '/img/team-photos/DilyanaKalinova.png', + name: 'Диляна Калинова', + description: 'Маркетинг', + linkedInProfile: 'https://www.linkedin.com/in/dilyana-kalinova-544762226/', + }, +] diff --git a/src/components/client/index/IndexPage.styled.tsx b/src/components/client/index/IndexPage.styled.tsx index d600020db..ca2df2cc9 100644 --- a/src/components/client/index/IndexPage.styled.tsx +++ b/src/components/client/index/IndexPage.styled.tsx @@ -1,33 +1,33 @@ -import { Typography } from '@mui/material' -import { styled } from '@mui/material/styles' - -import theme from 'common/theme' -import LinkButton from 'components/common/LinkButton' - -export const Heading = styled(Typography)(() => ({ - color: theme.palette.primary.dark, - textAlign: 'center', - fontWeight: 500, - marginBottom: theme.spacing(6), - fontFamily: 'Montserrat, sans-serif', - fontSize: theme.typography.pxToRem(35), - letterSpacing: '-1px', -})) - -export const InfoText = styled(Typography)(() => ({ - display: 'inline-block', - textAlign: 'center', - fontSize: theme.typography.pxToRem(16), - lineHeight: theme.spacing(3), - paddingBottom: theme.spacing(6), -})) - -export const OutlinedButton = styled(LinkButton)(() => ({ - marginTop: theme.spacing(6), - fontWeight: 'bold', - color: theme.palette.common.black, - - [theme.breakpoints.up('sm')]: { - minWidth: theme.spacing(35), - }, -})) +import { Typography } from '@mui/material' +import { styled } from '@mui/material/styles' + +import theme from 'common/theme' +import LinkButton from 'components/common/LinkButton' + +export const Heading = styled(Typography)(() => ({ + color: theme.palette.primary.dark, + textAlign: 'center', + fontWeight: 500, + marginBottom: theme.spacing(6), + fontFamily: 'Montserrat, sans-serif', + fontSize: theme.typography.pxToRem(35), + letterSpacing: '-1px', +})) + +export const InfoText = styled(Typography)(() => ({ + display: 'inline-block', + textAlign: 'center', + fontSize: theme.typography.pxToRem(16), + lineHeight: theme.spacing(3), + paddingBottom: theme.spacing(6), +})) + +export const OutlinedButton = styled(LinkButton)(() => ({ + marginTop: theme.spacing(6), + fontWeight: 'bold', + color: theme.palette.common.black, + + [theme.breakpoints.up('sm')]: { + minWidth: theme.spacing(35), + }, +})) diff --git a/src/components/client/index/sections/HowWeWorkSection/HowWeWorkSection.styled.tsx b/src/components/client/index/sections/HowWeWorkSection/HowWeWorkSection.styled.tsx index 9bc92c38a..ecfcc0761 100644 --- a/src/components/client/index/sections/HowWeWorkSection/HowWeWorkSection.styled.tsx +++ b/src/components/client/index/sections/HowWeWorkSection/HowWeWorkSection.styled.tsx @@ -1,12 +1,12 @@ -import { styled } from '@mui/material/styles' - -import theme from 'common/theme' - -export const Root = styled('section')(() => ({ - marginTop: theme.spacing(8), - textAlign: 'center', - - [theme.breakpoints.up('sm')]: { - marginTop: theme.spacing(14), - }, -})) +import { styled } from '@mui/material/styles' + +import theme from 'common/theme' + +export const Root = styled('section')(() => ({ + marginTop: theme.spacing(8), + textAlign: 'center', + + [theme.breakpoints.up('sm')]: { + marginTop: theme.spacing(14), + }, +})) diff --git a/src/components/client/index/sections/JoinPodkrepiBgSection/JoinPodkrepiBgSection.styled.tsx b/src/components/client/index/sections/JoinPodkrepiBgSection/JoinPodkrepiBgSection.styled.tsx index 695d58b1e..b2bef3c64 100644 --- a/src/components/client/index/sections/JoinPodkrepiBgSection/JoinPodkrepiBgSection.styled.tsx +++ b/src/components/client/index/sections/JoinPodkrepiBgSection/JoinPodkrepiBgSection.styled.tsx @@ -1,73 +1,73 @@ -import Image from 'next/image' - -import { styled } from '@mui/material/styles' - -import LinkButton from 'components/common/LinkButton' -import theme from 'common/theme' -import { Typography } from '@mui/material' - -export const Root = styled('section')(() => ({ - position: 'relative', - padding: theme.spacing(10, 14), - marginBottom: theme.spacing(12), - alignItems: 'center', - backgroundColor: '#ffecc2', - marginTop: theme.spacing(17), - flexDirection: 'column', - gap: theme.spacing(6.25), - display: 'flex', - - [theme.breakpoints.up('md')]: { - flexDirection: 'row', - justifyContent: 'space-around', - }, - - [theme.breakpoints.up(2000)]: { - maxWidth: theme.spacing(165), - margin: `${theme.spacing(4)} auto`, - }, -})) - -export const BecomeVolunteerHeading = styled(Typography)(() => ({ - fontStyle: 'normal', - fontWeight: 500, - lineHeight: theme.typography.pxToRem(60), - letterSpacing: '-1.5px', - color: '#284E84', - fontFamily: 'sans-serif', - textAlign: 'center', - - [theme.breakpoints.up('md')]: { - fontSize: theme.typography.pxToRem(45), - textAlign: 'left', - maxWidth: theme.spacing(57), - }, -})) - -export const BecomeVolunteerButton = styled(LinkButton)(() => ({ - backgroundColor: '#284E84', - color: theme.palette.common.white, - fontFamily: 'sans-serif', - fontSize: theme.typography.pxToRem(15), - minWidth: theme.spacing(35), - boxShadow: - '0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 2px 2px rgba(0, 0, 0, 0.14), 0px 1px 5px rgba(0, 0, 0, 0.12)', - borderRadius: theme.spacing(12.5), - - [theme.breakpoints.up('md')]: { - minWidth: theme.spacing(42.5), - fontSize: theme.typography.pxToRem(22), - }, -})) - -export const JoinIcon = styled(Image)(() => ({ - position: 'absolute', - top: theme.spacing(-7.5), - - [theme.breakpoints.up('md')]: { - left: theme.spacing(6.88), - top: theme.spacing(-13), - width: theme.spacing(32), - height: theme.spacing(22), - }, -})) +import Image from 'next/image' + +import { styled } from '@mui/material/styles' + +import LinkButton from 'components/common/LinkButton' +import theme from 'common/theme' +import { Typography } from '@mui/material' + +export const Root = styled('section')(() => ({ + position: 'relative', + padding: theme.spacing(10, 14), + marginBottom: theme.spacing(12), + alignItems: 'center', + backgroundColor: '#ffecc2', + marginTop: theme.spacing(17), + flexDirection: 'column', + gap: theme.spacing(6.25), + display: 'flex', + + [theme.breakpoints.up('md')]: { + flexDirection: 'row', + justifyContent: 'space-around', + }, + + [theme.breakpoints.up(2000)]: { + maxWidth: theme.spacing(165), + margin: `${theme.spacing(4)} auto`, + }, +})) + +export const BecomeVolunteerHeading = styled(Typography)(() => ({ + fontStyle: 'normal', + fontWeight: 500, + lineHeight: theme.typography.pxToRem(60), + letterSpacing: '-1.5px', + color: '#284E84', + fontFamily: 'sans-serif', + textAlign: 'center', + + [theme.breakpoints.up('md')]: { + fontSize: theme.typography.pxToRem(45), + textAlign: 'left', + maxWidth: theme.spacing(57), + }, +})) + +export const BecomeVolunteerButton = styled(LinkButton)(() => ({ + backgroundColor: '#284E84', + color: theme.palette.common.white, + fontFamily: 'sans-serif', + fontSize: theme.typography.pxToRem(15), + minWidth: theme.spacing(35), + boxShadow: + '0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 2px 2px rgba(0, 0, 0, 0.14), 0px 1px 5px rgba(0, 0, 0, 0.12)', + borderRadius: theme.spacing(12.5), + + [theme.breakpoints.up('md')]: { + minWidth: theme.spacing(42.5), + fontSize: theme.typography.pxToRem(22), + }, +})) + +export const JoinIcon = styled(Image)(() => ({ + position: 'absolute', + top: theme.spacing(-7.5), + + [theme.breakpoints.up('md')]: { + left: theme.spacing(6.88), + top: theme.spacing(-13), + width: theme.spacing(32), + height: theme.spacing(22), + }, +})) diff --git a/src/components/client/index/sections/JoinPodkrepiBgSection/JoinPodkrepiBgSection.tsx b/src/components/client/index/sections/JoinPodkrepiBgSection/JoinPodkrepiBgSection.tsx index 862a4223a..368afd8a7 100644 --- a/src/components/client/index/sections/JoinPodkrepiBgSection/JoinPodkrepiBgSection.tsx +++ b/src/components/client/index/sections/JoinPodkrepiBgSection/JoinPodkrepiBgSection.tsx @@ -1,31 +1,31 @@ -import { useTranslation } from 'next-i18next' - -import { Box } from '@mui/material' - -import { routes } from 'common/routes' - -import { - Root, - BecomeVolunteerButton, - BecomeVolunteerHeading, - JoinIcon, -} from './JoinPodkrepiBgSection.styled' - -export default function WantToHelpPodkrepiBgSection() { - const { t } = useTranslation('index') - const joinIconSource = '/img/JoinIcon.png' - - return ( - - - - {t('join-podkrepi-bg-section.heading')} - - - - {t('join-podkrepi-bg-section.become-volunteer')} - - - - ) -} +import { useTranslation } from 'next-i18next' + +import { Box } from '@mui/material' + +import { routes } from 'common/routes' + +import { + Root, + BecomeVolunteerButton, + BecomeVolunteerHeading, + JoinIcon, +} from './JoinPodkrepiBgSection.styled' + +export default function WantToHelpPodkrepiBgSection() { + const { t } = useTranslation('index') + const joinIconSource = '/img/JoinIcon.png' + + return ( + + + + {t('join-podkrepi-bg-section.heading')} + + + + {t('join-podkrepi-bg-section.become-volunteer')} + + + + ) +} diff --git a/src/gql/types.d.ts b/src/gql/types.d.ts index 4e501a984..760a0ec5a 100644 --- a/src/gql/types.d.ts +++ b/src/gql/types.d.ts @@ -7,6 +7,9 @@ export type PaginationData = { export type FilterData = { status: DonationStatus - type: DonationType + paymentProvider: PaymentProvider date: { from: Date | null; to: Date | null } + minAmount: number + maxAmount: number + sortBy: string } diff --git a/src/service/apiEndpoints.ts b/src/service/apiEndpoints.ts index aa53bd2a0..f56452258 100644 --- a/src/service/apiEndpoints.ts +++ b/src/service/apiEndpoints.ts @@ -61,13 +61,15 @@ export const endpoints = { searchData?: string, ) => { const { pageIndex, pageSize } = (paginationData as PaginationData) || {} - const { status, type, date } = (filterData as FilterData) || {} + const { status, paymentProvider, date } = (filterData as FilterData) || {} const { from, to } = date || {} return { - url: campaignId - ? `/donation/list?campaignId=${campaignId}&pageindex=${pageIndex}&pagesize=${pageSize}&status=${status}&type=${type}&from=${from}&to=${to}&search=${searchData}` - : `/donation/list?pageindex=${pageIndex}&pagesize=${pageSize}&status=${status}&type=${type}&from=${from}&to=${to}&search=${searchData}`, + url: `/donation/list?campaignId=${ + campaignId ?? '' + }&pageindex=${pageIndex}&pagesize=${pageSize}&status=${status}&provider=${paymentProvider}&from=${from}&to=${to}&search=${searchData}&minAmount=${ + filterData?.minAmount ?? '' + }&maxAmount=${filterData?.maxAmount ?? ''}&sortBy=${filterData?.sortBy ?? ''}`, method: 'GET', } }, @@ -92,7 +94,15 @@ export const endpoints = { userDonations: { url: 'donation/user-donations', method: 'GET' }, uploadBankTransactionsFile: (bankTransactionsFileId: string) => { url: `/bank-transactions-file/${bankTransactionsFileId}`, method: 'POST' }, - exportToExcel: { url: '/donation/export-excel', method: 'GET' }, + exportToExcel: (filterData?: FilterData, searchData?: string) => + { + url: `/donation/export-excel?status=${filterData?.status}&provider=${ + filterData?.paymentProvider + }&from=${filterData?.date.from}&to=${filterData?.date.to}&search=${searchData}&minAmount=${ + filterData?.minAmount ?? '' + }&maxAmount=${filterData?.maxAmount ?? ''}&sortBy=${filterData?.sortBy ?? ''}`, + method: 'GET', + }, }, bankTransactions: { transactionsList: ( @@ -101,11 +111,11 @@ export const endpoints = { searchData?: string, ) => { const { pageIndex, pageSize } = (paginationData as PaginationData) || {} - const { status, type, date } = (filterData as FilterData) || {} + const { status, date } = (filterData as FilterData) || {} const { from, to } = date || {} return { - url: `/bank-transaction/list?pageindex=${pageIndex}&pagesize=${pageSize}&status=${status}&type=${type}&from=${from}&to=${to}&search=${searchData}`, + url: `/bank-transaction/list?pageindex=${pageIndex}&pagesize=${pageSize}&status=${status}&from=${from}&to=${to}&search=${searchData}`, method: 'GET', } }, diff --git a/src/service/donation.ts b/src/service/donation.ts index c5a6e2092..e0aa887cd 100644 --- a/src/service/donation.ts +++ b/src/service/donation.ts @@ -16,6 +16,7 @@ import { endpoints } from 'service/apiEndpoints' import { authConfig } from 'service/restRequests' import { UploadBankTransactionsFiles } from 'components/admin/bank-transactions-file/types' import { useMutation } from '@tanstack/react-query' +import { FilterData } from 'gql/types' export const createCheckoutSession = async (data: CheckoutSessionInput) => { return await apiClient.post>( @@ -105,10 +106,10 @@ export const useUploadBankTransactionsFiles = () => { } } -export const useExportToExcel = () => { +export const useExportToExcel = (filterData?: FilterData, searchData?: string) => { const { data: session } = useSession() return async () => { - return await apiClient(endpoints.donation.exportToExcel.url, { + return await apiClient(endpoints.donation.exportToExcel(filterData, searchData).url, { ...authConfig(session?.accessToken), responseType: 'blob', }) diff --git a/src/stores/DomainStores/DonationStore.ts b/src/stores/DomainStores/DonationStore.ts index f3cedd0c4..99881cbc6 100644 --- a/src/stores/DomainStores/DonationStore.ts +++ b/src/stores/DomainStores/DonationStore.ts @@ -8,18 +8,24 @@ export class DonationStore { donations: DonationInput[] = [] donationFilters: { status: string | null - type: string | null + paymentProvider: string | null + minAmount: number | null + maxAmount: number | null date: { from?: Date | '' to?: Date | '' } + sortBy: string | null } = { status: '', - type: '', + paymentProvider: '', + minAmount: null, + maxAmount: null, date: { from: '', to: '', }, + sortBy: '', } donationSearch: string | undefined = undefined