Skip to content

Commit

Permalink
Merge branch 'dev' of https://github.com/themeum/tutor into ecommerce…
Browse files Browse the repository at this point in the history
…-backend
  • Loading branch information
shewa12 committed Nov 19, 2024
2 parents 9fe5ded + b12062a commit 350d352
Show file tree
Hide file tree
Showing 13 changed files with 209 additions and 117 deletions.
49 changes: 33 additions & 16 deletions assets/react/front/pages/cart.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ document.addEventListener('DOMContentLoaded', function () {
button.setAttribute('disabled', 'disabled');
button.classList.add('is-loading');

const post = await ajaxHandler(formData);
const post = await ajaxHandler(formData);
const { status_code, data, message = defaultErrorMessage } = await post.json();

if (status_code === 201) {
tutor_toast(__('Success', 'tutor'), message, 'success');
const viewCartButton = `<a href="${data?.cart_page_url}" class="tutor-btn tutor-btn-outline-primary ${isSinglePage ? 'tutor-btn-lg tutor-btn-block' : 'tutor-btn-md'}">${__('View Cart', 'tutor')}</a>`
if (status_code === 201) {
tutor_toast(__('Success', 'tutor'), message, 'success');
const viewCartButton = `<a href="${data?.cart_page_url ?? "#"}" class="tutor-btn tutor-btn-outline-primary ${isSinglePage ? 'tutor-btn-lg tutor-btn-block' : 'tutor-btn-md'} ${!data?.cart_page_url ? 'tutor-cart-page-not-configured' : ''}">${__('View Cart', 'tutor')}</a>`
button.parentElement.innerHTML = viewCartButton;

// Create a custom event with cart count
Expand All @@ -34,17 +34,17 @@ document.addEventListener('DOMContentLoaded', function () {
// Dispatch the custom cart event
document.dispatchEvent(addToCartEvent);

} else {
tutor_toast(__('Failed', 'tutor'), message, 'error');
}
} catch (error) {
tutor_toast(__('Failed', 'tutor'), defaultErrorMessage, 'error');
} finally {
button.removeAttribute('disabled');
button.classList.remove('is-loading');
}
}
});
} else {
tutor_toast(__('Failed', 'tutor'), message, 'error');
}
} catch (error) {
tutor_toast(__('Failed', 'tutor'), defaultErrorMessage, 'error');
} finally {
button.removeAttribute('disabled');
button.classList.remove('is-loading');
}
}
});

