Skip to content

Commit

Permalink
feat: support edit recurring charge (#702)
Browse files Browse the repository at this point in the history
Co-authored-by: Soham Parekh <[email protected]>
  • Loading branch information
satya-nutella and Soham Parekh authored Mar 17, 2023
1 parent d448335 commit 484d7f6
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,6 @@ import { DeleteOutlined, PlusOutlined } from "@ant-design/icons";
import { StepProps } from "./types";
import FeatureDisplay from "../FeatureDisplay";
import ComponentDisplay from "../ComponentDisplay";
import PlanRecurringCharges from "../PlanDetails/PlanRecurringCharges";
import capitalize from "../../../helpers/capitalize";
import removeUnderscore from "../../../helpers/removeUnderscore";
import createShortenedText from "../../../helpers/createShortenedText";
import CopyText from "../../base/CopytoClipboard";
import useMediaQuery from "../../../hooks/useWindowQuery";
import RecurringChargesDisplay from "../RecurringChargesDisplay";

Expand Down Expand Up @@ -56,6 +51,8 @@ const ChargesAndFeatures = ({ form, ...props }: StepProps) => {
<div>
<RecurringChargesDisplay
recurringCharges={props.recurringCharges}
handleEdit={props.handleEditRecurringCharge}
handleDelete={props.handleDeleteRecurringCharge}
/>
</div>

Expand Down
3 changes: 3 additions & 0 deletions frontend/src/components/Plans/CreatePlan/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ export interface StepProps {
handleComponentEdit: (component_id: string) => void;
deleteComponent: (component_id: string) => void;

handleEditRecurringCharge: (idx: number) => void;
handleDeleteRecurringCharge: (idx: number) => void;

showComponentModal: () => void;

setExternalLinks: (links: string[]) => void;
Expand Down
14 changes: 12 additions & 2 deletions frontend/src/components/Plans/RecurringChargeForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import React from "react";
import { Modal, Select, Input, Form, InputNumber } from "antd";
import { CurrencyType } from "../../types/pricing-unit-type";
import { components } from "../../gen-types";
import { CreateRecurringCharge } from "../../types/plan-type";

interface Props {
visible: boolean;
initialValues: CreateRecurringCharge | null;
onCancel: () => void;
onAddRecurringCharges: (
recurringCharge: components["schemas"]["PlanDetail"]["versions"][0]["recurring_charges"][number]
Expand All @@ -17,14 +19,21 @@ export default function RecurringChargeForm({
onCancel,
onAddRecurringCharges,
selectedCurrency,
initialValues,
}: Props) {
const [form] = Form.useForm();

const title = initialValues
? "Edit Recurring Charge"
: "Add Recurring Charge";

const okText = initialValues ? "Save" : "Add";

return (
<Modal
visible={visible}
title="Add Recurring Charge"
okText="Add"
title={title}
okText={okText}
okType="default"
cancelText="Cancel"
okButtonProps={{
Expand Down Expand Up @@ -53,6 +62,7 @@ export default function RecurringChargeForm({
invoicing_interval_count: undefined,
reset_interval_unit: null,
reset_interval_count: undefined,
...initialValues,
}}
name="recurring-charge-form"
onFinish={(values) => {
Expand Down
45 changes: 36 additions & 9 deletions frontend/src/components/Plans/RecurringChargesDisplay.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,53 @@
import { Typography } from "antd";
import { DeleteOutlined, EditOutlined } from "@ant-design/icons";
import { Button, Typography } from "antd";
import React from "react";
import { components } from "../../gen-types";
import capitalize from "../../helpers/capitalize";
import removeUnderscore from "../../helpers/removeUnderscore";

interface Props {
recurringCharges: components["schemas"]["PlanDetail"]["versions"][0]["recurring_charges"];
handleEdit: (idx: number) => void;
handleDelete: (idx: number) => void;
}

const RecurringChargesDisplay = ({ recurringCharges }: Props) => (
const RecurringChargesDisplay = ({
recurringCharges,
handleEdit,
handleDelete,
}: Props) => (
<div className="grid gap-6 grid-cols-1 xl:grid-cols-4">
{recurringCharges.map((recurringCharge) => (
{recurringCharges.map((recurringCharge, idx) => (
<div
key={recurringCharge.name}
className="pt-2 pb-4 bg-primary-50 mt-2 mb-2 p-4 min-h-[152px]"
>
<Typography.Title
className="pt-4 whitespace-pre-wrap !text-[18px]"
level={2}
>
{recurringCharge.name}
</Typography.Title>
<div className="flex items-center justify-between">
<Typography.Title
className="pt-4 whitespace-pre-wrap !text-[18px]"
level={2}
>
{recurringCharge.name}
</Typography.Title>
<div className="flex items-center justify-end">
<Button
key="edit"
type="text"
size="small"
icon={<EditOutlined />}
onClick={() => handleEdit(idx)}
/>

<Button
key="delete"
type="text"
size="small"
icon={<DeleteOutlined />}
danger
onClick={() => handleDelete(idx)}
/>
</div>
</div>

<div>
<div className="w-full h-[1.5px] mt-6 bg-card-divider mb-2" />
Expand Down
48 changes: 46 additions & 2 deletions frontend/src/pages/CreatePlan.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ function CreatePlan() {
const [month, setMonth] = useState(1);
const [editComponentItem, setEditComponentsItem] =
useState<CreateComponent>();
const [editRecurringChargeItem, setEditRecurringChargeItem] =
useState<CreateRecurringCharge | null>(null);
const [editRecurringChargeItemIdx, setEditRecurringChargeItemIdx] = useState<
number | null
>(null);
const [availableBillingTypes, setAvailableBillingTypes] = useState<
{ name: string; label: string }[]
>([{ label: "Monthly", name: "monthly" }]);
Expand Down Expand Up @@ -207,6 +212,24 @@ function CreatePlan() {
setcomponentVisible(true);
};

const handleRecurringChargeEdit = (idx: number) => {
const currentRecurringCharge = recurringCharges[idx];

setEditRecurringChargeItem(currentRecurringCharge);
setEditRecurringChargeItemIdx(idx);
setShowRecurringChargeModal(true);
};

const handleDeleteRecurringCharge = (idx: number) => {
setRecurringCharges((p) => {
const newRecurringCharges = [...p];

newRecurringCharges.splice(idx, 1);

return newRecurringCharges;
});
};

const deleteComponent = (metric_id: string) => {
setComponentsData(
componentsData.filter((item) => item.metric_id !== metric_id)
Expand Down Expand Up @@ -462,6 +485,8 @@ function CreatePlan() {
setShowRecurringChargeModal={setShowRecurringChargeModal}
recurringCharges={recurringCharges}
setRecurringCharges={setRecurringCharges}
handleEditRecurringCharge={handleRecurringChargeEdit}
handleDeleteRecurringCharge={handleDeleteRecurringCharge}
/>
</Form>

Expand Down Expand Up @@ -489,10 +514,29 @@ function CreatePlan() {
<RecurringChargeForm
visible={showRecurringChargeModal}
selectedCurrency={selectedCurrency}
onCancel={() => setShowRecurringChargeModal(false)}
initialValues={editRecurringChargeItem}
onCancel={() => {
setShowRecurringChargeModal(false);
setEditRecurringChargeItem(null);
setEditRecurringChargeItemIdx(null);
}}
onAddRecurringCharges={(newRecurringCharge) => {
setRecurringCharges((prev) => [...prev, newRecurringCharge]);
if (
editRecurringChargeItem &&
typeof editRecurringChargeItemIdx === "number"
) {
setRecurringCharges((prev) => [
...prev.slice(0, editRecurringChargeItemIdx),
newRecurringCharge,
...prev.slice(editRecurringChargeItemIdx + 1),
]);
} else {
setRecurringCharges((prev) => [...prev, newRecurringCharge]);
}

setShowRecurringChargeModal(false);
setEditRecurringChargeItem(null);
setEditRecurringChargeItemIdx(null);
}}
/>
) : null}
Expand Down
51 changes: 48 additions & 3 deletions frontend/src/pages/EditPlan.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
PlanDetailType,
CreateInitialVersionType,
CreatePlanVersionType,
CreateRecurringCharge,
} from "../types/plan-type";
import { Customer, Organization, Plan } from "../api/api";
import { FeatureType } from "../types/feature-type";
Expand Down Expand Up @@ -79,6 +80,11 @@ function EditPlan({ type, plan, versionIndex }: Props) {
plan.versions[versionIndex].price_adjustment?.price_adjustment_type ??
"none"
);
const [editRecurringChargeItemIdx, setEditRecurringChargeItemIdx] = useState<
number | null
>(null);
const [editRecurringChargeItem, setEditRecurringChargeItem] =
useState<CreateRecurringCharge | null>(null);

const latestVersion = sortBy(
plan.versions.filter((v) => typeof v.version === "number"),
Expand Down Expand Up @@ -288,6 +294,25 @@ function EditPlan({ type, plan, versionIndex }: Props) {
const deleteComponent = (id: string) => {
setComponentsData(componentsData.filter((item) => item.id !== id));
};

const handleRecurringChargeEdit = (idx: number) => {
const currentRecurringCharge = recurringCharges[idx];

setEditRecurringChargeItem(currentRecurringCharge);
setEditRecurringChargeItemIdx(idx);
setShowRecurringChargeModal(true);
};

const handleDeleteRecurringCharge = (idx: number) => {
setRecurringCharges((p) => {
const newRecurringCharges = [...p];

newRecurringCharges.splice(idx, 1);

return newRecurringCharges;
});
};

const hideFeatureModal = () => {
setFeatureVisible(false);
};
Expand Down Expand Up @@ -469,7 +494,6 @@ function EditPlan({ type, plan, versionIndex }: Props) {
}

mutation.mutate(newVersion);
return;
}
})
.catch((err) => {
Expand Down Expand Up @@ -684,6 +708,8 @@ function EditPlan({ type, plan, versionIndex }: Props) {
customers={customers}
targetCustomerId={targetCustomerId}
setTargetCustomerId={setTargetCustomerId}
handleEditRecurringCharge={handleRecurringChargeEdit}
handleDeleteRecurringCharge={handleDeleteRecurringCharge}
/>
</Form>

Expand Down Expand Up @@ -711,11 +737,30 @@ function EditPlan({ type, plan, versionIndex }: Props) {
{showRecurringChargeModal ? (
<RecurringChargeForm
visible={showRecurringChargeModal}
initialValues={editRecurringChargeItem}
selectedCurrency={selectedCurrency}
onCancel={() => setShowRecurringChargeModal(false)}
onCancel={() => {
setShowRecurringChargeModal(false);
setEditRecurringChargeItem(null);
setEditRecurringChargeItemIdx(null);
}}
onAddRecurringCharges={(newRecurringCharge) => {
setRecurringCharges((prev) => [...prev, newRecurringCharge]);
if (
editRecurringChargeItem &&
typeof editRecurringChargeItemIdx === "number"
) {
setRecurringCharges((prev) => [
...prev.slice(0, editRecurringChargeItemIdx),
newRecurringCharge,
...prev.slice(editRecurringChargeItemIdx + 1),
]);
} else {
setRecurringCharges((prev) => [...prev, newRecurringCharge]);
}

setShowRecurringChargeModal(false);
setEditRecurringChargeItem(null);
setEditRecurringChargeItemIdx(null);
}}
/>
) : null}
Expand Down

0 comments on commit 484d7f6

Please sign in to comment.