diff --git a/src/pages/Admin/Charity/Dashboard/Schedule/AllocationSlider.tsx b/src/pages/Admin/Charity/Dashboard/Schedule/AllocationSlider.tsx index e73bafd972..5f851c3a1d 100644 --- a/src/pages/Admin/Charity/Dashboard/Schedule/AllocationSlider.tsx +++ b/src/pages/Admin/Charity/Dashboard/Schedule/AllocationSlider.tsx @@ -3,7 +3,7 @@ import leaf from "assets/icons/leaf.png"; import sendMoney from "assets/icons/send-money.png"; import Icon from "components/Icon"; import Image from "components/Image"; -import { Arrow, Content, Tooltip } from "components/Tooltip"; + import { humanize } from "helpers"; import type { ReactNode } from "react"; import type { Allocation } from "types/aws"; @@ -14,6 +14,7 @@ interface Props { /** cash, liq, lock */ value: Allocation; onChange: (value: Allocation) => void; + classes?: string; } export type Boundary = [number, number]; @@ -35,13 +36,14 @@ export function AllocationSlider({ value, onChange, amount, + classes = "", }: Props) { const boundary = toBoundary(value); return ( -
+
{/** percentages */} -
+
} @@ -67,7 +69,7 @@ export function AllocationSlider({ value={boundary} minStepsBetweenThumbs={0} onValueChange={(b: Boundary) => onChange(toAlloc(b))} - className="group/slider relative flex items-center select-none touch-none mt-5" + className="group/slider relative flex items-center select-none touch-none mt-2" disabled={disabled} > {props.title}

{props.pct}%

-

+

$ {humanize(num)}

- - {isLessThanMin ? ( - } - > - - Less than minimum of $50, would be processed next period. - - - - ) : null}
); } diff --git a/src/pages/Admin/Charity/Dashboard/Schedule/Edit.tsx b/src/pages/Admin/Charity/Dashboard/Schedule/Edit.tsx index ae1ba90cb6..7032b095a9 100644 --- a/src/pages/Admin/Charity/Dashboard/Schedule/Edit.tsx +++ b/src/pages/Admin/Charity/Dashboard/Schedule/Edit.tsx @@ -1,4 +1,5 @@ import Modal from "components/Modal"; +import { Info } from "components/Status"; import { useErrorContext } from "contexts/ErrorContext"; import { useModalContext } from "contexts/ModalContext"; import { humanize } from "helpers"; @@ -6,6 +7,7 @@ import { useState } from "react"; import { useEditEndowmentMutation } from "services/aws/aws"; import type { Allocation } from "types/aws"; import { AllocationSlider } from "./AllocationSlider"; +import { MIN_PROCESSING_AMOUNT, unprocessed } from "./common"; export function Edit(props: Allocation & { id: number; amount: number }) { const { closeModal } = useModalContext(); @@ -13,12 +15,23 @@ export function Edit(props: Allocation & { id: number; amount: number }) { const { handleError } = useErrorContext(); const [alloc, setAlloc] = useState(props); + const leftover = unprocessed(alloc, props.amount); + return ( - -
+ +

Edit allocation

$ {humanize(props.amount)}

+ + {leftover > 0 && ( + + We process donations monthly, with a minimum balance requirement of $ + {MIN_PROCESSING_AMOUNT} per bucket. If your balance in any bucket is + below ${MIN_PROCESSING_AMOUNT}, it will be carried over to the next + month until it exceeds $50 + + )} { try { await editEndow({ id: props.id, allocation: alloc }).unwrap(); diff --git a/src/pages/Admin/Charity/Dashboard/Schedule/Schedule.tsx b/src/pages/Admin/Charity/Dashboard/Schedule/Schedule.tsx index dc3c22f629..f04c62a549 100644 --- a/src/pages/Admin/Charity/Dashboard/Schedule/Schedule.tsx +++ b/src/pages/Admin/Charity/Dashboard/Schedule/Schedule.tsx @@ -1,13 +1,16 @@ import leaf from "assets/icons/leaf.png"; import sendMoney from "assets/icons/send-money.png"; import Icon from "components/Icon"; +import { Info } from "components/Status"; import { Arrow, Content, Tooltip } from "components/Tooltip"; import { useModalContext } from "contexts/ModalContext"; import { humanize } from "helpers"; import { useAdminContext } from "pages/Admin/Context"; import type { ReactNode } from "react"; import { useEndowmentQuery } from "services/aws/aws"; +import type { Allocation } from "types/aws"; import { Edit } from "./Edit"; +import { MIN_PROCESSING_AMOUNT, unprocessed } from "./common"; interface Props { amount: number; @@ -23,6 +26,16 @@ export function Schedule(props: Props) { fields: ["allocation"], }); + const allocation: Allocation = !endow + ? { cash: 0, liq: 50, lock: 50 } + : { + cash: endow.allocation?.cash ?? 0, + liq: endow.allocation?.liq ?? 50, + lock: endow.allocation?.lock ?? 50, + }; + + const leftover = unprocessed(allocation, props.amount); + return (
@@ -33,11 +46,7 @@ export function Schedule(props: Props) { className="hover:text-blue disabled:text-gray" onClick={() => { if (!endow) throw "@dev: no endow"; - showModal(Edit, { - ...(endow.allocation ?? { cash: 0, liq: 50, lock: 50 }), - amount: props.amount, - id, - }); + showModal(Edit, { ...allocation, amount: props.amount, id }); }} > @@ -50,6 +59,14 @@ export function Schedule(props: Props) { in {props.periodRemaining}

+ {leftover > 0 && ( + + We process donations monthly, with a minimum balance requirement of $ + {MIN_PROCESSING_AMOUNT} per bucket. If your balance in any bucket is + below ${MIN_PROCESSING_AMOUNT}, it will be carried over to the next + month until it exceeds $50 + + )}
} @@ -110,21 +127,11 @@ function Row({ pct, icon, title, amount }: IRow) { {pct ?? 50} % $ {humanize((pct / 100) * amount)} - {isLessThanMin && ( - } - > - - Less than min - - - - )}
); } diff --git a/src/pages/Admin/Charity/Dashboard/Schedule/common.ts b/src/pages/Admin/Charity/Dashboard/Schedule/common.ts new file mode 100644 index 0000000000..dcc446ba27 --- /dev/null +++ b/src/pages/Admin/Charity/Dashboard/Schedule/common.ts @@ -0,0 +1,11 @@ +import type { Allocation } from "types/aws"; + +export const MIN_PROCESSING_AMOUNT = 50; +export const unprocessed = (alloc: Allocation, amount: number) => { + return Object.values(alloc).reduce((unprocessed, pct) => { + const val = (pct / 100) * amount; + if (val === 0) return unprocessed; + if (val > MIN_PROCESSING_AMOUNT) return unprocessed; + return unprocessed + val; + }, 0); +}; diff --git a/tailwind.config.js b/tailwind.config.js index b0640267dc..1f8df0462f 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -78,6 +78,8 @@ module.exports = { l6: "#FFFFFF", }, amber: { + d2: "#b45309", + d1: "#d97706", DEFAULT: "#f59e0b", l3: "#fcd34d", l4: "#fef3c7",