-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[SHEP-2] UI Created to Split a Single Campaign into Multiple Campaigns (
#268) ## References [SHEP-2](https://mozilla-hub.atlassian.net/browse/SHEP-2) ## Problem Statement With the automatic creation of a child campaign when new booster deals are imported, we need a UI that allows to split a single campaign into multiple campaigns. ## Proposed Changes Split Campaign Form Added to Allow Users to Split a Single Campaign into Multiple Campaigns. ## Verification Steps 1. Click on the "Split Campaign" icon on the Campaigns list page. 2. Click on the plus icon to split the campaign into multiple campaigns. 3. Add details for the newly created campaign. 4. Ensure the total net spend for the campaigns matches the actual value of the campaign before the split. ## Visuals https://github.com/user-attachments/assets/0d9c82ce-3e5e-4c39-a891-96ad19c399e1 [SHEP-2]: https://mozilla-hub.atlassian.net/browse/SHEP-2?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
- Loading branch information
1 parent
fc0a2a1
commit 786392a
Showing
20 changed files
with
557 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
219 changes: 219 additions & 0 deletions
219
ad-ops-dashboard/src/components/Forms/SplitCampaignForm.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,219 @@ | ||
import React from "react"; | ||
import { Box, Button, Grid2 } from "@mui/material"; | ||
import { Add, Remove } from "@mui/icons-material"; | ||
import { useFieldArray, useForm } from "react-hook-form"; | ||
import { zodResolver } from "@hookform/resolvers/zod"; | ||
import { styled } from "@mui/system"; | ||
import { | ||
CampaignFormSchema, | ||
SplitFormSchema, | ||
splitFormSchema, | ||
} from "../../utils/schemas/campaignFormSchema"; | ||
import TextInput from "../Inputs/TextInput"; | ||
import DateInput from "../Inputs/DateInput"; | ||
import { useSplitCampaignMutation } from "../../data/campaigns"; | ||
import Tooltip from "@mui/material/Tooltip"; | ||
|
||
interface SplitCampaignProps { | ||
handleClose: () => void; | ||
formData: CampaignFormSchema; | ||
} | ||
|
||
const StyledBox = styled(Box)(() => ({ | ||
display: "flex", | ||
justifyContent: "space-between", | ||
alignItems: "center", | ||
})); | ||
|
||
const StyledButton = styled(Button)(() => ({ | ||
marginRight: "3.8rem", | ||
})); | ||
|
||
export default function SplitCampaignForm({ | ||
formData, | ||
handleClose, | ||
}: SplitCampaignProps) { | ||
const splitMutation = useSplitCampaignMutation(); | ||
|
||
const { control, handleSubmit, reset } = useForm<SplitFormSchema>({ | ||
resolver: zodResolver(splitFormSchema), | ||
defaultValues: { | ||
campaigns: [ | ||
{ | ||
id: formData.id, | ||
impressions_sold: formData.impressions_sold || "", | ||
net_spend: formData.net_spend || "", | ||
kevel_flight_id: formData.kevel_flight_id ?? "", | ||
ad_ops_person: formData.ad_ops_person ?? "", | ||
seller: formData.seller || "", | ||
start_date: formData.start_date || "", | ||
end_date: formData.end_date || "", | ||
notes: formData.notes ?? "", | ||
deal: formData.deal || undefined, | ||
}, | ||
], | ||
}, | ||
}); | ||
|
||
const onSubmitHandler = (data: SplitFormSchema) => { | ||
const updatedData = { | ||
...data, | ||
campaigns: data.campaigns.map((campaign) => ({ | ||
...campaign, | ||
notes: campaign.notes?.trim() !== "" ? campaign.notes : null, | ||
ad_ops_person: | ||
campaign.ad_ops_person?.trim() !== "" ? campaign.ad_ops_person : null, | ||
kevel_flight_id: | ||
campaign.kevel_flight_id !== 0 ? campaign.kevel_flight_id : null, | ||
})), | ||
deal: formData.deal, | ||
}; | ||
|
||
splitMutation.mutate(updatedData, { | ||
onSuccess: () => { | ||
reset(); | ||
handleClose(); | ||
}, | ||
}); | ||
}; | ||
|
||
const { fields, append, remove } = useFieldArray({ | ||
control, | ||
name: "campaigns", | ||
}); | ||
|
||
return ( | ||
<Box mt="2rem"> | ||
<Box | ||
component="form" | ||
onSubmit={(event) => { | ||
event.preventDefault(); | ||
handleSubmit(onSubmitHandler)(); | ||
}} | ||
> | ||
<Grid2 container spacing={2}> | ||
{fields.map((field, index) => ( | ||
<React.Fragment key={field.id}> | ||
<Grid2 size={2}> | ||
<TextInput | ||
name={`campaigns.${index.toString()}.ad_ops_person`} | ||
label="Ad Ops Person" | ||
control={control} | ||
fullWidth | ||
/> | ||
</Grid2> | ||
<Grid2 size={1}> | ||
<TextInput | ||
name={`campaigns.${index.toString()}.kevel_flight_id`} | ||
label="Kevel Flight Id" | ||
type="number" | ||
control={control} | ||
fullWidth | ||
/> | ||
</Grid2> | ||
<Grid2 size={1}> | ||
<TextInput | ||
name={`campaigns.${index.toString()}.impressions_sold`} | ||
label="Impressions Sold" | ||
type="number" | ||
control={control} | ||
fullWidth | ||
/> | ||
</Grid2> | ||
<Grid2 size={1}> | ||
<TextInput | ||
name={`campaigns.${index.toString()}.net_spend`} | ||
label="Net spend" | ||
type="number" | ||
control={control} | ||
fullWidth | ||
/> | ||
</Grid2> | ||
<Grid2 size={2}> | ||
<TextInput | ||
name={`campaigns.${index.toString()}.seller`} | ||
label="Seller" | ||
control={control} | ||
fullWidth | ||
/> | ||
</Grid2> | ||
<Grid2 size={3}> | ||
<StyledBox> | ||
<Box> | ||
<DateInput | ||
control={control} | ||
label="Start Date" | ||
name={`campaigns.${index.toString()}.start_date`} | ||
/> | ||
</Box> | ||
<Box sx={{ marginLeft: "1rem" }}> | ||
<DateInput | ||
control={control} | ||
label="End Date" | ||
name={`campaigns.${index.toString()}.end_date`} | ||
/> | ||
</Box> | ||
</StyledBox> | ||
</Grid2> | ||
<Grid2 size={2}> | ||
<StyledBox> | ||
<Box> | ||
<TextInput | ||
name={`campaigns.${index.toString()}.notes`} | ||
label="Notes" | ||
control={control} | ||
/> | ||
</Box> | ||
<Box | ||
sx={{ | ||
display: "flex", | ||
justifyContent: "center", | ||
alignItems: "center", | ||
}} | ||
> | ||
{index == 0 ? ( | ||
<Tooltip title="Split Campaign" placement="top" arrow> | ||
<Button | ||
onClick={() => { | ||
append({ | ||
impressions_sold: "", | ||
net_spend: "", | ||
kevel_flight_id: "", | ||
ad_ops_person: "", | ||
seller: "", | ||
start_date: "", | ||
end_date: "", | ||
notes: "", | ||
deal: formData.deal, | ||
}); | ||
}} | ||
> | ||
<Add fontSize="large" /> | ||
</Button> | ||
</Tooltip> | ||
) : ( | ||
<Tooltip title="Remove Campaign" placement="top" arrow> | ||
<Button | ||
onClick={() => { | ||
remove(index); | ||
}} | ||
> | ||
<Remove fontSize="large" color="error" /> | ||
</Button> | ||
</Tooltip> | ||
)} | ||
</Box> | ||
</StyledBox> | ||
</Grid2> | ||
</React.Fragment> | ||
))} | ||
</Grid2> | ||
<Box mt="2rem" display="flex" justifyContent="flex-end" width="100%"> | ||
<StyledButton variant="contained" type="submit"> | ||
Save | ||
</StyledButton> | ||
</Box> | ||
</Box> | ||
</Box> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.