Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #510

Merged
merged 12 commits into from
Apr 29, 2024
3 changes: 2 additions & 1 deletion packages/evershop/bin/dev/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
process.env.ALLOW_CONFIG_MUTATIONS = true;
require('dotenv').config();
const { start } = require('@evershop/evershop/bin/lib/startUp');
const { watchComponents } = require('../lib/watch/watchComponents');

(async () => {
await start();
await start(watchComponents);
})();
42 changes: 16 additions & 26 deletions packages/evershop/bin/lib/watch/watchComponents.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,24 @@
const chokidar = require('chokidar');
const { resolve, sep, normalize } = require('path');
const touch = require('touch');
const { resolve } = require('path');
const { CONSTANTS } = require('@evershop/evershop/src/lib/helpers');
const { Componee } = require('@evershop/evershop/src/lib/componee/Componee');
const {
createComponents
} = require('@evershop/evershop/bin/lib/createComponents');
const { getRoutes } = require('@evershop/evershop/src/lib/router/Router');
const {
isBuildRequired
} = require('@evershop/evershop/src/lib/webpack/isBuildRequired');

function watchComponents() {
chokidar
.watch('**/**/pages/*.js', {
ignored: /node_modules[\\/]/,
ignoreInitial: true,
persistent: true
})
.on('all', (event, path) => {
const modulePath = resolve(CONSTANTS.ROOTPATH, path).split(
normalize('/views/')
)[0];
Componee.updateModuleComponents({
name: modulePath.split(sep).reverse()[0],
path: modulePath
});
const routes = getRoutes();
createComponents(
routes.filter((r) => isBuildRequired(r)),
true
.watch(
['./packages/**/*.jsx', './extensions/**/*.jsx', './themes/**/*.jsx'],
{
ignored: /node_modules[\\/]/,
ignoreInitial: true,
persistent: true
}
)
.on('add', () => {
touch(
resolve(
CONSTANTS.MOLDULESPATH,
'../components/common/react/client/Index.jsx'
)
);
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,18 @@ export function VariantModal({
</div>
<div className="col-span-1">
<div className="grid grid-cols-2 gap-x-1 border-b border-divider pb-15 mb-15">
{variantAttributes.map((a) => (
{variantAttributes.map((a, index) => (
<div key={a.attributeId} className="mt-1 col">
<div>
<label>{a.attributeName}</label>
</div>
<input
type="hidden"
name={`attributes[${index}][attribute_code]`}
value={a.attributeCode}
/>
<Field
name={a.attributeCode}
name={`attributes[${index}][value]`}
validationRules={['notEmpty']}
value={
variant?.attributes.find(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useQuery } from 'urql';
import { Card } from '@components/admin/cms/Card';
import { CreateVariant } from '@components/admin/catalog/productEdit/variants/CreateVariant';
import Spinner from '@components/common/Spinner';
import { Variant } from './Variant';
import { Variant } from '@components/admin/catalog/productEdit/variants/Variant';

export const VariantQuery = `
query Query($productId: ID!) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
import CogIcon from '@heroicons/react/outline/CogIcon';
import { useModal } from '@components/common/modal/useModal';
import MethodForm from './MethodForm';
import MethodForm from '@components/admin/checkout/shippingSetting/MethodForm';

function Method({ method, getZones }) {
const modal = useModal();
Expand All @@ -12,7 +13,20 @@ function Method({ method, getZones }) {
<td className="border-none py-1">
{method.isEnabled ? 'Enabled' : 'Disabled'}
</td>
<td className="border-none py-1">{method.cost?.text}</td>
<td className="border-none py-1">
{method.cost?.text || (
<a
href="#"
className="text-interactive"
onClick={(e) => {
e.preventDefault();
modal.openModal();
}}
>
<CogIcon width={22} height={22} />
</a>
)}
</td>
<td className="border-none py-1">
{method.conditionType
? `${method.min || 0} <= ${method.conditionType} <= ${
Expand Down Expand Up @@ -62,6 +76,18 @@ Method.propTypes = {
cost: PropTypes.shape({
text: PropTypes.string.isRequired
}),
priceBasedCost: PropTypes.arrayOf(
PropTypes.shape({
minPrice: PropTypes.number.isRequired,
cost: PropTypes.number.isRequired
})
),
weightBasedCost: PropTypes.arrayOf(
PropTypes.shape({
minWeight: PropTypes.number.isRequired,
cost: PropTypes.number.isRequired
})
),
conditionType: PropTypes.string.isRequired,
min: PropTypes.number.isRequired,
max: PropTypes.number.isRequired,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import CreatableSelect from 'react-select/creatable';
import Spinner from '@components/common/Spinner';
import { useQuery } from 'urql';
import { toast } from 'react-toastify';
import PriceBasedPrice from '@components/admin/checkout/shippingSetting/PriceBasedPrice';
import WeightBasedPrice from '@components/admin/checkout/shippingSetting/WeightBasedPrice';

const MethodsQuery = `
query Methods {
Expand Down Expand Up @@ -83,9 +85,18 @@ Condition.defaultProps = {
};

function MethodForm({ saveMethodApi, closeModal, getZones, method }) {
const [type, setType] = React.useState(
method?.calculateApi ? 'api' : 'flat_rate'
);
const [type, setType] = React.useState(() => {
if (method?.calculateApi) {
return 'api';
}
if (method?.priceBasedCost) {
return 'price_based_rate';
}
if (method?.weightBasedCost) {
return 'weight_based_rate';
}
return 'flat_rate';
});
const [isLoading, setIsLoading] = React.useState(false);
const [shippingMethod, setMethod] = React.useState(
method
Expand Down Expand Up @@ -138,6 +149,7 @@ function MethodForm({ saveMethodApi, closeModal, getZones, method }) {
if (!response.error) {
await getZones({ requestPolicy: 'network-only' });
closeModal();
toast.success('Shipping method saved successfully');
} else {
toast.error(response.error.message);
}
Expand Down Expand Up @@ -166,6 +178,8 @@ function MethodForm({ saveMethodApi, closeModal, getZones, method }) {
name="calculation_type"
options={[
{ text: 'Flat rate', value: 'flat_rate' },
{ text: 'Price based rate', value: 'price_based_rate' },
{ text: 'Weight based rate', value: 'weight_based_rate' },
{ text: 'API calculate', value: 'api' }
]}
defaultValue={method?.calculateApi ? 'api' : 'flat_rate'}
Expand All @@ -183,6 +197,12 @@ function MethodForm({ saveMethodApi, closeModal, getZones, method }) {
value={method?.cost?.value}
/>
)}
{type === 'price_based_rate' && (
<PriceBasedPrice lines={method?.priceBasedCost || []} />
)}
{type === 'weight_based_rate' && (
<WeightBasedPrice lines={method?.weightBasedCost || []} />
)}
{type === 'api' && (
<Field
name="calculate_api"
Expand Down Expand Up @@ -242,6 +262,26 @@ MethodForm.propTypes = {
cost: PropTypes.shape({
value: PropTypes.string
}),
priceBasedCost: PropTypes.arrayOf(
PropTypes.shape({
minPrice: PropTypes.shape({
value: PropTypes.number
}),
cost: PropTypes.shape({
value: PropTypes.number
})
})
),
weightBasedCost: PropTypes.arrayOf(
PropTypes.shape({
minWeight: PropTypes.shape({
value: PropTypes.number
}),
cost: PropTypes.shape({
value: PropTypes.number
})
})
),
conditionType: PropTypes.string,
min: PropTypes.string,
max: PropTypes.string
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
import { useModal } from '@components/common/modal/useModal';
import Method from './Method';
import MethodForm from './MethodForm';
import Method from '@components/admin/checkout/shippingSetting/Method';
import MethodForm from '@components/admin/checkout/shippingSetting/MethodForm';

export function Methods({ getZones, methods, addMethodApi }) {
const modal = useModal();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Field } from '@components/common/form/Field';

export default function PriceBasedPrice({ lines }) {
// This is a table with 3 columns: Min Price, Shipping Cost, and Action
const [rows, setRows] = React.useState(
lines.map((line) => ({
...line,
key: Math.random().toString(36).substring(7)
}))
);
return (
<div className="my-2">
<table className="border-collapse divide-y">
<thead>
<tr>
<th className="border-none">Min Price</th>
<th className="border-none">Shipping Cost</th>
<th className="border-none">Action</th>
</tr>
</thead>
<tbody>
{rows.map((row, index) => (
// Create a random key for each row
<tr key={row.key} className="border-divider py-2">
<td className="border-none">
<Field
name={`price_based_cost[${index}][min_price]`}
placeholder="Min Price"
type="text"
value={row.minPrice?.value}
validationRules={['notEmpty', 'number']}
/>
</td>
<td className="border-none">
<Field
name={`price_based_cost[${index}][cost]`}
placeholder="Shipping Cost"
type="text"
value={row.cost?.value}
validationRules={['notEmpty', 'number']}
/>
</td>
<td className="border-none">
<a
href="#"
onClick={() => {
setRows(rows.filter((r) => r.key !== row.key));
}}
className="text-critical"
>
Delete
</a>
</td>
</tr>
))}
</tbody>
<tfoot>
<tr>
<td colSpan="3" className="border-none">
<a
href="#"
className="text-interactive"
onClick={() => {
setRows([
...rows,
{
min_price: '',
shipping_cost: '',
key: Math.random().toString(36).substring(7)
}
]);
}}
>
+ Add Line
</a>
</td>
</tr>
</tfoot>
</table>
</div>
);
}

PriceBasedPrice.propTypes = {
lines: PropTypes.arrayOf(
PropTypes.shape({
minPrice: PropTypes.shape({
value: PropTypes.number.isRequired
}),
cost: PropTypes.shape({
value: PropTypes.number.isRequired
})
})
)
};

PriceBasedPrice.defaultProps = {
lines: []
};
Loading
Loading