Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Campaign Applications (alpha) #1930

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -121,6 +121,7 @@
"jest": "^29.6.1",
"jest-environment-jsdom": "^29.6.1",
"lint-staged": "11.0.0",
"msw": "1",
"next-sitemap": "^3.1.52",
"prettier": "2.3.0",
"shx": "^0.3.3",
29 changes: 26 additions & 3 deletions public/locales/bg/campaign-application.json
Original file line number Diff line number Diff line change
@@ -40,12 +40,15 @@
}
},
"photos": "Снимков/видео материал",
"documents": "Документи"
"documents": "Документи",
"disclaimer": "Приемат се до 10 документа. Всеки от документите може да бъде до 30МБ"
},
"admin": {
"title": "Администраторска редакция",
"status": "Статус",
"external-url": "Външен линк"
"external-url": "Външен линк",
"archived": "Архивиран",
"organizer-edit-link": "Организатор може да редактира на"
}
},
"cta": {
@@ -62,6 +65,26 @@
}
},
"alerts": {
"successfully-created": "Успешно създадена кампания. "
"successfully-created": "Успешно създадена заявка за кампания. "
},
"result": {
"created": "Успешно създадена заявка за кампания.",
"edited": "Успешно редактирана заявка за кампания.",
"editButton": "Редакция на заявка за кампания",
"uploadOk": "Добавени файлове",
"deleteOk": "Премахнати файлове",
"uploadFailed": "Неуспешно добавени файлове",
"deleteFailed": "Неуспешно премахнати файлове",
"uploadFailedWhat": "Какво мога да направя?",
"uploadFailedDirection": "Моля посетете страницата за редакция на заявката за кампания от бутона по-долу и опитайте отново да добавите/премахнете файловете"
},
"status": {
"selectorLabel": "Статус",
"review": "Нова за ревю",
"requestInfo": "За още информация",
"forCommitteeReview": "За ревю от комисия",
"approved": "Одобрена",
"denied": "Отказана",
"abandoned": "Изоставена"
}
}
27 changes: 25 additions & 2 deletions public/locales/en/campaign-application.json
Original file line number Diff line number Diff line change
@@ -40,12 +40,15 @@
}
},
"photos": "Photo/Video material",
"documents": "Documents"
"documents": "Documents",
"disclaimer": "Up to 10 documents accepted. Each of the documents can be up to 30MB is size"
},
"admin": {
"title": "Admin edit",
"status": "Status",
"external-url": "External URL"
"external-url": "External URL",
"archived": "Archived",
"organizer-edit-link": "Organizer can edit at"
}
},
"cta": {
@@ -63,5 +66,25 @@
},
"alerts": {
"successfully-created": "Campaign application successfully created."
},
"result": {
"created": "Successfully created campaign application",
"edited": "Successfully edited campaign application",
"editButton": "Edit campaign application",
"uploadOk": "Fails added",
"deleteOk": "Files removed",
"uploadFailed": "Failed file add",
"deleteFailed": "Failed to remove files",
"uploadFailedWhat": "What can I do?",
"uploadFailedDirection": "Please visit the campaign application edit page linked below and retry adding/removing the files."
},
"status": {
"selectorLabel": "Status",
"review": "New - for review",
"requestInfo": "Request for more info",
"forCommitteeReview": "For committee review",
"approved": "Approved",
"denied": "Denied",
"abandoned": "Abandoned"
}
}
1 change: 1 addition & 0 deletions src/common/routes.ts
Original file line number Diff line number Diff line change
@@ -92,6 +92,7 @@ export const routes = {
index: '/campaigns',
create: '/campaigns/create',
application: 'campaigns/application',
applicationEdit: (id: string) => `/campaigns/application/${id}`,
viewCampaignBySlug: (slug: string) => `/campaigns/${slug}`,
viewExpenses: (slug: string) => `/campaigns/${slug}/expenses`,
oneTimeDonation: (slug: string) => `/campaigns/donation/${slug}`,
Original file line number Diff line number Diff line change
@@ -1,33 +1,45 @@
import { useTranslation } from 'next-i18next'

import { Grid } from '@mui/material'
import { StatusSelector } from 'components/client/campaign-application/helpers/campaign-application-status'
import {
StyledFormTextField,
StyledStepHeading,
} from 'components/client/campaign-application/helpers/campaignApplication.styled'
import { CamAppDetail } from 'components/client/campaign-application/steps/CampaignApplicationSummary'
import CheckboxField from 'components/common/form/CheckboxField'
import OrganizerCanEditAt from './CampaignApplicationOrganizerCanEditAt'

export default function CampaignApplicationAdminPropsEdit() {
export default function CampaignApplicationAdminPropsEdit({ id }: { id: string }) {
const { t } = useTranslation('campaign-application')

return (
<Grid container spacing={6} justifyContent="center" direction="column" alignContent="center">
<Grid item container justifyContent="center">
<StyledStepHeading variant="h4">{t('steps.admin.title')}</StyledStepHeading>
</Grid>
<Grid item container spacing={6} justifyContent="space-between" direction="row">
<Grid item xs={12}>
<StyledFormTextField label={t('steps.admin.status')} type="text" name="status" />
<Grid item xs={6}>
<StatusSelector name="admin.state" />
</Grid>
<Grid item xs={6}>
<CheckboxField label={t('steps.admin.archived')} name="admin.archived" />
</Grid>
</Grid>
<Grid item container spacing={6} justifyContent="space-between" direction="row">
<Grid container item xs={12} md={6}>
<Grid container item xs={12}>
<StyledFormTextField
label={t('steps.admin.external-url')}
type="phone"
name="ticketUrl"
type="text"
name="admin.ticketURL"
/>
</Grid>
</Grid>
<Grid item container spacing={6} justifyContent="space-between" direction="row" mb="20px">
<CamAppDetail
label={t('steps.admin.organizer-edit-link')}
value={<OrganizerCanEditAt id={id} />}
/>
</Grid>
</Grid>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { routes } from 'common/routes'
import { CopyTextButton } from 'components/common/CopyTextButton'
import getConfig from 'next/config'
import Copy from '@mui/icons-material/CopyAll'
import { Typography } from '@mui/material'
export type Props = {
id: string
}
const OrganizerCanEditAt = ({ id }: Props) => {
const { publicRuntimeConfig } = getConfig()
const url = `${publicRuntimeConfig?.APP_URL}${routes.campaigns.applicationEdit(id)}`

return (
<>
<Typography variant="subtitle1" component="span">
{url}
</Typography>
<CopyTextButton label="" startIcon={<Copy />} text={url} title={`Copy ${url}`} />
</>
)
}

export default OrganizerCanEditAt
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { useTranslation } from 'next-i18next'

import { DataGrid, GridColDef, GridRenderCellParams } from '@mui/x-data-grid'
import { useQuery } from '@tanstack/react-query'
import { routes } from 'common/routes'
import theme from 'common/theme'
import { CampaignApplicationAdminResponse } from 'gql/campaign-applications'
import { useSession } from 'next-auth/react'
import Link from 'next/link'
import { endpoints } from 'service/apiEndpoints'
import { authQueryFnFactory } from 'service/restRequests'

export default function CampaignApplicationsGrid() {
const { t, i18n } = useTranslation()
const { t } = useTranslation('campaign-application')
const { list } = useCampaignsList()

const commonProps: Partial<GridColDef> = {
align: 'left',
@@ -16,33 +22,34 @@ export default function CampaignApplicationsGrid() {

const columns: GridColDef[] = [
{
field: 'status',
field: 'state',
headerName: t('campaigns:status'),
...commonProps,
align: 'left',
width: 220,
renderCell: (cellValues: GridRenderCellParams) => t(`status.${cellValues.row.state}`),
},
{
field: 'title',
field: 'campaignName',
headerName: t('campaigns:title'),
...commonProps,
align: 'left',
width: 250,
renderCell: (cellValues: GridRenderCellParams) => (
<Link href={routes.admin.campaignApplications.edit(cellValues.id.toString())}>
{cellValues.row.title}
{cellValues.row.campaignName}
</Link>
),
},
{
field: 'essence',
field: 'goal',
headerName: t('campaigns:essence'),
...commonProps,
align: 'left',
width: 250,
},
{
field: 'organizer',
field: 'organizerName',
headerName: t('campaigns:organizer'),
...commonProps,
align: 'left',
@@ -71,76 +78,44 @@ export default function CampaignApplicationsGrid() {
},
]

const data = [
{
updatedAt: 'date',
createdAt: '2024-5-5',
beneficiary: 'beneficiary',
organizer: 'organizer',
essence: 'essence',
title: 'title',
id: '1',
status: 'нова',
},
{
updatedAt: 'yesterday',
createdAt: '10 days ago',
beneficiary: 'beneficiary',
organizer: 'organizer',
essence: 'essence',
title: 'title',
id: '2',
status: 'очаква документи',
},
{
updatedAt: '',
createdAt: '',
beneficiary: 'beneficiary',
organizer: 'organizer',
essence: 'essence',
title: 'title',
id: '3',
status: 'очаква решение на комисия',
},

{
updatedAt: '',
createdAt: '',
beneficiary: 'beneficiary',
organizer: 'organizer',
essence: 'essence',
title: 'title',
id: '4',
status: 'одобрена',
},
{
updatedAt: '',
createdAt: '',
beneficiary: 'beneficiary',
organizer: 'organizer',
essence: 'essence',
title: 'title',
id: '4',
status: 'отказана',
},
]
return (
<DataGrid
style={{
background: theme.palette.common.white,
position: 'absolute',
height: 'calc(100vh - 300px)',
height: 'calc(100vh - 299px)',
border: 'none',
width: 'calc(100% - 48px)',
left: '24px',
overflowY: 'auto',
overflowX: 'hidden',
borderRadius: '0 0 13px 13px',
}}
rows={data || []}
rows={list || []}
columns={columns}
editMode="row"
pageSizeOptions={[20, 50, 100]}
/>
)
}

function fetchMutation() {
const { data } = useSession()
return useQuery(
[endpoints.campaignApplication.listAllForAdmin.url],
authQueryFnFactory<CampaignApplicationAdminResponse[]>(data?.accessToken),
{
cacheTime: 10 * 60 * 1000,
staleTime: 10 * 60 * 1000,
},
)
}

export const useCampaignsList = () => {
const { data, isLoading } = fetchMutation()

return {
list: data?.sort((a, b) => b?.updatedAt?.localeCompare(a?.updatedAt ?? '') ?? 0),
isLoading,
}
}
Loading