Skip to content

Commit

Permalink
Merge pull request #266 from AmbireTech/block-pacements
Browse files Browse the repository at this point in the history
wip: edit campaign with tabs
  • Loading branch information
ivopaunov authored Aug 14, 2024
2 parents d638249 + 3ed82be commit fb50410
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 131 deletions.
14 changes: 10 additions & 4 deletions src/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,16 @@ export const router = createBrowserRouter(
path: '',
element: <Dashboard />
},
{ path: 'campaign-analytics/:id', element: <CampaignAnalytics /> },
{ path: 'campaign-analytics/admin/:id', element: <CampaignAnalytics isAdminPanel /> },
{ path: 'campaign-details/:id', element: <CampaignDetails /> },
{ path: 'campaign-details/admin/:id', element: <CampaignDetails isAdminPanel /> },
{ path: 'campaign-analytics/:id/:activeTab?', element: <CampaignAnalytics /> },
{
path: 'campaign-analytics/admin/:id/:activeTab?',
element: <CampaignAnalytics isAdminPanel />
},
{ path: 'campaign-details/:id/:tabValue?', element: <CampaignDetails /> },
{
path: 'campaign-details/admin/:id/:tabValue?',
element: <CampaignDetails isAdminPanel />
},
{
path: 'billing',
element: <Billing />
Expand Down
23 changes: 14 additions & 9 deletions src/components/CampaignAnalytics/CampaignAnalytics.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useCallback, useEffect, useState, useMemo } from 'react'
import { Container, Flex, Loader, Tabs, Paper, Group, Text, Anchor, Center } from '@mantine/core'
import { useParams } from 'react-router-dom'
import { AnalyticsType, BaseAnalyticsData, AnalyticsPeriod } from 'types'
import { useParams, useNavigate } from 'react-router-dom'
import { BaseAnalyticsData, AnalyticsPeriod, AnalyticsType } from 'types'
import GoBack from 'components/common/GoBack/GoBack'
import DownloadCSV from 'components/common/DownloadCSV'
import useCampaignAnalytics from 'hooks/useCampaignAnalytics'
Expand All @@ -19,9 +19,9 @@ import { generateCVSData } from './CvsDownloadConfigurations'
import SeeOnMapBtn from './SeeOnMapBtn'

const CampaignAnalytics = ({ isAdminPanel = false }: { isAdminPanel?: boolean }) => {
const { id } = useParams()
const { id, activeTab = 'timeframe' } = useParams<{ id: string; activeTab: AnalyticsType }>()

const [activeTab, setActiveTab] = useState<AnalyticsType>('timeframe')
const navigate = useNavigate()
const [isMapBtnShown, setIsMapBtnShown] = useState<boolean>(false)
const [isMapVisible, setIsMapVisible] = useState<boolean>(false)
const [csvData, setCsvData] = useState<any | undefined>()
Expand Down Expand Up @@ -103,11 +103,16 @@ const CampaignAnalytics = ({ isAdminPanel = false }: { isAdminPanel?: boolean })
}
}, [activeTab, campaignMappedAnalytics])

const handleTabChange = useCallback((value: string | null) => {
// TODO: validate value if it is in AnalyticsType
if (!value) return
setActiveTab(value as AnalyticsType)
}, [])
const handleTabChange = useCallback(
(value: string | null) => {
campaign?.id &&
navigate(
`/dashboard/campaign-analytics${isAdminPanel ? '/admin' : ''}/${campaign?.id}/${value}`,
{ replace: true }
)
},
[campaign?.id, isAdminPanel, navigate]
)

// TODO: there is delay when updated analytics table is displayed after the tab is switched - add loading bars or something

Expand Down
6 changes: 3 additions & 3 deletions src/components/CampaignAnalytics/Placements.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import CustomTable, { TableElement, TableRowAction } from 'components/common/Cus
import { getHumneSrcName } from 'helpers'
import { useMemo } from 'react'
import { BaseAnalyticsData } from 'types'
import InvisibilityIcon from 'resources/icons/Invisibility'
import VisibilityIcon from 'resources/icons/Visibility'
import IncludeIcon from 'resources/icons/Include'
import ExcludeIcon from 'resources/icons/Exclude'
import { useCampaignsData } from 'hooks/useCampaignsData'

