Skip to content

Commit

Permalink
Merge pull request #510 from evershopcommerce/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
treoden authored Apr 29, 2024
2 parents efd2b7c + 76e15a2 commit 3096c81
Show file tree
Hide file tree
Showing 115 changed files with 3,117 additions and 1,875 deletions.
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

0 comments on commit 3096c81

Please sign in to comment.