diff --git a/src/api/marketplace/orders/views.py b/src/api/marketplace/orders/views.py index 3414223d..e68c980e 100644 --- a/src/api/marketplace/orders/views.py +++ b/src/api/marketplace/orders/views.py @@ -729,6 +729,20 @@ def put(self, request, pk): }, status=status.HTTP_400_BAD_REQUEST, ) + elif order_item.status == "accepted" and order_item.service_master.twitter_service_type == "spaces": + # Disable the cancel button for spaces 1 hour before the publish_date but allow if it's in past + if order_item.publish_date < timezone.now() + timezone.timedelta(hours=1) and order_item.publish_date > timezone.now(): + return Response( + { + "isSuccess": False, + "message": "Order cannot be cancelled as publish date of a space is less than 1 hour", + "data": None, + "errors": "Order cannot be cancelled as publish date of a space is less than 1 hour", + }, + status=status.HTTP_400_BAD_REQUEST, + ) + + order_status = "cancelled" if request.user_account.id == order.buyer.id else "rejected" # See if an on chain transaction is already created escrow = self.get_escrow(order) diff --git a/src/ui/app/business/dashboard/page.tsx b/src/ui/app/business/dashboard/page.tsx index fc93522d..8d5285f9 100644 --- a/src/ui/app/business/dashboard/page.tsx +++ b/src/ui/app/business/dashboard/page.tsx @@ -359,6 +359,42 @@ export default function BusinessDashboardPage() { } }; + const isOrderCancellationAllowed = (order: OrderType): boolean => { + const orderStatus = order?.status; + const orderItems = order?.order_item_order_id; + + const isValidOrderStatus = + orderStatus === ORDER_STATUS.ACCEPTED || + orderStatus === ORDER_STATUS.PENDING; + const hasValidOrderItems = + orderItems?.filter( + (item: OrderItemType) => + item?.status === ORDER_ITEM_STATUS.PUBLISHED || + item?.status === ORDER_ITEM_STATUS.SCHEDULED + ).length === 0; + + let isNotWithinAnHourOfSpaces = true; + + orderItems?.forEach((order_item: OrderItemType) => { + if ( + order_item?.status === ORDER_ITEM_STATUS.ACCEPTED && + order_item?.service_master?.twitter_service_type === + SERVICE_MASTER_TWITTER_SERVICE_TYPE.SPACES + ) { + if ( + dayjs(order_item?.publish_date) > dayjs() && + dayjs(order_item?.publish_date).diff(dayjs(), "hour") < 1 + ) { + isNotWithinAnHourOfSpaces = false; + } + } + }); + + return ( + isValidOrderStatus && hasValidOrderItems && isNotWithinAnHourOfSpaces + ); + }; + const cancelOrder = async (order: OrderType) => { try { setCancelLoading(true); @@ -878,27 +914,21 @@ export default function BusinessDashboardPage() { disabled={cancellationInProgress} /> )} - {(params?.row?.status === ORDER_STATUS.ACCEPTED || - params?.row?.status === ORDER_STATUS.PENDING) && - params?.row?.order_item_order_id?.filter( - (item: OrderItemType) => - item?.status === ORDER_ITEM_STATUS.PUBLISHED || - item?.status === ORDER_ITEM_STATUS.SCHEDULED - ).length === 0 && ( - { - cancelOrder(params?.row); - }} - deleteElement={ - - - - } - title={`Order ${params?.row?.order_code}`} - hide={true} - disabled={cancellationInProgress} - /> - )} + {isOrderCancellationAllowed(params?.row) && ( + { + cancelOrder(params?.row); + }} + deleteElement={ + + + + } + title={`Order ${params?.row?.order_code}`} + hide={true} + disabled={cancellationInProgress} + /> + )} ); }, diff --git a/src/ui/src/components/checkoutComponents/orderItemForm/index.tsx b/src/ui/src/components/checkoutComponents/orderItemForm/index.tsx index 364bc081..4d85bed9 100644 --- a/src/ui/src/components/checkoutComponents/orderItemForm/index.tsx +++ b/src/ui/src/components/checkoutComponents/orderItemForm/index.tsx @@ -16,6 +16,7 @@ import { ORDER_ITEM_STATUS, ROLE_NAME, SERVICE_MASTER_TWITTER_SERVICE_TYPE, + SPACES_DISCLAIMER_TEXT, } from "@/src/utils/consts"; import DeleteIcon from "@mui/icons-material/Delete"; import { @@ -481,11 +482,7 @@ export default function OrderItemForm({ mt: 1, }} > - Spaces need to be manually scheduled by the influencer through their - mobile app. Business owners will need to then manually validate / - approve the scheduled space. Xflunencer will not be able to track the - status of the space due to limitations in the X (formerly Twitter) - API. + {SPACES_DISCLAIMER_TEXT} )} - Spaces need to be manually scheduled by the influencer through - their mobile app. Business owners will need to then manually - validate / approve the scheduled space. Xflunencer will not be - able to track the status of the space due to limitations in the - X (formerly Twitter) API. + {SPACES_DISCLAIMER_TEXT} )} diff --git a/src/ui/src/utils/consts.ts b/src/ui/src/utils/consts.ts index a26adc7b..3a07bf90 100644 --- a/src/ui/src/utils/consts.ts +++ b/src/ui/src/utils/consts.ts @@ -167,6 +167,9 @@ export const TWITTER_PROMOTION_TEXT = export const XFLUENCER_PROMOTION_TEXT = "Hi I've just signed up for XFluencer, an incredible platform connecting influencers and businesses like never before. Please find my referral code: "; +export const SPACES_DISCLAIMER_TEXT = + "Spaces need to be manually scheduled by the influencer through their mobile app. Business owners will need to then manually validate / approve the scheduled space. Xflunencer will not be able to track the status of the space due to limitations in the X (formerly Twitter) API. Spaces cannot be cancelled one hour before publish date"; + export const IDL: Xfluencer = { version: "1.0.0", name: "xfluencer",