const Placements = ({
Expand Down Expand Up @@ -89,7 +89,7 @@ const Placements = ({
label: ({ isBlocked, placementName }: PlacementsTableElement['actionData']) =>
`${isBlocked ? 'Unblock' : 'Block'} "${placementName}"`,
icon: ({ isBlocked }: PlacementsTableElement['actionData']) =>
isBlocked ? <VisibilityIcon size="inherit" /> : <InvisibilityIcon size="inherit" />
isBlocked ? <IncludeIcon /> : <ExcludeIcon />
}
]
: []
Expand Down
6 changes: 3 additions & 3 deletions src/components/CampaignDetails/CampaignDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,8 @@ const CampaignDetails = ({ isAdminPanel }: { isAdminPanel?: boolean }) => {
<Button
disabled={isDraft ? !canEditDraft : !canEdit}
rightSection={<EditIcon size="15px" />}
variant="subtle"
color="mainText"
variant={isEditMode ? 'filled' : 'subtle'}
color={isEditMode ? 'brand' : 'mainText'}
onClick={() =>
isDraft
? canEditDraft && handleEditDraft()
Expand Down Expand Up @@ -262,7 +262,7 @@ const CampaignDetails = ({ isAdminPanel }: { isAdminPanel?: boolean }) => {
</StickyPanel>

{isEditMode ? (
<EditCampaign campaign={campaign} />
<EditCampaign campaign={campaign} isAdmin={isAdminPanel} />
) : (
<Paper p="lg" shadow="xs">
<Grid gutter="lg">
Expand Down
2 changes: 1 addition & 1 deletion src/components/Dashboard/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ const Dashboard = ({ isAdminPanel, accountId }: { isAdminPanel?: boolean; accoun

const handleEdit = useCallback(
(data: DashboardTableElement['actionData']) =>
navigate(`/dashboard/campaign-details/${data.campaign.id}?edit=true`, {}),
navigate(`/dashboard/campaign-details/${data.campaign.id}/budget?edit=true`, {}),
[navigate]
)

Expand Down
249 changes: 142 additions & 107 deletions src/components/EditCampaign/EditCampaign.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import {
ActionIcon,
Checkbox,
NumberInput,
Paper
Paper,
Tabs
} from '@mantine/core'
import { useForm } from '@mantine/form'
import { modals } from '@mantine/modals'
Expand All @@ -32,7 +33,7 @@ import type {
unstable_Blocker as Blocker,
unstable_BlockerFunction as BlockerFunction
} from 'react-router-dom'
import { unstable_useBlocker as useBlocker } from 'react-router-dom'
import { unstable_useBlocker as useBlocker, useParams, useNavigate } from 'react-router-dom'
import InfoFilledIcon from 'resources/icons/InfoFilled'
import throttle from 'lodash.throttle'
import { defaultConfirmModalProps } from 'components/common/Modals/CustomConfirmModal'
Expand All @@ -54,10 +55,12 @@ type FormProps = {
targetingInput: TargetingInputEdit
}

const EditCampaign = ({ campaign }: { campaign: Campaign }) => {
const EditCampaign = ({ campaign, isAdmin }: { campaign: Campaign; isAdmin?: boolean }) => {
const {
adexAccount: { balanceToken }
} = useAccount()
const { tabValue = 'budget' } = useParams()
const navigate = useNavigate()
const { supplyStats, editCampaign } = useCampaignsData()

const recommendedPaymentBounds = useMemo(
Expand Down Expand Up @@ -242,115 +245,147 @@ const EditCampaign = ({ campaign }: { campaign: Campaign }) => {

if (!campaign) return <div>Invalid Campaign ID</div>
return (
<Paper p="md">
<form onSubmit={form.onSubmit(throttledSbm)}>
<Stack gap="xl">
<Stack gap="xs">
<Group gap="xs">
<Text color="secondaryText" size="sm" fw="bold">
CPM
</Text>
<Tooltip
label={`Recommended CPM: Min - ${recommendedPaymentBounds.min}; Max - ${recommendedPaymentBounds.max}`}
ml="sm"
>
<ActionIcon variant="transparent" color="secondaryText" size="xs">
<InfoFilledIcon />
</ActionIcon>
</Tooltip>
</Group>
<Group align="baseline">
<NumberInput
w="196px"
size="md"
placeholder="CPM min"
rightSection={
<Text color="brand" mr="sm" size="sm">
Min
</Text>
}
rightSectionWidth="auto"
name="cpmPricingBoundsMin"
decimalScale={2}
{...form.getInputProps('pricingBounds.IMPRESSION.min')}
/>
<NumberInput
w="196px"
size="md"
placeholder="CPM max"
inputWrapperOrder={['input', 'description', 'error']}
rightSection={
<Text color="brand" mr="sm" size="sm">
Max
<Paper p="md" shadow="xs">
<Tabs
value={tabValue}
onChange={(value) =>
navigate(
`/dashboard/campaign-details${isAdmin ? '/admin' : ''}/${
campaign.id
}/${value}?edit=true`,
{ replace: true }
)
}
>
<Tabs.List mb="xl">
<Tabs.Tab value="budget">Budget</Tabs.Tab>
<Tabs.Tab value="targeting">Targeting</Tabs.Tab>
</Tabs.List>

<form onSubmit={form.onSubmit(throttledSbm)}>
<Tabs.Panel value="budget">
<Stack gap="xl">
<Stack gap="xs">
<Group gap="xs">
<Text color="secondaryText" size="sm" fw="bold">
CPM
</Text>
}
rightSectionWidth="md"
name="cpmPricingBoundsMax"
decimalScale={2}
{...form.getInputProps('pricingBounds.IMPRESSION.max')}
/>
</Group>
</Stack>
<Tooltip
label={`Recommended CPM: Min - ${recommendedPaymentBounds.min}; Max - ${recommendedPaymentBounds.max}`}
ml="sm"
>
<ActionIcon variant="transparent" color="secondaryText" size="xs">
<InfoFilledIcon />
</ActionIcon>
</Tooltip>
</Group>
<Group align="baseline">
<NumberInput
w="196px"
size="md"
placeholder="CPM min"
rightSection={
<Text color="brand" mr="sm" size="sm">
Min
</Text>
}
rightSectionWidth="auto"
name="cpmPricingBoundsMin"
decimalScale={2}
{...form.getInputProps('pricingBounds.IMPRESSION.min')}
/>
<NumberInput
w="196px"
size="md"
placeholder="CPM max"
inputWrapperOrder={['input', 'description', 'error']}
rightSection={
<Text color="brand" mr="sm" size="sm">
Max
</Text>
}
rightSectionWidth="md"
name="cpmPricingBoundsMax"
decimalScale={2}
{...form.getInputProps('pricingBounds.IMPRESSION.max')}
/>
</Group>
</Stack>

<Stack gap="xs">
<Text c="secondaryText" size="sm" fw="bold">
Advanced
</Text>
<Group>
<Checkbox
label="Limit average daily spending"
{...form.getInputProps(
'targetingInput.inputs.advanced.limitDailyAverageSpending',
{
type: 'checkbox'
}
)}
/>
</Group>
</Stack>

<Stack gap="xs">
<Text c="secondaryText" size="sm" fw="bold">
Advanced
</Text>
<Group>
<Checkbox
label="Limit average daily spending"
{...form.getInputProps('targetingInput.inputs.advanced.limitDailyAverageSpending', {
type: 'checkbox'
})}
/>
</Group>
</Stack>
<Button disabled={!form.isDirty()} size="lg" type="submit" maw={200}>
Save Changes
</Button>
</Stack>
</Tabs.Panel>

<Stack gap="xs">
<Text c="secondaryText" size="sm" fw="bold">
Categories
</Text>
<MultiSelectAndRadioButtons
onCategoriesChange={handleCategories}
multiSelectData={CATEGORIES}
defaultRadioValue={
catSelectedRadioAndValuesArray &&
(catSelectedRadioAndValuesArray[0] as TargetingInputApplyProp)
}
defaultSelectValue={
catSelectedRadioAndValuesArray && (catSelectedRadioAndValuesArray[1] as string[])
}
groups={CAT_GROUPS}
label="Categories"
error={form.errors['targetingInput.inputs.categories']?.toString()}
/>
</Stack>
<Tabs.Panel value="targeting">
<Stack gap="xl">
<Stack gap="xs">
<Text c="secondaryText" size="sm" fw="bold">
Categories
</Text>
<MultiSelectAndRadioButtons
onCategoriesChange={handleCategories}
multiSelectData={CATEGORIES}
defaultRadioValue={
catSelectedRadioAndValuesArray &&
(catSelectedRadioAndValuesArray[0] as TargetingInputApplyProp)
}
defaultSelectValue={
catSelectedRadioAndValuesArray &&
(catSelectedRadioAndValuesArray[1] as string[])
}
groups={CAT_GROUPS}
label="Categories"
error={form.errors['targetingInput.inputs.categories']?.toString()}
/>
</Stack>

<Stack gap="xs">
<Text c="secondaryText" size="sm" fw="bold">
Countries
</Text>
<MultiSelectAndRadioButtons
onCategoriesChange={handleCountries}
defaultRadioValue={
locSelectedRadioAndValuesArray &&
(locSelectedRadioAndValuesArray[0] as TargetingInputApplyProp)
}
defaultSelectValue={
locSelectedRadioAndValuesArray && (locSelectedRadioAndValuesArray[1] as string[])
}
multiSelectData={COUNTRIES}
groups={REGION_GROUPS}
label="Countries"
error={form.errors['targetingInput.inputs.location']?.toString()}
/>
</Stack>
<Stack gap="xs">
<Text c="secondaryText" size="sm" fw="bold">
Countries
</Text>
<MultiSelectAndRadioButtons
onCategoriesChange={handleCountries}
defaultRadioValue={
locSelectedRadioAndValuesArray &&
(locSelectedRadioAndValuesArray[0] as TargetingInputApplyProp)
}
defaultSelectValue={
locSelectedRadioAndValuesArray &&
(locSelectedRadioAndValuesArray[1] as string[])
}
multiSelectData={COUNTRIES}
groups={REGION_GROUPS}
label="Countries"
error={form.errors['targetingInput.inputs.location']?.toString()}
/>
</Stack>

<Button disabled={!form.isDirty()} size="lg" type="submit" maw={200}>
Save Changes
</Button>
</Stack>
</form>
<Button disabled={!form.isDirty()} size="lg" type="submit" maw={200}>
Save Changes
</Button>
</Stack>
</Tabs.Panel>
</form>
</Tabs>
</Paper>
)
}
Expand Down
Loading

0 comments on commit fb50410

Please sign in to comment.