// Remove course from card
const tutorCartPage = document.querySelector('.tutor-cart-page');
Expand All @@ -66,7 +66,7 @@ document.addEventListener('DOMContentLoaded', function () {
if (status_code === 200) {
document.querySelector('.tutor-cart-page-wrapper').parentElement.innerHTML = data?.cart_template;
tutor_toast(__('Success', 'tutor'), message, 'success');

// Trigger a custom event with cart count
const removeCartEvent = new CustomEvent('tutorRemoveCartEvent', {
detail: { cart_count: data?.cart_count },
Expand All @@ -86,4 +86,21 @@ document.addEventListener('DOMContentLoaded', function () {
}
});
}


// Display toast if cart page is not configured.
document.addEventListener('click', (e) => {
if (e.target.classList.contains('tutor-cart-page-not-configured')) {
e.preventDefault();
tutor_toast('Error!', 'Cart page is not configured.', 'error');
}
});

// Display toast if checkout page is not configured.
document.addEventListener('click', (e) => {
if (e.target.classList.contains('tutor-checkout-page-not-configured')) {
e.preventDefault();
tutor_toast('Error!', 'Checkout page is not configured.', 'error');
}
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ const HeaderActions = () => {
const postVisibility = useWatch({ name: 'visibility' });
const previewLink = useWatch({ name: 'preview_link' });
const isScheduleEnabled = useWatch({ name: 'isScheduleEnabled' });
const postDate = useWatch({ name: 'post_date' });
const scheduleDate = useWatch({ name: 'schedule_date' });
const scheduleTime = useWatch({ name: 'schedule_time' });

Expand All @@ -61,8 +60,7 @@ const HeaderActions = () => {
const handleSubmit = async (data: CourseFormData, postStatus: PostStatus) => {
const triggerAndFocus = (field: keyof CourseFormData) => {
Promise.resolve().then(() => {
form.trigger(field);
form.setFocus(field);
form.trigger(field, { shouldFocus: true });
});
};

Expand Down
80 changes: 61 additions & 19 deletions assets/react/v3/entries/payment-settings/components/PaymentItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,41 @@ import { useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import { css } from '@emotion/react';
import { __, sprintf } from '@wordpress/i18n';
import { useEffect, useState } from 'react';
import { Controller, useFormContext } from 'react-hook-form';

import Alert from '@Atoms/Alert';
import Button from '@Atoms/Button';
import SVGIcon from '@Atoms/SVGIcon';

import FormImageInput from '@Components/fields/FormImageInput';
import FormInput from '@Components/fields/FormInput';
import FormSelectInput from '@Components/fields/FormSelectInput';
import FormImageInput from '@Components/fields/FormImageInput';
import FormSwitch from '@Components/fields/FormSwitch';
import FormTextareaInput from '@Components/fields/FormTextareaInput';
import { useModal } from '@Components/modals/Modal';
import StaticConfirmationModal from '@Components/modals/StaticConfirmationModal';

import { borderRadius, colorTokens, fontWeight, lineHeight, shadow, spacing, zIndex } from '@Config/styles';
import For from '@Controls/For';
import Show from '@Controls/Show';
import { styleUtils } from '@Utils/style-utils';
import { animateLayoutChanges } from '@Utils/dndkit';
import { styleUtils } from '@Utils/style-utils';
import { isObject } from '@Utils/types';
import { requiredRule } from '@Utils/validation';

import Badge from '../atoms/Badge';
import { usePaymentContext } from '../contexts/payment-context';
import OptionWebhookUrl from '../fields/OptionWebhookUrl';
import Card from '../molecules/Card';
import {
type PaymentMethod,
type PaymentSettings,
getWebhookUrl,
manualMethodFields,
useInstallPaymentMutation,
useRemovePaymentMutation,
type PaymentMethod,
type PaymentSettings,
} from '../services/payment';
import Badge from '../atoms/Badge';
import { isObject } from '@Utils/types';
import { usePaymentContext } from '../contexts/payment-context';
import Alert from '@/v3/shared/atoms/Alert';

interface PaymentItemProps {
data: PaymentMethod;
Expand All @@ -44,6 +48,7 @@ const PaymentItem = ({ data, paymentIndex, isOverlay = false }: PaymentItemProps
const { payment_gateways } = usePaymentContext();
const { showModal } = useModal();
const form = useFormContext<PaymentSettings>();
const [isCollapsed, setIsCollapsed] = useState<boolean>(true);

const paymentFormFields = data.is_manual
? manualMethodFields
Expand Down Expand Up @@ -73,6 +78,17 @@ const PaymentItem = ({ data, paymentIndex, isOverlay = false }: PaymentItemProps
});
};

const hasEmptyFields = form
.getValues(`payment_methods.${paymentIndex}.fields`)
.some((field) => !['icon', 'webhook_url'].includes(field.name) && !field.value);

// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
useEffect(() => {
if (hasEmptyFields) {
form.setValue(`payment_methods.${paymentIndex}.is_active`, false, { shouldDirty: true });
}
}, [hasEmptyFields]);

return (
<div
{...attributes}
Expand All @@ -95,6 +111,14 @@ const PaymentItem = ({ data, paymentIndex, isOverlay = false }: PaymentItemProps
<Card
title={data.label}
titleIcon={data.icon}
toggleCollapse={() => {
setIsCollapsed(!isCollapsed);
}}
style={style}
hasBorder
noSeparator
collapsed={isDragging || isCollapsed}
dataAttribute="data-card"
subscription={data.support_subscription}
actionTray={
<div css={styles.cardActions}>
Expand Down Expand Up @@ -124,15 +148,23 @@ const PaymentItem = ({ data, paymentIndex, isOverlay = false }: PaymentItemProps
<Controller
name={`payment_methods.${paymentIndex}.is_active`}
control={form.control}
render={(controllerProps) => <FormSwitch {...controllerProps} />}
render={(controllerProps) => (
<FormSwitch
{...controllerProps}
onChange={async (value) => {
const isValid = await form.trigger(`payment_methods.${paymentIndex}.fields`);

if (value && !isValid) {
form.setValue(`payment_methods.${paymentIndex}.is_active`, false, { shouldDirty: true });
setIsCollapsed(false);
return;
}
}}
/>
)}
/>
</div>
}
style={style}
hasBorder
noSeparator
collapsed
dataAttribute="data-card"
>
<div css={styles.paymentWrapper}>
<div css={styles.fieldWrapper}>
Expand All @@ -143,8 +175,16 @@ const PaymentItem = ({ data, paymentIndex, isOverlay = false }: PaymentItemProps
<For each={paymentFormFields}>
{(field, index) => (
<Controller
key={field.name}
name={`payment_methods.${paymentIndex}.fields.${index}.value`}
control={form.control}
rules={
['icon', 'webhook_url'].includes(field.name || '')
? {
required: false,
}
: { ...requiredRule() }
}
render={(controllerProps) => {
switch (field.type) {
case 'select':
Expand Down Expand Up @@ -247,7 +287,7 @@ const PaymentItem = ({ data, paymentIndex, isOverlay = false }: PaymentItemProps
form.getValues('payment_methods').filter((_, index) => index !== paymentIndex),
{
shouldDirty: true,
}
},
);
} else {
const response = await removePaymentMutation.mutateAsync({
Expand All @@ -257,7 +297,7 @@ const PaymentItem = ({ data, paymentIndex, isOverlay = false }: PaymentItemProps
if (response.status_code === 200) {
form.setValue(
'payment_methods',
form.getValues('payment_methods').filter((_, index) => index !== paymentIndex)
form.getValues('payment_methods').filter((_, index) => index !== paymentIndex),
);

// Save settings
Expand Down Expand Up @@ -291,12 +331,14 @@ const styles = {
}
}
${isOverlay &&
css`
${
isOverlay &&
css`
[data-card] {
box-shadow: ${shadow.drag} !important;
}
`}
`
}
`,
cardActions: css`
display: flex;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const PaymentMethods = () => {
distance: 10,
},
}),
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }),
);

const activeSortItem = useMemo(() => {
Expand Down Expand Up @@ -99,7 +99,7 @@ const PaymentMethods = () => {
}}
</Show>
</DragOverlay>,
document.body
document.body,
)}
</DndContext>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
import Show from '@Controls/Show';
import { colorTokens, fontSize, spacing, zIndex } from '@Config/styles';
import { typography } from '@Config/typography';
import { useFormWithGlobalError } from '@Hooks/useFormWithGlobalError';
import { css } from '@emotion/react';
import { __ } from '@wordpress/i18n';
import { useEffect } from 'react';
import { FormProvider } from 'react-hook-form';
import { convertPaymentMethods, initialPaymentSettings, type PaymentSettings } from '../services/payment';
import PaymentMethods from './PaymentMethods';

import Button from '@Atoms/Button';
import ProBadge from '@Atoms/ProBadge';
import SVGIcon from '@Atoms/SVGIcon';
import ManualPaymentModal from './modals/ManualPaymentModal';
import { useModal } from '@Components/modals/Modal';

import StaticConfirmationModal from '@Components/modals/StaticConfirmationModal';
import PaymentGatewaysModal from './modals/PaymentGatewaysModal';
import ProBadge from '@Atoms/ProBadge';
import { tutorConfig } from '@Config/config';
import { colorTokens, fontSize, spacing, zIndex } from '@Config/styles';
import { typography } from '@Config/typography';
import Show from '@Controls/Show';
import { useFormWithGlobalError } from '@Hooks/useFormWithGlobalError';

import { usePaymentContext } from '../contexts/payment-context';
import { type PaymentSettings, convertPaymentMethods, initialPaymentSettings } from '../services/payment';
import PaymentMethods from './PaymentMethods';
import ManualPaymentModal from './modals/ManualPaymentModal';
import PaymentGatewaysModal from './modals/PaymentGatewaysModal';

const TaxSettingsPage = () => {
const { payment_gateways, payment_settings } = usePaymentContext();
Expand All @@ -27,17 +30,20 @@ const TaxSettingsPage = () => {
...initialPaymentSettings,
payment_methods: convertPaymentMethods([], payment_gateways),
},
mode: 'all',
});
const { reset } = form;
const formData = form.watch();

// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
useEffect(() => {
if (form.formState.isDirty) {
document.getElementById('save_tutor_option')?.removeAttribute('disabled');
form.reset(form.getValues(), { keepValues: true });
}
}, [form.formState.isDirty]);

// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
useEffect(() => {
if (payment_settings) {
const methods = convertPaymentMethods(payment_settings.payment_methods, payment_gateways);
Expand All @@ -64,7 +70,7 @@ const TaxSettingsPage = () => {
title: __('Reset to Default Settings?', 'tutor'),
description: __(
'WARNING! This will overwrite all customized settings of this section and reset them to default. Proceed with caution.',
'tutor'
'tutor',
),
confirmButtonText: __('Reset', 'tutor'),
},
Expand Down
Loading

0 comments on commit 350d352

Please sign in to comment.