🦄 Simple taxes (#2072)
* Tax configuration - implement channels view (#2048) * Add channels view * Fix channels view import * Remove legacy stories references * Fix link in configuration * Update snapshots * Remove sample checkboxes props * Disable hover in country exceptions * Update snapshots * Extract country exception rows to seperate component * Extract components to seperate files * Remove duplicated section name * Remove backlink * Add translations to section names * Extract messages * Add ListItemLink component * Replace navigator with link in TaxChannelsMenu * Fix horizontal scroll in TaxChannelsMenu * Change codegen to build from custom schema * Build types * Update fragments * Add fixtures * Change any to proper types * Add story for tax channels page * Replace MUI Skeleton with Saleor Skeleton * Change clsx import to classnames * Fix checkboxes shadows in settings card * Update IDs in fixtures * Fix offset in TaxChannelsMenu * Update snapshots * Remove any from TaxSettings * Fix todos * Change relative marginLeft to before pseudoelement * Extract styles to seperate files * Change folder structure * Extract redirect logic to custom hook * Update snapshots * Fix comment * Add early return in channels view * Tax configuration - implement countries view (#2053) * Add channels view * Remove sample checkboxes props * Disable hover in country exceptions * Extract country exception rows to seperate component * Extract components to seperate files * Remove duplicated section name * Remove backlink * Add translations to section names * Replace navigator with link in TaxChannelsMenu * Fix horizontal scroll in TaxChannelsMenu * Change any to proper types * Add story for tax channels page * Replace MUI Skeleton with Saleor Skeleton * Change clsx import to classnames * Fix checkboxes shadows in settings card * Update IDs in fixtures * Fix offset in TaxChannelsMenu * Remove any from TaxSettings * Add countries list view * Add TaxCountryMenu component * Add CountryList page * Change channels menu rows height * Change countries menu rows height * Add TaxInput component * Add tax classes rates to countries page * Fix search input padding * Add minmax to TaxInput * Add searching through tax class rates * Extract messages * Add better handlers * Add fullWidth to TaxInput * Specify type for TaxInputs * Remove spinboxes on firefox * Remove custom spinboxes * Remove maxHeight from menu rows * Post-rebase fix * Change setter to formchagne * Add TaxConfiguration fragment * Add isDefault field to taxClass * Add fixtures * Shape data * Replace useEffect with useTaxUrlRedirect * Fix country names in menu * Add country page story * Add early return in countries view * Unify loading states between channels and countries pages * Handle special chars and case insensitiveness in local search * Replace navigate function with ListItemLink * Move styles to seperate file * Move styles to seperate file * Migrate to strict null checks * Remove unnecessary optional chaining * Change overflow scroll to Y only * Add useMemo on finding selected country * Add useMemo on local search * Translate labels in page tabs * Change url from /taxes/classes to /taxes/tax-classes * Remove capitalization from strings * Extract messages * Bump macaw to 0.6.2 * Update snapshots * Add spinboxes explanation comment * Handle empty state * Add tax classes view (#2093) * Add TaxClass fragment * Build types * Add tax classes to fixtures * Add tax classes view * wip Add tax classes page * Add tax classes menu * Add TaxRate fragment * Extract logic * Handle loading state & add story * Extract messages * Update snapshots * Change schema building from schema back to introspection * Update schema * Update fragments * Build types * Update fixtures * Reshape data * Move styles to seperate file * Use getById * Add explicit undefined * Comment out unfinished modal stories * Update snapshots * Taxes - add API calls in channels view (#2106) * Build types * Add TaxRate fragment * Update snapshots * Add taxConfigurationList query * Add taxCountriesList query * Add TaxClassesList query * Rename TaxConfigurationsList query * Handle empty state * Fix types post-rebase * Add form to TaxChannelsPage * wip Add dialog for handling country exceptions * wip Fix dialog url * wip Add update exceptions handlers * Add dialog story * Fix type errors * Add mutation support * Fix types in story * Add transition state to submit button * Add notifier * Extract messages * Remove unused import * Add backlink in savebar * Update snapshots * Fix link in navigation * Update snapshots * Remove message from tax config error fragment * Add hook description * Use useStateFromProps * Remove error handling * Improve url & path function names * Use theme.spacing in TaxCountryDialog styles * Remove redundant key modification * Revert "Use useStateFromProps" This reverts commit d3c68b04701cf935e917d7baa3ed1361ca3446d5. * Move initial map to parent & add open dependency to countries state * Use useModalDialogOpen * Fix state update * Remove scrolls & add ellipsis in side menu * Center checkboxes * Update snapshots * Add fake div for list alignment * Trigger deployment * Close modal on submit * Remove divider on last ListItem * Align add country button * Wrap grid child in div to avoid card stretching * Update snapshots * Trigger changes in add/delete exceptions * Trigger change on expcetion checkboxes * Add trailing commas * Connect countries view to API (#2178) * Add empty states * Update countries view urls * Remove unused import * Add country modal to countries view * Update schema * Implement country view mutations & error fragments * Implement tax class update mutation * Add sidebar temporary state for new configs * Remove unused imports * Wrap in form * Add savebar & fix search * Update schema * Add form wrapper * Fix types * Extract messages * Bump macaw * Update snapshots * Fix comma dangles * Update snapshots * Notify about mutation success * Add logic for mixing current and new rates * Workaround for sending null rates * Fix filling form with correct data after submitting * Handle deleting configuration * Fix selected banner * Remove leftover comment * Add handler for country configuration delete * Trigger deployment * Clean up useEffects causing infinite render loops * Sort countries from api by name * Fix card bottom padding * Remove bottom divider & fix padding * Remove scroll wrapper in side menu * Update snapshots * Remove scroll wrapper from tax classes menu * Update snapshots * Refresh form to initial onSubmit * Revert "Refresh form to initial onSubmit" This reverts commit 42414237d35086da63f4aa088c8072411429b1d8. * Allow only 3 decimal characters in tax inputs * Update snapshots * Update schema * Update types * Change logic from default tax class to null class * Fix sorting * Send empty country rates as nulls in mutation * Extract messages * Update lockfile * Update schema * Drop default tax classes * Update snapshots * Post-rebase fixes * Connect tax classes view to API (#2334) * Add mutations * Handle empty state * Wrap page in form * Update stories * Build types * Handle tax class delete * Handle update tax class * Update stories * Handle tax class change name * Add mutation state to savebar * Handle creating new tax classes * Extract messages * Specify type * Update stories * Sort rates * Fix skeleton rendering * Remove placeholders * Fix skeleton rendering on country list * Update snapshots * Change initial pagination to 100 * Disallow creating multiple new tax classes * Disallow creating multiple country configurations * Fix messages * Autofocus on new tax class name * Add country name to header * Temporarily comment out broken code in tax channels * Update snapshots * Update snapshots post-rebase * Add tax strategies & assigning tax classes (#2369) * Update fragments * Add optional merging in useForm * Handle tax strategies * Update snapshots * Update fixtures * Extract messages * Remove unused shop query fields * Fix breaking bug when fetchMore is used in non-searchable SingleAutocompleteSelectFields * Migrate product types to tax classes * Add tax classes to shipping methods * Use encapsulated logic in product types * Fix product type stories * Fix shipping fixtures * Fix product type type mismatch * Fix shipping stories * Fix product type fixtures * Fix mismatching types * Extract messages * Update snapshots * Update snapshots * Fix comment * Drop deprecated graphql fields * Replace tax types with tax classes in product create view * Replace tax types with tax classes in product update view * Fix tests, stories, fixtures * Extract messages * Update snapshots * Move status messages to commonStatusMessages * Handle empty array case in tax class change handler * Reuse messages * Simple taxes bugfixes (#2395) * Fix tax channels menu - dense layout * Change view names to fit convention * Fix per country exceptions in tax channels view * Fix skeleton rendering on tax countries card title * Filter out existing countries from modal * Update snapshots * Fix deleting country configuration * Disallow negative values in tax inputs * Handle empty tax classes view * Allow empty options in shipping & product types views tax class assignment field * Modify undefined rates in tax classes view * Update macaw-ui * Fix UI on channels view * Fix UI on countries view * Fix UI on countries view * Align tax class rate label to the right * Updaste snapshots * Extract messages * Fix adding rates on new tax class * Fix key errors * Update schema * Build types * Allow empty rates in taxClassUpdate mutation * Extract tax channels change country function as a handler * Deprecate useStateFromProps * Change useStateFromProps to useStateUpdate * Fix dividers * Delete delete icon on new tax classes * Update snapshots * Update lockfile * Update macaw to 0.6.6 * Update snapshots * Specify type of input in country change handler * Extract autofocus logic to custom hook * Replace alternative with switch statement * Extract country exclusion logic from JSX * Update lockfile * Update lockfile * Trigger deployment * Fix invisible select markers * Fix linter issue * Fix crashing product details page * Fix e2e error * Update snapshots * Allow view taxes with any staff permissions (#2510) * Update after rebase Co-authored-by: Dawid <tarasiukdawid@gmail.com>
This commit is contained in:
parent
6e1230b10d
commit
5c1a62171d
131 changed files with 17441 additions and 7433 deletions
6027
introspection.json
6027
introspection.json
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,8 @@
|
||||||
{
|
{
|
||||||
|
"+2VydL": {
|
||||||
|
"context": "card title",
|
||||||
|
"string": "Country exceptions"
|
||||||
|
},
|
||||||
"+2VzH4": {
|
"+2VzH4": {
|
||||||
"context": "avatar change button",
|
"context": "avatar change button",
|
||||||
"string": "Change"
|
"string": "Change"
|
||||||
|
@ -31,14 +35,14 @@
|
||||||
"context": "variant sku",
|
"context": "variant sku",
|
||||||
"string": "SKU {sku}"
|
"string": "SKU {sku}"
|
||||||
},
|
},
|
||||||
|
"+Jgot0": {
|
||||||
|
"context": "tax class for a product type",
|
||||||
|
"string": "Tax class"
|
||||||
|
},
|
||||||
"+NUzaQ": {
|
"+NUzaQ": {
|
||||||
"context": "check to mark this account as active",
|
"context": "check to mark this account as active",
|
||||||
"string": "User account active"
|
"string": "User account active"
|
||||||
},
|
},
|
||||||
"+OV+Gj": {
|
|
||||||
"context": "button",
|
|
||||||
"string": "Fetch taxes"
|
|
||||||
},
|
|
||||||
"+PbHKD": {
|
"+PbHKD": {
|
||||||
"context": "dialog header",
|
"context": "dialog header",
|
||||||
"string": "Capture Payment"
|
"string": "Capture Payment"
|
||||||
|
@ -148,6 +152,10 @@
|
||||||
"context": "product type shipping settings, section header",
|
"context": "product type shipping settings, section header",
|
||||||
"string": "Shipping"
|
"string": "Shipping"
|
||||||
},
|
},
|
||||||
|
"/5r4he": {
|
||||||
|
"context": "label for button",
|
||||||
|
"string": "Add country"
|
||||||
|
},
|
||||||
"/68iG8": {
|
"/68iG8": {
|
||||||
"context": "product export to csv file, header",
|
"context": "product export to csv file, header",
|
||||||
"string": "Information exported"
|
"string": "Information exported"
|
||||||
|
@ -176,8 +184,9 @@
|
||||||
"context": "section description",
|
"context": "section description",
|
||||||
"string": "Strategy defines the preference of warehouses for stock allocations and reservations."
|
"string": "Strategy defines the preference of warehouses for stock allocations and reservations."
|
||||||
},
|
},
|
||||||
"/JENWS": {
|
"/ILyIf": {
|
||||||
"string": "Reduced Tax Rates"
|
"context": "tax classes menu header",
|
||||||
|
"string": "Tax class label"
|
||||||
},
|
},
|
||||||
"/KWNJW": {
|
"/KWNJW": {
|
||||||
"context": "order discount was updated event title",
|
"context": "order discount was updated event title",
|
||||||
|
@ -269,9 +278,6 @@
|
||||||
"context": "order history message",
|
"context": "order history message",
|
||||||
"string": "Order cancel information was sent to customer"
|
"string": "Order cancel information was sent to customer"
|
||||||
},
|
},
|
||||||
"07KB2d": {
|
|
||||||
"string": "Country Code"
|
|
||||||
},
|
|
||||||
"0AQH0Q": {
|
"0AQH0Q": {
|
||||||
"string": "Plugin is misconfigured and cannot be activated"
|
"string": "Plugin is misconfigured and cannot be activated"
|
||||||
},
|
},
|
||||||
|
@ -286,9 +292,6 @@
|
||||||
"context": "min price in channel",
|
"context": "min price in channel",
|
||||||
"string": "Min. value"
|
"string": "Min. value"
|
||||||
},
|
},
|
||||||
"0GJfWd": {
|
|
||||||
"string": "Country Name"
|
|
||||||
},
|
|
||||||
"0MetrR": {
|
"0MetrR": {
|
||||||
"context": "webhook input help text",
|
"context": "webhook input help text",
|
||||||
"string": "This URL will receive webhook POST requests"
|
"string": "This URL will receive webhook POST requests"
|
||||||
|
@ -309,6 +312,10 @@
|
||||||
"context": "dialog header",
|
"context": "dialog header",
|
||||||
"string": "Unassign Collection From Sale"
|
"string": "Unassign Collection From Sale"
|
||||||
},
|
},
|
||||||
|
"0V1q0d": {
|
||||||
|
"context": "add country dialog header",
|
||||||
|
"string": "Choose country you want to add"
|
||||||
|
},
|
||||||
"0VDwAP": {
|
"0VDwAP": {
|
||||||
"context": "checkbox label",
|
"context": "checkbox label",
|
||||||
"string": "Send shipment details to customer"
|
"string": "Send shipment details to customer"
|
||||||
|
@ -317,6 +324,10 @@
|
||||||
"context": "menu item name",
|
"context": "menu item name",
|
||||||
"string": "Name"
|
"string": "Name"
|
||||||
},
|
},
|
||||||
|
"0a0fLZ": {
|
||||||
|
"context": "countries list menu label when no countries are assigned",
|
||||||
|
"string": "There are no countries assigned"
|
||||||
|
},
|
||||||
"0dPP8O": {
|
"0dPP8O": {
|
||||||
"string": "Order #{orderId} was placed"
|
"string": "Order #{orderId} was placed"
|
||||||
},
|
},
|
||||||
|
@ -658,9 +669,6 @@
|
||||||
"context": "no category set error",
|
"context": "no category set error",
|
||||||
"string": "Product category not set"
|
"string": "Product category not set"
|
||||||
},
|
},
|
||||||
"3BTtL2": {
|
|
||||||
"string": "No countries found"
|
|
||||||
},
|
|
||||||
"3C3Nj5": {
|
"3C3Nj5": {
|
||||||
"context": "button",
|
"context": "button",
|
||||||
"string": "Add variant"
|
"string": "Add variant"
|
||||||
|
@ -780,9 +788,6 @@
|
||||||
"context": "order status",
|
"context": "order status",
|
||||||
"string": "Returned"
|
"string": "Returned"
|
||||||
},
|
},
|
||||||
"4EuJKs": {
|
|
||||||
"string": "All products prices are entered with tax included"
|
|
||||||
},
|
|
||||||
"4JW9iJ": {
|
"4JW9iJ": {
|
||||||
"context": "home section name",
|
"context": "home section name",
|
||||||
"string": "Home"
|
"string": "Home"
|
||||||
|
@ -837,6 +842,10 @@
|
||||||
"context": "variant attribute checkbox",
|
"context": "variant attribute checkbox",
|
||||||
"string": "Variant Selection"
|
"string": "Variant Selection"
|
||||||
},
|
},
|
||||||
|
"4p3bjX": {
|
||||||
|
"context": "tax strategy combobox choice",
|
||||||
|
"string": "Use flat rates"
|
||||||
|
},
|
||||||
"4prRLv": {
|
"4prRLv": {
|
||||||
"string": "Permission is out of your scope"
|
"string": "Permission is out of your scope"
|
||||||
},
|
},
|
||||||
|
@ -1034,6 +1043,10 @@
|
||||||
"context": "WarehouseSettings local warehouse description",
|
"context": "WarehouseSettings local warehouse description",
|
||||||
"string": "If selected customer will be able to choose this warehouse as pickup point. Ordered products will be only fulfilled from this warehouse stock"
|
"string": "If selected customer will be able to choose this warehouse as pickup point. Ordered products will be only fulfilled from this warehouse stock"
|
||||||
},
|
},
|
||||||
|
"6HHPFy": {
|
||||||
|
"context": "tax strategy combobox hint",
|
||||||
|
"string": "Select the method of tax calculation"
|
||||||
|
},
|
||||||
"6JlXeD": {
|
"6JlXeD": {
|
||||||
"context": "button",
|
"context": "button",
|
||||||
"string": "Create page type"
|
"string": "Create page type"
|
||||||
|
@ -1118,6 +1131,10 @@
|
||||||
"7+GBlj": {
|
"7+GBlj": {
|
||||||
"string": "Error code {errorCode} {fieldError}"
|
"string": "Error code {errorCode} {fieldError}"
|
||||||
},
|
},
|
||||||
|
"720c51": {
|
||||||
|
"context": "tax classes name input placeholder",
|
||||||
|
"string": "Tax rate name"
|
||||||
|
},
|
||||||
"73RU3R": {
|
"73RU3R": {
|
||||||
"context": "deactivate app",
|
"context": "deactivate app",
|
||||||
"string": "Are you sure you want to disable this app? Your data will be kept until you reactivate the app. You will be still billed for the app."
|
"string": "Are you sure you want to disable this app? Your data will be kept until you reactivate the app. You will be still billed for the app."
|
||||||
|
@ -1164,6 +1181,10 @@
|
||||||
"context": "navigator section header",
|
"context": "navigator section header",
|
||||||
"string": "Search in Catalog"
|
"string": "Search in Catalog"
|
||||||
},
|
},
|
||||||
|
"7U/NPm": {
|
||||||
|
"context": "tax class rates list label when no country is selected",
|
||||||
|
"string": "Add country to access tax classes"
|
||||||
|
},
|
||||||
"7U8GRy": {
|
"7U8GRy": {
|
||||||
"string": "Shipping method successfully updated"
|
"string": "Shipping method successfully updated"
|
||||||
},
|
},
|
||||||
|
@ -1226,6 +1247,10 @@
|
||||||
"context": "navigator placeholder",
|
"context": "navigator placeholder",
|
||||||
"string": "Order Number"
|
"string": "Order Number"
|
||||||
},
|
},
|
||||||
|
"8BBMRj": {
|
||||||
|
"context": "default tax class name for new tax classes",
|
||||||
|
"string": "New tax class"
|
||||||
|
},
|
||||||
"8EGagh": {
|
"8EGagh": {
|
||||||
"context": "search box label",
|
"context": "search box label",
|
||||||
"string": "Filter Countries"
|
"string": "Filter Countries"
|
||||||
|
@ -1312,13 +1337,14 @@
|
||||||
"97l2MO": {
|
"97l2MO": {
|
||||||
"string": "Customer Email"
|
"string": "Customer Email"
|
||||||
},
|
},
|
||||||
|
"98Nw4g": {
|
||||||
|
"context": "card subtitle",
|
||||||
|
"string": "Rendered prices"
|
||||||
|
},
|
||||||
"98WMlR": {
|
"98WMlR": {
|
||||||
"context": "header",
|
"context": "header",
|
||||||
"string": "Translation Product Variant \"{productName}\" - {languageCode}"
|
"string": "Translation Product Variant \"{productName}\" - {languageCode}"
|
||||||
},
|
},
|
||||||
"98isC5": {
|
|
||||||
"string": "Show gross prices to customers in the storefront"
|
|
||||||
},
|
|
||||||
"9C7PZE": {
|
"9C7PZE": {
|
||||||
"context": "navigation section name",
|
"context": "navigation section name",
|
||||||
"string": "Navigation"
|
"string": "Navigation"
|
||||||
|
@ -1427,9 +1453,6 @@
|
||||||
"context": "collection label",
|
"context": "collection label",
|
||||||
"string": "Visible"
|
"string": "Visible"
|
||||||
},
|
},
|
||||||
"9xUIAh": {
|
|
||||||
"string": "Tax group"
|
|
||||||
},
|
|
||||||
"9xlPgt": {
|
"9xlPgt": {
|
||||||
"context": "used staff users counter",
|
"context": "used staff users counter",
|
||||||
"string": "{count}/{max} members"
|
"string": "{count}/{max} members"
|
||||||
|
@ -1589,6 +1612,10 @@
|
||||||
"context": "number of subcategories",
|
"context": "number of subcategories",
|
||||||
"string": "Subcategories"
|
"string": "Subcategories"
|
||||||
},
|
},
|
||||||
|
"BJtUQI": {
|
||||||
|
"context": "button",
|
||||||
|
"string": "Add"
|
||||||
|
},
|
||||||
"BL/Lbk": {
|
"BL/Lbk": {
|
||||||
"context": "install app permissions",
|
"context": "install app permissions",
|
||||||
"string": "Installing this app will give it following permissions:"
|
"string": "Installing this app will give it following permissions:"
|
||||||
|
@ -1721,6 +1748,10 @@
|
||||||
"context": "dialog content",
|
"context": "dialog content",
|
||||||
"string": "{counter,plural,one{Are you sure you want to delete this shipping zone?} other{Are you sure you want to delete {displayQuantity} shipping zones?}}"
|
"string": "{counter,plural,one{Are you sure you want to delete this shipping zone?} other{Are you sure you want to delete {displayQuantity} shipping zones?}}"
|
||||||
},
|
},
|
||||||
|
"CFT171": {
|
||||||
|
"context": "card header title",
|
||||||
|
"string": "Country list"
|
||||||
|
},
|
||||||
"CG+awx": {
|
"CG+awx": {
|
||||||
"context": "dialog content",
|
"context": "dialog content",
|
||||||
"string": "Which address would you like to use as shipping address for selected customer:"
|
"string": "Which address would you like to use as shipping address for selected customer:"
|
||||||
|
@ -1777,10 +1808,6 @@
|
||||||
"context": "dialog header",
|
"context": "dialog header",
|
||||||
"string": "Delete Page Types"
|
"string": "Delete Page Types"
|
||||||
},
|
},
|
||||||
"CdIHMu": {
|
|
||||||
"context": "select tax ratte",
|
|
||||||
"string": "Tax Rate"
|
|
||||||
},
|
|
||||||
"ChAjJu": {
|
"ChAjJu": {
|
||||||
"context": "character limit",
|
"context": "character limit",
|
||||||
"string": "{numberOfCharacters} of {maxCharacters} characters"
|
"string": "{numberOfCharacters} of {maxCharacters} characters"
|
||||||
|
@ -1834,6 +1861,10 @@
|
||||||
"context": "checkbox label",
|
"context": "checkbox label",
|
||||||
"string": "Grant this app full access to the store"
|
"string": "Grant this app full access to the store"
|
||||||
},
|
},
|
||||||
|
"D5Wtf/": {
|
||||||
|
"context": "table header column",
|
||||||
|
"string": "Country name"
|
||||||
|
},
|
||||||
"D8nsBc": {
|
"D8nsBc": {
|
||||||
"context": "no warehouses info",
|
"context": "no warehouses info",
|
||||||
"string": "There are no warehouses set up for your store. To add stock quantity to the variant please <a>configure a warehouse</a>"
|
"string": "There are no warehouses set up for your store. To add stock quantity to the variant please <a>configure a warehouse</a>"
|
||||||
|
@ -2004,6 +2035,10 @@
|
||||||
"context": "delete app",
|
"context": "delete app",
|
||||||
"string": "Deleting {name}, you will remove installation of the app. If you are paying for app subscription, remember to unsubscribe from the app in Saleor Marketplace. Are you sure you want to delete the app?"
|
"string": "Deleting {name}, you will remove installation of the app. If you are paying for app subscription, remember to unsubscribe from the app in Saleor Marketplace. Are you sure you want to delete the app?"
|
||||||
},
|
},
|
||||||
|
"EYkW1J": {
|
||||||
|
"context": "checkbox label",
|
||||||
|
"string": "Charge taxes for this channel"
|
||||||
|
},
|
||||||
"Eau5AV": {
|
"Eau5AV": {
|
||||||
"string": "Manage Products Channel Availability"
|
"string": "Manage Products Channel Availability"
|
||||||
},
|
},
|
||||||
|
@ -2097,9 +2132,6 @@
|
||||||
"FNAZoh": {
|
"FNAZoh": {
|
||||||
"string": "Last login"
|
"string": "Last login"
|
||||||
},
|
},
|
||||||
"FNKhkx": {
|
|
||||||
"string": "Charge taxes on shipping rates"
|
|
||||||
},
|
|
||||||
"FNT4b+": {
|
"FNT4b+": {
|
||||||
"context": "tabel column header",
|
"context": "tabel column header",
|
||||||
"string": "Product"
|
"string": "Product"
|
||||||
|
@ -2499,9 +2531,6 @@
|
||||||
"context": "create gift card product alert message",
|
"context": "create gift card product alert message",
|
||||||
"string": "Create a gift card product"
|
"string": "Create a gift card product"
|
||||||
},
|
},
|
||||||
"HtQGEH": {
|
|
||||||
"string": "Successfully fetched tax rates"
|
|
||||||
},
|
|
||||||
"HtfL5/": {
|
"HtfL5/": {
|
||||||
"context": "button",
|
"context": "button",
|
||||||
"string": "Open App"
|
"string": "Open App"
|
||||||
|
@ -3242,6 +3271,14 @@
|
||||||
"context": "section header",
|
"context": "section header",
|
||||||
"string": "All Subcategories"
|
"string": "All Subcategories"
|
||||||
},
|
},
|
||||||
|
"Nj9iSB": {
|
||||||
|
"context": "table header column",
|
||||||
|
"string": "Tax rate"
|
||||||
|
},
|
||||||
|
"NlEVVT": {
|
||||||
|
"context": "label for button",
|
||||||
|
"string": "Create class"
|
||||||
|
},
|
||||||
"NlSJMM": {
|
"NlSJMM": {
|
||||||
"context": "channels section name",
|
"context": "channels section name",
|
||||||
"string": "Channels"
|
"string": "Channels"
|
||||||
|
@ -3604,10 +3641,6 @@
|
||||||
"context": "table header name col label",
|
"context": "table header name col label",
|
||||||
"string": "Name"
|
"string": "Name"
|
||||||
},
|
},
|
||||||
"QHB48n": {
|
|
||||||
"context": "header",
|
|
||||||
"string": "Tax Rates in {countryName}"
|
|
||||||
},
|
|
||||||
"QJG+d/": {
|
"QJG+d/": {
|
||||||
"context": "staff added type order discount",
|
"context": "staff added type order discount",
|
||||||
"string": "Staff added"
|
"string": "Staff added"
|
||||||
|
@ -3694,6 +3727,10 @@
|
||||||
"Qox+kb": {
|
"Qox+kb": {
|
||||||
"string": "on field {fieldName}"
|
"string": "on field {fieldName}"
|
||||||
},
|
},
|
||||||
|
"QpBqa9": {
|
||||||
|
"context": "label for radio button",
|
||||||
|
"string": "Product prices are entered without tax"
|
||||||
|
},
|
||||||
"Qph0GE": {
|
"Qph0GE": {
|
||||||
"context": "dialog content",
|
"context": "dialog content",
|
||||||
"string": "Add a new address:"
|
"string": "Add a new address:"
|
||||||
|
@ -3772,6 +3809,10 @@
|
||||||
"context": "issue card button label",
|
"context": "issue card button label",
|
||||||
"string": "Issue card"
|
"string": "Issue card"
|
||||||
},
|
},
|
||||||
|
"Rfk+8B": {
|
||||||
|
"context": "tax classes menu label when there are no tax classes",
|
||||||
|
"string": "There are no tax classes"
|
||||||
|
},
|
||||||
"Rj8LxK": {
|
"Rj8LxK": {
|
||||||
"string": "Add search engine title and description to make this collection easier to find"
|
"string": "Add search engine title and description to make this collection easier to find"
|
||||||
},
|
},
|
||||||
|
@ -3793,6 +3834,10 @@
|
||||||
"context": "dialog header",
|
"context": "dialog header",
|
||||||
"string": "Unassign Attribute from Page Type"
|
"string": "Unassign Attribute from Page Type"
|
||||||
},
|
},
|
||||||
|
"RqtZQ6": {
|
||||||
|
"context": "tax classes card header",
|
||||||
|
"string": "Tax class rates"
|
||||||
|
},
|
||||||
"RrCui3": {
|
"RrCui3": {
|
||||||
"string": "Summary"
|
"string": "Summary"
|
||||||
},
|
},
|
||||||
|
@ -3975,6 +4020,10 @@
|
||||||
"context": "product availability available date",
|
"context": "product availability available date",
|
||||||
"string": "Set available on"
|
"string": "Set available on"
|
||||||
},
|
},
|
||||||
|
"TJ7WHA": {
|
||||||
|
"context": "tax strategy combobox choice",
|
||||||
|
"string": "Use tax app"
|
||||||
|
},
|
||||||
"TKmub+": {
|
"TKmub+": {
|
||||||
"string": "This field is required"
|
"string": "This field is required"
|
||||||
},
|
},
|
||||||
|
@ -4009,13 +4058,9 @@
|
||||||
"context": "orders section name",
|
"context": "orders section name",
|
||||||
"string": "Orders"
|
"string": "Orders"
|
||||||
},
|
},
|
||||||
"TalJlD": {
|
"TfzIXS": {
|
||||||
"context": "tax rate for a product type",
|
"context": "tax classes card header",
|
||||||
"string": "Tax"
|
"string": "General information"
|
||||||
},
|
|
||||||
"TfY/Pi": {
|
|
||||||
"context": "checkbox",
|
|
||||||
"string": "Charge taxes on this product"
|
|
||||||
},
|
},
|
||||||
"TjGYna": {
|
"TjGYna": {
|
||||||
"context": "product inventory, checkbox",
|
"context": "product inventory, checkbox",
|
||||||
|
@ -4075,6 +4120,10 @@
|
||||||
"context": "no gift card products and types alert message",
|
"context": "no gift card products and types alert message",
|
||||||
"string": "{createGiftCardProductType} and {giftCardProduct} to start selling gift cards in your store."
|
"string": "{createGiftCardProductType} and {giftCardProduct} to start selling gift cards in your store."
|
||||||
},
|
},
|
||||||
|
"UBuKZ9": {
|
||||||
|
"context": "searchbar placeholder",
|
||||||
|
"string": "Country"
|
||||||
|
},
|
||||||
"UCHtG6": {
|
"UCHtG6": {
|
||||||
"context": "button",
|
"context": "button",
|
||||||
"string": "About"
|
"string": "About"
|
||||||
|
@ -4127,9 +4176,6 @@
|
||||||
"UaYJJ8": {
|
"UaYJJ8": {
|
||||||
"string": "Are you sure you want to delete {name} search tab?"
|
"string": "Are you sure you want to delete {name} search tab?"
|
||||||
},
|
},
|
||||||
"Ubath+": {
|
|
||||||
"string": "No reduced tax categories found"
|
|
||||||
},
|
|
||||||
"Uf3oHA": {
|
"Uf3oHA": {
|
||||||
"context": "add new menu item",
|
"context": "add new menu item",
|
||||||
"string": "Create new item"
|
"string": "Create new item"
|
||||||
|
@ -4398,6 +4444,10 @@
|
||||||
"context": "order refund amount",
|
"context": "order refund amount",
|
||||||
"string": "Shipment Cost"
|
"string": "Shipment Cost"
|
||||||
},
|
},
|
||||||
|
"WIxSDm": {
|
||||||
|
"context": "card header",
|
||||||
|
"string": "{country} class rates"
|
||||||
|
},
|
||||||
"WMGoqz": {
|
"WMGoqz": {
|
||||||
"context": "used by filter label",
|
"context": "used by filter label",
|
||||||
"string": "Used by"
|
"string": "Used by"
|
||||||
|
@ -4469,6 +4519,10 @@
|
||||||
"context": "title",
|
"context": "title",
|
||||||
"string": "There’s a problem with app."
|
"string": "There’s a problem with app."
|
||||||
},
|
},
|
||||||
|
"Ww69SE": {
|
||||||
|
"context": "search input placeholder",
|
||||||
|
"string": "Search tax classes"
|
||||||
|
},
|
||||||
"WwNtFn": {
|
"WwNtFn": {
|
||||||
"context": "delete product variant",
|
"context": "delete product variant",
|
||||||
"string": "Are you sure you want to delete {name}?"
|
"string": "Are you sure you want to delete {name}?"
|
||||||
|
@ -4794,6 +4848,10 @@
|
||||||
"context": "stock exceeded dialog description",
|
"context": "stock exceeded dialog description",
|
||||||
"string": "Stock for items shown below are not enough to prepare fulfillment:"
|
"string": "Stock for items shown below are not enough to prepare fulfillment:"
|
||||||
},
|
},
|
||||||
|
"ZAaXfz": {
|
||||||
|
"context": "Taxes section title",
|
||||||
|
"string": "Countries"
|
||||||
|
},
|
||||||
"ZDJEat": {
|
"ZDJEat": {
|
||||||
"context": "button",
|
"context": "button",
|
||||||
"string": "Load More"
|
"string": "Load More"
|
||||||
|
@ -4932,6 +4990,10 @@
|
||||||
"aI80kg": {
|
"aI80kg": {
|
||||||
"string": "Properties"
|
"string": "Properties"
|
||||||
},
|
},
|
||||||
|
"aJm/by": {
|
||||||
|
"context": "Taxes section title",
|
||||||
|
"string": "Tax classes"
|
||||||
|
},
|
||||||
"aMwxYb": {
|
"aMwxYb": {
|
||||||
"string": "Countries"
|
"string": "Countries"
|
||||||
},
|
},
|
||||||
|
@ -5018,6 +5080,10 @@
|
||||||
"b1zuN9": {
|
"b1zuN9": {
|
||||||
"string": "Price"
|
"string": "Price"
|
||||||
},
|
},
|
||||||
|
"b2DlTO": {
|
||||||
|
"context": "Taxes section title",
|
||||||
|
"string": "Channels"
|
||||||
|
},
|
||||||
"b6L9n7": {
|
"b6L9n7": {
|
||||||
"context": "voucher is active until date",
|
"context": "voucher is active until date",
|
||||||
"string": "Ends"
|
"string": "Ends"
|
||||||
|
@ -5026,6 +5092,10 @@
|
||||||
"context": "product price",
|
"context": "product price",
|
||||||
"string": "Price"
|
"string": "Price"
|
||||||
},
|
},
|
||||||
|
"bDBiac": {
|
||||||
|
"context": "dropdown or column label",
|
||||||
|
"string": "Tax class"
|
||||||
|
},
|
||||||
"bDHiYK": {
|
"bDHiYK": {
|
||||||
"context": "gift card export success alert description",
|
"context": "gift card export success alert description",
|
||||||
"string": "We are currently exporting your gift card codes. As soon as your file is available it will be sent to your email address"
|
"string": "We are currently exporting your gift card codes. As soon as your file is available it will be sent to your email address"
|
||||||
|
@ -5190,6 +5260,10 @@
|
||||||
"context": "button",
|
"context": "button",
|
||||||
"string": "Unassign and save"
|
"string": "Unassign and save"
|
||||||
},
|
},
|
||||||
|
"cVjewM": {
|
||||||
|
"context": "label for radio button",
|
||||||
|
"string": "Product prices are entered with tax"
|
||||||
|
},
|
||||||
"cW1RIo": {
|
"cW1RIo": {
|
||||||
"context": "section header",
|
"context": "section header",
|
||||||
"string": "Media View"
|
"string": "Media View"
|
||||||
|
@ -5802,10 +5876,6 @@
|
||||||
"context": "dialog content",
|
"context": "dialog content",
|
||||||
"string": "{counter,plural,one{Are you sure you want to unassign this variant?} other{Are you sure you want to unassign {displayQuantity} variants?}}"
|
"string": "{counter,plural,one{Are you sure you want to unassign this variant?} other{Are you sure you want to unassign {displayQuantity} variants?}}"
|
||||||
},
|
},
|
||||||
"iYH3Y7": {
|
|
||||||
"context": "checkbox",
|
|
||||||
"string": "Override the product type's tax rate"
|
|
||||||
},
|
|
||||||
"ibnmEd": {
|
"ibnmEd": {
|
||||||
"context": "voucher country range",
|
"context": "voucher country range",
|
||||||
"string": "Countries"
|
"string": "Countries"
|
||||||
|
@ -5901,6 +5971,10 @@
|
||||||
"jHJmjf": {
|
"jHJmjf": {
|
||||||
"string": "No results"
|
"string": "No results"
|
||||||
},
|
},
|
||||||
|
"jMzyU8": {
|
||||||
|
"context": "tax classes card header",
|
||||||
|
"string": "Tax classes"
|
||||||
|
},
|
||||||
"jNSOSu": {
|
"jNSOSu": {
|
||||||
"context": "cancelled fulfillment, section header",
|
"context": "cancelled fulfillment, section header",
|
||||||
"string": "Refunded and Returned ({quantity})"
|
"string": "Refunded and Returned ({quantity})"
|
||||||
|
@ -6065,6 +6139,10 @@
|
||||||
"context": "product updated at",
|
"context": "product updated at",
|
||||||
"string": "Last updated"
|
"string": "Last updated"
|
||||||
},
|
},
|
||||||
|
"kXqn6A": {
|
||||||
|
"context": "table header column",
|
||||||
|
"string": "Charge taxes"
|
||||||
|
},
|
||||||
"kYYbrv": {
|
"kYYbrv": {
|
||||||
"context": "channel publication date",
|
"context": "channel publication date",
|
||||||
"string": "Published since {date}"
|
"string": "Published since {date}"
|
||||||
|
@ -6182,9 +6260,6 @@
|
||||||
"context": "money",
|
"context": "money",
|
||||||
"string": "from {money}"
|
"string": "from {money}"
|
||||||
},
|
},
|
||||||
"la9cZ4": {
|
|
||||||
"string": "Tax Rate"
|
|
||||||
},
|
|
||||||
"labkPK": {
|
"labkPK": {
|
||||||
"context": "search gift card placeholder",
|
"context": "search gift card placeholder",
|
||||||
"string": "Search Gift Cards, e.g {exampleGiftCardCode}"
|
"string": "Search Gift Cards, e.g {exampleGiftCardCode}"
|
||||||
|
@ -6215,9 +6290,9 @@
|
||||||
"context": "password reset, button",
|
"context": "password reset, button",
|
||||||
"string": "Send an email with reset link"
|
"string": "Send an email with reset link"
|
||||||
},
|
},
|
||||||
"lnQAos": {
|
"lnteBJ": {
|
||||||
"context": "header",
|
"context": "country rates list label for the default rate",
|
||||||
"string": "Taxes"
|
"string": "Country default rate"
|
||||||
},
|
},
|
||||||
"lqIzC8": {
|
"lqIzC8": {
|
||||||
"string": "This field needs to be unique"
|
"string": "This field needs to be unique"
|
||||||
|
@ -6288,10 +6363,6 @@
|
||||||
"context": "NoChannels content",
|
"context": "NoChannels content",
|
||||||
"string": "No channels to assign. Please first assign them for the product."
|
"string": "No channels to assign. Please first assign them for the product."
|
||||||
},
|
},
|
||||||
"mUb8Gt": {
|
|
||||||
"context": "section header",
|
|
||||||
"string": "Taxes"
|
|
||||||
},
|
|
||||||
"mWQt3s": {
|
"mWQt3s": {
|
||||||
"string": "No. of Products"
|
"string": "No. of Products"
|
||||||
},
|
},
|
||||||
|
@ -6439,6 +6510,10 @@
|
||||||
"context": "attribute internal name",
|
"context": "attribute internal name",
|
||||||
"string": "Slug"
|
"string": "Slug"
|
||||||
},
|
},
|
||||||
|
"ngAgBy": {
|
||||||
|
"context": "tax class rates list label when no countries are assigned",
|
||||||
|
"string": "There are no countries using this tax class yet, use {tab} tab to assign tax rates."
|
||||||
|
},
|
||||||
"njBulj": {
|
"njBulj": {
|
||||||
"context": "check to require attribute to have value",
|
"context": "check to require attribute to have value",
|
||||||
"string": "Value Required"
|
"string": "Value Required"
|
||||||
|
@ -6634,6 +6709,10 @@
|
||||||
"pVFoOk": {
|
"pVFoOk": {
|
||||||
"string": "Are you sure you want to delete {collectionName}?"
|
"string": "Are you sure you want to delete {collectionName}?"
|
||||||
},
|
},
|
||||||
|
"pWClYm": {
|
||||||
|
"context": "card title",
|
||||||
|
"string": "Default settings"
|
||||||
|
},
|
||||||
"paa4m0": {
|
"paa4m0": {
|
||||||
"string": "Successfully created product type"
|
"string": "Successfully created product type"
|
||||||
},
|
},
|
||||||
|
@ -6673,6 +6752,10 @@
|
||||||
"context": "notes about customer, header",
|
"context": "notes about customer, header",
|
||||||
"string": "Notes"
|
"string": "Notes"
|
||||||
},
|
},
|
||||||
|
"puRlnN": {
|
||||||
|
"context": "card subtitle",
|
||||||
|
"string": "Entered prices"
|
||||||
|
},
|
||||||
"puikeb": {
|
"puikeb": {
|
||||||
"context": "button",
|
"context": "button",
|
||||||
"string": "Delete Address"
|
"string": "Delete Address"
|
||||||
|
@ -6746,6 +6829,10 @@
|
||||||
"context": "stock exceeded dialog title",
|
"context": "stock exceeded dialog title",
|
||||||
"string": "Not enough stock"
|
"string": "Not enough stock"
|
||||||
},
|
},
|
||||||
|
"qbcNjQ": {
|
||||||
|
"context": "table header column",
|
||||||
|
"string": "Tax name"
|
||||||
|
},
|
||||||
"qbmeUI": {
|
"qbmeUI": {
|
||||||
"context": "dialog header",
|
"context": "dialog header",
|
||||||
"string": "Delete Order Drafts"
|
"string": "Delete Order Drafts"
|
||||||
|
@ -7042,6 +7129,10 @@
|
||||||
"context": "button",
|
"context": "button",
|
||||||
"string": "Accept"
|
"string": "Accept"
|
||||||
},
|
},
|
||||||
|
"skklRz": {
|
||||||
|
"context": "table header column",
|
||||||
|
"string": "Show gross prices in storefront"
|
||||||
|
},
|
||||||
"sn2awN": {
|
"sn2awN": {
|
||||||
"context": "ExitFormPrompt cancel button",
|
"context": "ExitFormPrompt cancel button",
|
||||||
"string": "Discard changes"
|
"string": "Discard changes"
|
||||||
|
@ -7163,6 +7254,9 @@
|
||||||
"context": "window title",
|
"context": "window title",
|
||||||
"string": "Create collection"
|
"string": "Create collection"
|
||||||
},
|
},
|
||||||
|
"tthToS": {
|
||||||
|
"string": "Disabled"
|
||||||
|
},
|
||||||
"ttk0w7": {
|
"ttk0w7": {
|
||||||
"context": "resend code to customer description",
|
"context": "resend code to customer description",
|
||||||
"string": "Gift Card Code will be resent to email provided during checkout. You can provide a different email address if you want to:"
|
"string": "Gift Card Code will be resent to email provided during checkout. You can provide a different email address if you want to:"
|
||||||
|
@ -7196,6 +7290,10 @@
|
||||||
"u24Ppd": {
|
"u24Ppd": {
|
||||||
"string": "This attribute cannot be assigned to this product type"
|
"string": "This attribute cannot be assigned to this product type"
|
||||||
},
|
},
|
||||||
|
"u34css": {
|
||||||
|
"context": "label for empty list in channels list",
|
||||||
|
"string": "There are no exceptions for this channel"
|
||||||
|
},
|
||||||
"u3sYPH": {
|
"u3sYPH": {
|
||||||
"context": "independent of any particular day, eg. 11:35",
|
"context": "independent of any particular day, eg. 11:35",
|
||||||
"string": "Time"
|
"string": "Time"
|
||||||
|
@ -7734,6 +7832,10 @@
|
||||||
"context": "attribute can be searched in dashboard",
|
"context": "attribute can be searched in dashboard",
|
||||||
"string": "Searchable"
|
"string": "Searchable"
|
||||||
},
|
},
|
||||||
|
"yLfbSh": {
|
||||||
|
"context": "support label",
|
||||||
|
"string": "Channel name"
|
||||||
|
},
|
||||||
"yMi8I8": {
|
"yMi8I8": {
|
||||||
"context": "dialog header",
|
"context": "dialog header",
|
||||||
"string": "Dectivate App"
|
"string": "Dectivate App"
|
||||||
|
|
1292
schema.graphql
1292
schema.graphql
File diff suppressed because it is too large
Load diff
|
@ -14,6 +14,7 @@ export interface FormProps<TData, TErrors>
|
||||||
onSubmit?: (data: TData) => SubmitPromise<TErrors[]> | void;
|
onSubmit?: (data: TData) => SubmitPromise<TErrors[]> | void;
|
||||||
formId?: FormId;
|
formId?: FormId;
|
||||||
checkIfSaveIsDisabled?: CheckIfSaveIsDisabledFnType<TData>;
|
checkIfSaveIsDisabled?: CheckIfSaveIsDisabledFnType<TData>;
|
||||||
|
mergeData?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Form<TData, Terrors>({
|
function Form<TData, Terrors>({
|
||||||
|
@ -25,6 +26,7 @@ function Form<TData, Terrors>({
|
||||||
formId,
|
formId,
|
||||||
checkIfSaveIsDisabled,
|
checkIfSaveIsDisabled,
|
||||||
disabled,
|
disabled,
|
||||||
|
mergeData,
|
||||||
...rest
|
...rest
|
||||||
}: FormProps<TData, Terrors>) {
|
}: FormProps<TData, Terrors>) {
|
||||||
const renderProps = useForm(initial, onSubmit, {
|
const renderProps = useForm(initial, onSubmit, {
|
||||||
|
@ -32,6 +34,7 @@ function Form<TData, Terrors>({
|
||||||
formId,
|
formId,
|
||||||
checkIfSaveIsDisabled,
|
checkIfSaveIsDisabled,
|
||||||
disabled,
|
disabled,
|
||||||
|
mergeData,
|
||||||
});
|
});
|
||||||
|
|
||||||
function handleSubmit(event?: React.FormEvent<any>, cb?: () => void) {
|
function handleSubmit(event?: React.FormEvent<any>, cb?: () => void) {
|
||||||
|
|
45
src/components/ListItemLink/ListItemLink.tsx
Normal file
45
src/components/ListItemLink/ListItemLink.tsx
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import { BaseListItemProps, ListItem, makeStyles } from "@saleor/macaw-ui";
|
||||||
|
import clsx from "classnames";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import Link from "../Link";
|
||||||
|
|
||||||
|
export interface ListItemLinkProps
|
||||||
|
extends Omit<BaseListItemProps, "onClick" | "classes"> {
|
||||||
|
href?: string;
|
||||||
|
className?: string;
|
||||||
|
linkClassName?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const useStyles = makeStyles(
|
||||||
|
{
|
||||||
|
link: {
|
||||||
|
all: "inherit",
|
||||||
|
display: "contents",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ name: "ListItemLink" },
|
||||||
|
);
|
||||||
|
|
||||||
|
export const ListItemLink: React.FC<ListItemLinkProps> = ({
|
||||||
|
href,
|
||||||
|
children,
|
||||||
|
linkClassName,
|
||||||
|
...props
|
||||||
|
}) => {
|
||||||
|
const classes = useStyles();
|
||||||
|
|
||||||
|
if (!href) {
|
||||||
|
return <ListItem {...props}>{children}</ListItem>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ListItem {...props}>
|
||||||
|
<Link className={clsx(classes.link, linkClassName)} href={href}>
|
||||||
|
{children}
|
||||||
|
</Link>
|
||||||
|
</ListItem>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ListItemLink;
|
2
src/components/ListItemLink/index.ts
Normal file
2
src/components/ListItemLink/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export { default } from "./ListItemLink";
|
||||||
|
export * from "./ListItemLink";
|
|
@ -16,7 +16,7 @@ import { productTypeListUrl } from "@saleor/productTypes/urls";
|
||||||
import { shippingZonesListUrl } from "@saleor/shipping/urls";
|
import { shippingZonesListUrl } from "@saleor/shipping/urls";
|
||||||
import { siteSettingsUrl } from "@saleor/siteSettings/urls";
|
import { siteSettingsUrl } from "@saleor/siteSettings/urls";
|
||||||
import { staffListUrl } from "@saleor/staff/urls";
|
import { staffListUrl } from "@saleor/staff/urls";
|
||||||
import { countryListUrl } from "@saleor/taxes/urls";
|
import { taxConfigurationListUrl } from "@saleor/taxes/urls";
|
||||||
import { languageListUrl } from "@saleor/translations/urls";
|
import { languageListUrl } from "@saleor/translations/urls";
|
||||||
import { warehouseListUrl } from "@saleor/warehouses/urls";
|
import { warehouseListUrl } from "@saleor/warehouses/urls";
|
||||||
import { score } from "fuzzaldrin";
|
import { score } from "fuzzaldrin";
|
||||||
|
@ -108,7 +108,7 @@ function searchInViews(
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: intl.formatMessage(sectionNames.taxes),
|
label: intl.formatMessage(sectionNames.taxes),
|
||||||
url: countryListUrl,
|
url: taxConfigurationListUrl(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: intl.formatMessage(sectionNames.translations),
|
label: intl.formatMessage(sectionNames.translations),
|
||||||
|
|
|
@ -16,7 +16,6 @@ export const shopInfo = gql`
|
||||||
...CountryWithCode
|
...CountryWithCode
|
||||||
}
|
}
|
||||||
defaultWeightUnit
|
defaultWeightUnit
|
||||||
displayGrossPrices
|
|
||||||
domain {
|
domain {
|
||||||
host
|
host
|
||||||
url
|
url
|
||||||
|
@ -24,7 +23,6 @@ export const shopInfo = gql`
|
||||||
languages {
|
languages {
|
||||||
...Language
|
...Language
|
||||||
}
|
}
|
||||||
includeTaxesInPrices
|
|
||||||
name
|
name
|
||||||
trackInventoryByDefault
|
trackInventoryByDefault
|
||||||
permissions {
|
permissions {
|
||||||
|
|
|
@ -167,7 +167,7 @@ const SingleAutocompleteSelectFieldContent: React.FC<SingleAutocompleteSelectFie
|
||||||
const scrolledToBottom = isScrolledToBottom(anchor, scrollPosition, offset);
|
const scrolledToBottom = isScrolledToBottom(anchor, scrollPosition, offset);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!calledForMore && onFetchMore && scrolledToBottom) {
|
if (!calledForMore && onFetchMore && scrolledToBottom && hasMore) {
|
||||||
onFetchMore();
|
onFetchMore();
|
||||||
setCalledForMore(true);
|
setCalledForMore(true);
|
||||||
} else if (scrolledToBottom && !onFetchMore) {
|
} else if (scrolledToBottom && !onFetchMore) {
|
||||||
|
|
|
@ -1,32 +1,18 @@
|
||||||
import { Typography } from "@material-ui/core";
|
import { Typography } from "@material-ui/core";
|
||||||
import { IconProps } from "@material-ui/core/Icon";
|
|
||||||
import { useTheme } from "@material-ui/core/styles";
|
import { useTheme } from "@material-ui/core/styles";
|
||||||
import useMediaQuery from "@material-ui/core/useMediaQuery";
|
import useMediaQuery from "@material-ui/core/useMediaQuery";
|
||||||
import { PermissionEnum, UserFragment } from "@saleor/graphql";
|
import { UserFragment } from "@saleor/graphql";
|
||||||
import { sectionNames } from "@saleor/intl";
|
import { sectionNames } from "@saleor/intl";
|
||||||
import { makeStyles, NavigationCard } from "@saleor/macaw-ui";
|
import { makeStyles, NavigationCard } from "@saleor/macaw-ui";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
import { hasAnyPermissions } from "../auth/misc";
|
|
||||||
import Container from "../components/Container";
|
import Container from "../components/Container";
|
||||||
import PageHeader from "../components/PageHeader";
|
import PageHeader from "../components/PageHeader";
|
||||||
import VersionInfo from "../components/VersionInfo";
|
import VersionInfo from "../components/VersionInfo";
|
||||||
|
import { MenuSection } from "./types";
|
||||||
export interface MenuItem {
|
import { hasUserMenuItemPermissions } from "./utils";
|
||||||
description: string;
|
|
||||||
icon: React.ReactElement<IconProps>;
|
|
||||||
permissions: PermissionEnum[];
|
|
||||||
title: string;
|
|
||||||
url?: string;
|
|
||||||
testId?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface MenuSection {
|
|
||||||
label: string;
|
|
||||||
menuItems: MenuItem[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface VersionInfo {
|
interface VersionInfo {
|
||||||
dashboardVersion: string;
|
dashboardVersion: string;
|
||||||
|
@ -115,7 +101,7 @@ export const ConfigurationPage: React.FC<ConfigurationPageProps> = props => {
|
||||||
{menus
|
{menus
|
||||||
.filter(menu =>
|
.filter(menu =>
|
||||||
menu.menuItems.some(menuItem =>
|
menu.menuItems.some(menuItem =>
|
||||||
hasAnyPermissions(menuItem.permissions, user),
|
hasUserMenuItemPermissions(menuItem, user),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.map((menu, menuIndex) => (
|
.map((menu, menuIndex) => (
|
||||||
|
@ -125,9 +111,7 @@ export const ConfigurationPage: React.FC<ConfigurationPageProps> = props => {
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.configurationItem}>
|
<div className={classes.configurationItem}>
|
||||||
{menu.menuItems
|
{menu.menuItems
|
||||||
.filter(menuItem =>
|
.filter(menuItem => hasUserMenuItemPermissions(menuItem, user))
|
||||||
hasAnyPermissions(menuItem.permissions, user),
|
|
||||||
)
|
|
||||||
.map((item, itemIndex) => (
|
.map((item, itemIndex) => (
|
||||||
<Link className={classes.link} to={item.url}>
|
<Link className={classes.link} to={item.url}>
|
||||||
<NavigationCard
|
<NavigationCard
|
||||||
|
|
|
@ -27,12 +27,13 @@ import { productTypeListUrl } from "@saleor/productTypes/urls";
|
||||||
import { shippingZonesListUrl } from "@saleor/shipping/urls";
|
import { shippingZonesListUrl } from "@saleor/shipping/urls";
|
||||||
import { siteSettingsUrl } from "@saleor/siteSettings/urls";
|
import { siteSettingsUrl } from "@saleor/siteSettings/urls";
|
||||||
import { staffListUrl } from "@saleor/staff/urls";
|
import { staffListUrl } from "@saleor/staff/urls";
|
||||||
import { taxSection } from "@saleor/taxes/urls";
|
import { taxConfigurationListUrl } from "@saleor/taxes/urls";
|
||||||
import { warehouseSection } from "@saleor/warehouses/urls";
|
import { warehouseSection } from "@saleor/warehouses/urls";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { IntlShape, useIntl } from "react-intl";
|
import { IntlShape, useIntl } from "react-intl";
|
||||||
|
|
||||||
import ConfigurationPage, { MenuSection } from "./ConfigurationPage";
|
import ConfigurationPage from "./ConfigurationPage";
|
||||||
|
import { MenuSection } from "./types";
|
||||||
|
|
||||||
export function createConfigurationMenu(intl: IntlShape): MenuSection[] {
|
export function createConfigurationMenu(intl: IntlShape): MenuSection[] {
|
||||||
return [
|
return [
|
||||||
|
@ -81,9 +82,8 @@ export function createConfigurationMenu(intl: IntlShape): MenuSection[] {
|
||||||
defaultMessage: "Manage how your store charges tax",
|
defaultMessage: "Manage how your store charges tax",
|
||||||
}),
|
}),
|
||||||
icon: <Taxes />,
|
icon: <Taxes />,
|
||||||
permissions: [PermissionEnum.MANAGE_SETTINGS],
|
|
||||||
title: intl.formatMessage(sectionNames.taxes),
|
title: intl.formatMessage(sectionNames.taxes),
|
||||||
url: taxSection,
|
url: taxConfigurationListUrl(),
|
||||||
testId: "configuration-menu-taxes",
|
testId: "configuration-menu-taxes",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
16
src/configuration/types.ts
Normal file
16
src/configuration/types.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { IconProps } from "@material-ui/core";
|
||||||
|
import { PermissionEnum } from "@saleor/graphql";
|
||||||
|
|
||||||
|
export interface MenuItem {
|
||||||
|
description: string;
|
||||||
|
icon: React.ReactElement<IconProps>;
|
||||||
|
permissions?: PermissionEnum[];
|
||||||
|
title: string;
|
||||||
|
url?: string;
|
||||||
|
testId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MenuSection {
|
||||||
|
label: string;
|
||||||
|
menuItems: MenuItem[];
|
||||||
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
import { PermissionEnum } from "@saleor/graphql";
|
import { hasAnyPermissions } from "@saleor/auth/misc";
|
||||||
|
import { PermissionEnum, UserFragment } from "@saleor/graphql";
|
||||||
import { IntlShape } from "react-intl";
|
import { IntlShape } from "react-intl";
|
||||||
|
|
||||||
import { createConfigurationMenu } from ".";
|
import { createConfigurationMenu } from ".";
|
||||||
|
import { MenuItem } from "./types";
|
||||||
|
|
||||||
export const getConfigMenuItemsPermissions = (
|
export const getConfigMenuItemsPermissions = (
|
||||||
intl: IntlShape,
|
intl: IntlShape,
|
||||||
|
@ -15,3 +17,9 @@ export const getConfigMenuItemsPermissions = (
|
||||||
[],
|
[],
|
||||||
)
|
)
|
||||||
.flat();
|
.flat();
|
||||||
|
|
||||||
|
export const hasUserMenuItemPermissions = (
|
||||||
|
menuItem: MenuItem,
|
||||||
|
user: UserFragment,
|
||||||
|
): boolean =>
|
||||||
|
menuItem.permissions ? hasAnyPermissions(menuItem.permissions, user) : true;
|
||||||
|
|
|
@ -487,3 +487,42 @@ export const shippingPriceTranslateErrorFragment = gql`
|
||||||
message
|
message
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const taxConfigurationUpdateError = gql`
|
||||||
|
fragment TaxConfigurationUpdateErrorFragment on TaxConfigurationUpdateError {
|
||||||
|
field
|
||||||
|
code
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const taxCountryConfigurationUpdateError = gql`
|
||||||
|
fragment TaxCountryConfigurationUpdateErrorFragment on TaxCountryConfigurationUpdateError {
|
||||||
|
field
|
||||||
|
code
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export const taxCountryConfigurationDeleteError = gql`
|
||||||
|
fragment TaxCountryConfigurationDeleteErrorFragment on TaxCountryConfigurationDeleteError {
|
||||||
|
field
|
||||||
|
code
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const taxClassUpdateError = gql`
|
||||||
|
fragment TaxClassUpdateErrorFragment on TaxClassUpdateError {
|
||||||
|
field
|
||||||
|
code
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export const taxClassCreateError = gql`
|
||||||
|
fragment TaxClassCreateErrorFragment on TaxClassCreateError {
|
||||||
|
field
|
||||||
|
code
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export const taxClassDeleteError = gql`
|
||||||
|
fragment TaxClassDeleteErrorFragment on TaxClassDeleteError {
|
||||||
|
field
|
||||||
|
code
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
|
@ -7,9 +7,9 @@ export const productTypeFragment = gql`
|
||||||
kind
|
kind
|
||||||
hasVariants
|
hasVariants
|
||||||
isShippingRequired
|
isShippingRequired
|
||||||
taxType {
|
taxClass {
|
||||||
description
|
id
|
||||||
taxCode
|
name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -226,7 +226,6 @@ export const productFragmentDetails = gql`
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
chargeTaxes
|
|
||||||
channelListings {
|
channelListings {
|
||||||
...ChannelListingProductWithoutPricing
|
...ChannelListingProductWithoutPricing
|
||||||
}
|
}
|
||||||
|
@ -241,15 +240,13 @@ export const productFragmentDetails = gql`
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
hasVariants
|
hasVariants
|
||||||
taxType {
|
|
||||||
...TaxType
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
weight {
|
weight {
|
||||||
...Weight
|
...Weight
|
||||||
}
|
}
|
||||||
taxType {
|
taxClass {
|
||||||
...TaxType
|
id
|
||||||
|
name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -28,6 +28,10 @@ export const shippingMethodTypeFragment = gql`
|
||||||
fragment ShippingMethodType on ShippingMethodType {
|
fragment ShippingMethodType on ShippingMethodType {
|
||||||
...ShippingMethodWithPostalCodes
|
...ShippingMethodWithPostalCodes
|
||||||
...Metadata
|
...Metadata
|
||||||
|
taxClass {
|
||||||
|
name
|
||||||
|
id
|
||||||
|
}
|
||||||
minimumOrderWeight {
|
minimumOrderWeight {
|
||||||
unit
|
unit
|
||||||
value
|
value
|
||||||
|
|
|
@ -16,28 +16,65 @@ export const countryFragment = gql`
|
||||||
code
|
code
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
export const countryWithTaxesFragment = gql`
|
|
||||||
fragment CountryWithTaxes on CountryDisplay {
|
export const taxConfigurationPerCountry = gql`
|
||||||
...Country
|
fragment TaxConfigurationPerCountry on TaxConfigurationPerCountry {
|
||||||
vat {
|
country {
|
||||||
standardRate
|
...CountryWithCode
|
||||||
reducedRates {
|
}
|
||||||
rateType
|
chargeTaxes
|
||||||
rate
|
taxCalculationStrategy
|
||||||
|
displayGrossPrices
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const taxConfiguration = gql`
|
||||||
|
fragment TaxConfiguration on TaxConfiguration {
|
||||||
|
id
|
||||||
|
channel {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
displayGrossPrices
|
||||||
|
pricesEnteredWithTax
|
||||||
|
chargeTaxes
|
||||||
|
taxCalculationStrategy
|
||||||
|
countries {
|
||||||
|
...TaxConfigurationPerCountry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const taxCountryConfigurationFragment = gql`
|
||||||
|
fragment TaxCountryConfiguration on TaxCountryConfiguration {
|
||||||
|
country {
|
||||||
|
...CountryWithCode
|
||||||
|
}
|
||||||
|
taxClassCountryRates {
|
||||||
|
rate
|
||||||
|
taxClass {
|
||||||
|
id
|
||||||
|
name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
export const shopTaxesFragment = gql`
|
|
||||||
fragment ShopTaxes on Shop {
|
export const taxRateFragment = gql`
|
||||||
chargeTaxesOnShipping
|
fragment TaxRate on TaxClassCountryRate {
|
||||||
includeTaxesInPrices
|
country {
|
||||||
displayGrossPrices
|
...CountryWithCode
|
||||||
|
}
|
||||||
|
rate
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
export const taxTypeFragment = gql`
|
|
||||||
fragment TaxType on TaxType {
|
export const taxClassFragment = gql`
|
||||||
description
|
fragment TaxClass on TaxClass {
|
||||||
taxCode
|
id
|
||||||
|
name
|
||||||
|
countries {
|
||||||
|
...TaxRate
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -210,6 +210,8 @@
|
||||||
"ShopTranslation",
|
"ShopTranslation",
|
||||||
"StaffNotificationRecipient",
|
"StaffNotificationRecipient",
|
||||||
"Stock",
|
"Stock",
|
||||||
|
"TaxClass",
|
||||||
|
"TaxConfiguration",
|
||||||
"Transaction",
|
"Transaction",
|
||||||
"TransactionEvent",
|
"TransactionEvent",
|
||||||
"TransactionItem",
|
"TransactionItem",
|
||||||
|
@ -246,6 +248,8 @@
|
||||||
"ShippingMethod",
|
"ShippingMethod",
|
||||||
"ShippingMethodType",
|
"ShippingMethodType",
|
||||||
"ShippingZone",
|
"ShippingZone",
|
||||||
|
"TaxClass",
|
||||||
|
"TaxConfiguration",
|
||||||
"TransactionItem",
|
"TransactionItem",
|
||||||
"User",
|
"User",
|
||||||
"Voucher",
|
"Voucher",
|
||||||
|
|
|
@ -972,6 +972,42 @@ export const ShippingPriceTranslateErrorFragmentFragmentDoc = gql`
|
||||||
message
|
message
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
export const TaxConfigurationUpdateErrorFragmentFragmentDoc = gql`
|
||||||
|
fragment TaxConfigurationUpdateErrorFragment on TaxConfigurationUpdateError {
|
||||||
|
field
|
||||||
|
code
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export const TaxCountryConfigurationUpdateErrorFragmentFragmentDoc = gql`
|
||||||
|
fragment TaxCountryConfigurationUpdateErrorFragment on TaxCountryConfigurationUpdateError {
|
||||||
|
field
|
||||||
|
code
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export const TaxCountryConfigurationDeleteErrorFragmentFragmentDoc = gql`
|
||||||
|
fragment TaxCountryConfigurationDeleteErrorFragment on TaxCountryConfigurationDeleteError {
|
||||||
|
field
|
||||||
|
code
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export const TaxClassUpdateErrorFragmentFragmentDoc = gql`
|
||||||
|
fragment TaxClassUpdateErrorFragment on TaxClassUpdateError {
|
||||||
|
field
|
||||||
|
code
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export const TaxClassCreateErrorFragmentFragmentDoc = gql`
|
||||||
|
fragment TaxClassCreateErrorFragment on TaxClassCreateError {
|
||||||
|
field
|
||||||
|
code
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export const TaxClassDeleteErrorFragmentFragmentDoc = gql`
|
||||||
|
fragment TaxClassDeleteErrorFragment on TaxClassDeleteError {
|
||||||
|
field
|
||||||
|
code
|
||||||
|
}
|
||||||
|
`;
|
||||||
export const GiftCardsSettingsFragmentDoc = gql`
|
export const GiftCardsSettingsFragmentDoc = gql`
|
||||||
fragment GiftCardsSettings on GiftCardSettings {
|
fragment GiftCardsSettings on GiftCardSettings {
|
||||||
expiryType
|
expiryType
|
||||||
|
@ -1796,9 +1832,9 @@ export const ProductTypeFragmentDoc = gql`
|
||||||
kind
|
kind
|
||||||
hasVariants
|
hasVariants
|
||||||
isShippingRequired
|
isShippingRequired
|
||||||
taxType {
|
taxClass {
|
||||||
description
|
id
|
||||||
taxCode
|
name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
@ -1996,12 +2032,6 @@ export const ProductDetailsVariantFragmentDoc = gql`
|
||||||
${StockFragmentDoc}
|
${StockFragmentDoc}
|
||||||
${PreorderFragmentDoc}
|
${PreorderFragmentDoc}
|
||||||
${ChannelListingProductVariantFragmentDoc}`;
|
${ChannelListingProductVariantFragmentDoc}`;
|
||||||
export const TaxTypeFragmentDoc = gql`
|
|
||||||
fragment TaxType on TaxType {
|
|
||||||
description
|
|
||||||
taxCode
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
export const WeightFragmentDoc = gql`
|
export const WeightFragmentDoc = gql`
|
||||||
fragment Weight on Weight {
|
fragment Weight on Weight {
|
||||||
unit
|
unit
|
||||||
|
@ -2029,7 +2059,6 @@ export const ProductFragmentDoc = gql`
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
chargeTaxes
|
|
||||||
channelListings {
|
channelListings {
|
||||||
...ChannelListingProductWithoutPricing
|
...ChannelListingProductWithoutPricing
|
||||||
}
|
}
|
||||||
|
@ -2044,15 +2073,13 @@ export const ProductFragmentDoc = gql`
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
hasVariants
|
hasVariants
|
||||||
taxType {
|
|
||||||
...TaxType
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
weight {
|
weight {
|
||||||
...Weight
|
...Weight
|
||||||
}
|
}
|
||||||
taxType {
|
taxClass {
|
||||||
...TaxType
|
id
|
||||||
|
name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
${ProductVariantAttributesFragmentDoc}
|
${ProductVariantAttributesFragmentDoc}
|
||||||
|
@ -2060,7 +2087,6 @@ ${MetadataFragmentDoc}
|
||||||
${ChannelListingProductWithoutPricingFragmentDoc}
|
${ChannelListingProductWithoutPricingFragmentDoc}
|
||||||
${ProductMediaFragmentDoc}
|
${ProductMediaFragmentDoc}
|
||||||
${ProductDetailsVariantFragmentDoc}
|
${ProductDetailsVariantFragmentDoc}
|
||||||
${TaxTypeFragmentDoc}
|
|
||||||
${WeightFragmentDoc}`;
|
${WeightFragmentDoc}`;
|
||||||
export const VariantAttributeFragmentDoc = gql`
|
export const VariantAttributeFragmentDoc = gql`
|
||||||
fragment VariantAttribute on Attribute {
|
fragment VariantAttribute on Attribute {
|
||||||
|
@ -2201,6 +2227,10 @@ export const ShippingMethodTypeFragmentDoc = gql`
|
||||||
fragment ShippingMethodType on ShippingMethodType {
|
fragment ShippingMethodType on ShippingMethodType {
|
||||||
...ShippingMethodWithPostalCodes
|
...ShippingMethodWithPostalCodes
|
||||||
...Metadata
|
...Metadata
|
||||||
|
taxClass {
|
||||||
|
name
|
||||||
|
id
|
||||||
|
}
|
||||||
minimumOrderWeight {
|
minimumOrderWeight {
|
||||||
unit
|
unit
|
||||||
value
|
value
|
||||||
|
@ -2282,12 +2312,6 @@ export const ShippingZoneDetailsFragmentDoc = gql`
|
||||||
}
|
}
|
||||||
${ShippingZoneFragmentDoc}
|
${ShippingZoneFragmentDoc}
|
||||||
${ShippingMethodTypeFragmentDoc}`;
|
${ShippingMethodTypeFragmentDoc}`;
|
||||||
export const CountryWithCodeFragmentDoc = gql`
|
|
||||||
fragment CountryWithCode on CountryDisplay {
|
|
||||||
country
|
|
||||||
code
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
export const LanguageFragmentDoc = gql`
|
export const LanguageFragmentDoc = gql`
|
||||||
fragment Language on LanguageDisplay {
|
fragment Language on LanguageDisplay {
|
||||||
code
|
code
|
||||||
|
@ -2370,25 +2394,69 @@ export const CountryFragmentDoc = gql`
|
||||||
code
|
code
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
export const CountryWithTaxesFragmentDoc = gql`
|
export const CountryWithCodeFragmentDoc = gql`
|
||||||
fragment CountryWithTaxes on CountryDisplay {
|
fragment CountryWithCode on CountryDisplay {
|
||||||
...Country
|
country
|
||||||
vat {
|
code
|
||||||
standardRate
|
}
|
||||||
reducedRates {
|
`;
|
||||||
rateType
|
export const TaxConfigurationPerCountryFragmentDoc = gql`
|
||||||
rate
|
fragment TaxConfigurationPerCountry on TaxConfigurationPerCountry {
|
||||||
|
country {
|
||||||
|
...CountryWithCode
|
||||||
|
}
|
||||||
|
chargeTaxes
|
||||||
|
taxCalculationStrategy
|
||||||
|
displayGrossPrices
|
||||||
|
}
|
||||||
|
${CountryWithCodeFragmentDoc}`;
|
||||||
|
export const TaxConfigurationFragmentDoc = gql`
|
||||||
|
fragment TaxConfiguration on TaxConfiguration {
|
||||||
|
id
|
||||||
|
channel {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
displayGrossPrices
|
||||||
|
pricesEnteredWithTax
|
||||||
|
chargeTaxes
|
||||||
|
taxCalculationStrategy
|
||||||
|
countries {
|
||||||
|
...TaxConfigurationPerCountry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
${TaxConfigurationPerCountryFragmentDoc}`;
|
||||||
|
export const TaxCountryConfigurationFragmentDoc = gql`
|
||||||
|
fragment TaxCountryConfiguration on TaxCountryConfiguration {
|
||||||
|
country {
|
||||||
|
...CountryWithCode
|
||||||
|
}
|
||||||
|
taxClassCountryRates {
|
||||||
|
rate
|
||||||
|
taxClass {
|
||||||
|
id
|
||||||
|
name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
${CountryFragmentDoc}`;
|
${CountryWithCodeFragmentDoc}`;
|
||||||
export const ShopTaxesFragmentDoc = gql`
|
export const TaxRateFragmentDoc = gql`
|
||||||
fragment ShopTaxes on Shop {
|
fragment TaxRate on TaxClassCountryRate {
|
||||||
chargeTaxesOnShipping
|
country {
|
||||||
includeTaxesInPrices
|
...CountryWithCode
|
||||||
displayGrossPrices
|
}
|
||||||
|
rate
|
||||||
}
|
}
|
||||||
`;
|
${CountryWithCodeFragmentDoc}`;
|
||||||
|
export const TaxClassFragmentDoc = gql`
|
||||||
|
fragment TaxClass on TaxClass {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
countries {
|
||||||
|
...TaxRate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
${TaxRateFragmentDoc}`;
|
||||||
export const TimePeriodFragmentDoc = gql`
|
export const TimePeriodFragmentDoc = gql`
|
||||||
fragment TimePeriod on TimePeriod {
|
fragment TimePeriod on TimePeriod {
|
||||||
amount
|
amount
|
||||||
|
@ -5091,7 +5159,6 @@ export const ShopInfoDocument = gql`
|
||||||
...CountryWithCode
|
...CountryWithCode
|
||||||
}
|
}
|
||||||
defaultWeightUnit
|
defaultWeightUnit
|
||||||
displayGrossPrices
|
|
||||||
domain {
|
domain {
|
||||||
host
|
host
|
||||||
url
|
url
|
||||||
|
@ -5099,7 +5166,6 @@ export const ShopInfoDocument = gql`
|
||||||
languages {
|
languages {
|
||||||
...Language
|
...Language
|
||||||
}
|
}
|
||||||
includeTaxesInPrices
|
|
||||||
name
|
name
|
||||||
trackInventoryByDefault
|
trackInventoryByDefault
|
||||||
permissions {
|
permissions {
|
||||||
|
@ -11032,10 +11098,6 @@ export const ProductTypeDetailsDocument = gql`
|
||||||
shop {
|
shop {
|
||||||
defaultWeightUnit
|
defaultWeightUnit
|
||||||
}
|
}
|
||||||
taxTypes {
|
|
||||||
taxCode
|
|
||||||
description
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
${ProductTypeDetailsFragmentDoc}`;
|
${ProductTypeDetailsFragmentDoc}`;
|
||||||
|
|
||||||
|
@ -11071,10 +11133,6 @@ export const ProductTypeCreateDataDocument = gql`
|
||||||
shop {
|
shop {
|
||||||
defaultWeightUnit
|
defaultWeightUnit
|
||||||
}
|
}
|
||||||
taxTypes {
|
|
||||||
taxCode
|
|
||||||
description
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -12425,12 +12483,8 @@ export const ProductDetailsDocument = gql`
|
||||||
product(id: $id, channel: $channel) {
|
product(id: $id, channel: $channel) {
|
||||||
...Product
|
...Product
|
||||||
}
|
}
|
||||||
taxTypes {
|
|
||||||
...TaxType
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
${ProductFragmentDoc}
|
${ProductFragmentDoc}`;
|
||||||
${TaxTypeFragmentDoc}`;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __useProductDetailsQuery__
|
* __useProductDetailsQuery__
|
||||||
|
@ -12487,13 +12541,13 @@ export const ProductTypeDocument = gql`
|
||||||
...AttributeValueList
|
...AttributeValueList
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
taxType {
|
taxClass {
|
||||||
...TaxType
|
id
|
||||||
|
name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
${AttributeValueListFragmentDoc}
|
${AttributeValueListFragmentDoc}`;
|
||||||
${TaxTypeFragmentDoc}`;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __useProductTypeQuery__
|
* __useProductTypeQuery__
|
||||||
|
@ -14745,157 +14799,421 @@ export function useStaffMemberDetailsLazyQuery(baseOptions?: ApolloReactHooks.La
|
||||||
export type StaffMemberDetailsQueryHookResult = ReturnType<typeof useStaffMemberDetailsQuery>;
|
export type StaffMemberDetailsQueryHookResult = ReturnType<typeof useStaffMemberDetailsQuery>;
|
||||||
export type StaffMemberDetailsLazyQueryHookResult = ReturnType<typeof useStaffMemberDetailsLazyQuery>;
|
export type StaffMemberDetailsLazyQueryHookResult = ReturnType<typeof useStaffMemberDetailsLazyQuery>;
|
||||||
export type StaffMemberDetailsQueryResult = Apollo.QueryResult<Types.StaffMemberDetailsQuery, Types.StaffMemberDetailsQueryVariables>;
|
export type StaffMemberDetailsQueryResult = Apollo.QueryResult<Types.StaffMemberDetailsQuery, Types.StaffMemberDetailsQueryVariables>;
|
||||||
export const UpdateTaxSettingsDocument = gql`
|
export const TaxConfigurationUpdateDocument = gql`
|
||||||
mutation UpdateTaxSettings($input: ShopSettingsInput!) {
|
mutation TaxConfigurationUpdate($id: ID!, $input: TaxConfigurationUpdateInput!) {
|
||||||
shopSettingsUpdate(input: $input) {
|
taxConfigurationUpdate(id: $id, input: $input) {
|
||||||
errors {
|
errors {
|
||||||
...ShopSettingsUpdateErrorFragment
|
...TaxConfigurationUpdateErrorFragment
|
||||||
}
|
}
|
||||||
shop {
|
taxConfiguration {
|
||||||
...ShopTaxes
|
...TaxConfiguration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
${ShopSettingsUpdateErrorFragmentFragmentDoc}
|
${TaxConfigurationUpdateErrorFragmentFragmentDoc}
|
||||||
${ShopTaxesFragmentDoc}`;
|
${TaxConfigurationFragmentDoc}`;
|
||||||
export type UpdateTaxSettingsMutationFn = Apollo.MutationFunction<Types.UpdateTaxSettingsMutation, Types.UpdateTaxSettingsMutationVariables>;
|
export type TaxConfigurationUpdateMutationFn = Apollo.MutationFunction<Types.TaxConfigurationUpdateMutation, Types.TaxConfigurationUpdateMutationVariables>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __useUpdateTaxSettingsMutation__
|
* __useTaxConfigurationUpdateMutation__
|
||||||
*
|
*
|
||||||
* To run a mutation, you first call `useUpdateTaxSettingsMutation` within a React component and pass it any options that fit your needs.
|
* To run a mutation, you first call `useTaxConfigurationUpdateMutation` within a React component and pass it any options that fit your needs.
|
||||||
* When your component renders, `useUpdateTaxSettingsMutation` returns a tuple that includes:
|
* When your component renders, `useTaxConfigurationUpdateMutation` returns a tuple that includes:
|
||||||
* - A mutate function that you can call at any time to execute the mutation
|
* - A mutate function that you can call at any time to execute the mutation
|
||||||
* - An object with fields that represent the current status of the mutation's execution
|
* - An object with fields that represent the current status of the mutation's execution
|
||||||
*
|
*
|
||||||
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* const [updateTaxSettingsMutation, { data, loading, error }] = useUpdateTaxSettingsMutation({
|
* const [taxConfigurationUpdateMutation, { data, loading, error }] = useTaxConfigurationUpdateMutation({
|
||||||
|
* variables: {
|
||||||
|
* id: // value for 'id'
|
||||||
|
* input: // value for 'input'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useTaxConfigurationUpdateMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<Types.TaxConfigurationUpdateMutation, Types.TaxConfigurationUpdateMutationVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return ApolloReactHooks.useMutation<Types.TaxConfigurationUpdateMutation, Types.TaxConfigurationUpdateMutationVariables>(TaxConfigurationUpdateDocument, options);
|
||||||
|
}
|
||||||
|
export type TaxConfigurationUpdateMutationHookResult = ReturnType<typeof useTaxConfigurationUpdateMutation>;
|
||||||
|
export type TaxConfigurationUpdateMutationResult = Apollo.MutationResult<Types.TaxConfigurationUpdateMutation>;
|
||||||
|
export type TaxConfigurationUpdateMutationOptions = Apollo.BaseMutationOptions<Types.TaxConfigurationUpdateMutation, Types.TaxConfigurationUpdateMutationVariables>;
|
||||||
|
export const TaxCountryConfigurationUpdateDocument = gql`
|
||||||
|
mutation TaxCountryConfigurationUpdate($countryCode: CountryCode!, $updateTaxClassRates: [TaxClassRateInput!]!) {
|
||||||
|
taxCountryConfigurationUpdate(
|
||||||
|
countryCode: $countryCode
|
||||||
|
updateTaxClassRates: $updateTaxClassRates
|
||||||
|
) {
|
||||||
|
errors {
|
||||||
|
...TaxCountryConfigurationUpdateErrorFragment
|
||||||
|
}
|
||||||
|
taxCountryConfiguration {
|
||||||
|
...TaxCountryConfiguration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
${TaxCountryConfigurationUpdateErrorFragmentFragmentDoc}
|
||||||
|
${TaxCountryConfigurationFragmentDoc}`;
|
||||||
|
export type TaxCountryConfigurationUpdateMutationFn = Apollo.MutationFunction<Types.TaxCountryConfigurationUpdateMutation, Types.TaxCountryConfigurationUpdateMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useTaxCountryConfigurationUpdateMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useTaxCountryConfigurationUpdateMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useTaxCountryConfigurationUpdateMutation` returns a tuple that includes:
|
||||||
|
* - A mutate function that you can call at any time to execute the mutation
|
||||||
|
* - An object with fields that represent the current status of the mutation's execution
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const [taxCountryConfigurationUpdateMutation, { data, loading, error }] = useTaxCountryConfigurationUpdateMutation({
|
||||||
|
* variables: {
|
||||||
|
* countryCode: // value for 'countryCode'
|
||||||
|
* updateTaxClassRates: // value for 'updateTaxClassRates'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useTaxCountryConfigurationUpdateMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<Types.TaxCountryConfigurationUpdateMutation, Types.TaxCountryConfigurationUpdateMutationVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return ApolloReactHooks.useMutation<Types.TaxCountryConfigurationUpdateMutation, Types.TaxCountryConfigurationUpdateMutationVariables>(TaxCountryConfigurationUpdateDocument, options);
|
||||||
|
}
|
||||||
|
export type TaxCountryConfigurationUpdateMutationHookResult = ReturnType<typeof useTaxCountryConfigurationUpdateMutation>;
|
||||||
|
export type TaxCountryConfigurationUpdateMutationResult = Apollo.MutationResult<Types.TaxCountryConfigurationUpdateMutation>;
|
||||||
|
export type TaxCountryConfigurationUpdateMutationOptions = Apollo.BaseMutationOptions<Types.TaxCountryConfigurationUpdateMutation, Types.TaxCountryConfigurationUpdateMutationVariables>;
|
||||||
|
export const TaxCountryConfigurationDeleteDocument = gql`
|
||||||
|
mutation TaxCountryConfigurationDelete($countryCode: CountryCode!) {
|
||||||
|
taxCountryConfigurationDelete(countryCode: $countryCode) {
|
||||||
|
errors {
|
||||||
|
...TaxCountryConfigurationDeleteErrorFragment
|
||||||
|
}
|
||||||
|
taxCountryConfiguration {
|
||||||
|
...TaxCountryConfiguration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
${TaxCountryConfigurationDeleteErrorFragmentFragmentDoc}
|
||||||
|
${TaxCountryConfigurationFragmentDoc}`;
|
||||||
|
export type TaxCountryConfigurationDeleteMutationFn = Apollo.MutationFunction<Types.TaxCountryConfigurationDeleteMutation, Types.TaxCountryConfigurationDeleteMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useTaxCountryConfigurationDeleteMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useTaxCountryConfigurationDeleteMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useTaxCountryConfigurationDeleteMutation` returns a tuple that includes:
|
||||||
|
* - A mutate function that you can call at any time to execute the mutation
|
||||||
|
* - An object with fields that represent the current status of the mutation's execution
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const [taxCountryConfigurationDeleteMutation, { data, loading, error }] = useTaxCountryConfigurationDeleteMutation({
|
||||||
|
* variables: {
|
||||||
|
* countryCode: // value for 'countryCode'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useTaxCountryConfigurationDeleteMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<Types.TaxCountryConfigurationDeleteMutation, Types.TaxCountryConfigurationDeleteMutationVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return ApolloReactHooks.useMutation<Types.TaxCountryConfigurationDeleteMutation, Types.TaxCountryConfigurationDeleteMutationVariables>(TaxCountryConfigurationDeleteDocument, options);
|
||||||
|
}
|
||||||
|
export type TaxCountryConfigurationDeleteMutationHookResult = ReturnType<typeof useTaxCountryConfigurationDeleteMutation>;
|
||||||
|
export type TaxCountryConfigurationDeleteMutationResult = Apollo.MutationResult<Types.TaxCountryConfigurationDeleteMutation>;
|
||||||
|
export type TaxCountryConfigurationDeleteMutationOptions = Apollo.BaseMutationOptions<Types.TaxCountryConfigurationDeleteMutation, Types.TaxCountryConfigurationDeleteMutationVariables>;
|
||||||
|
export const TaxClassUpdateDocument = gql`
|
||||||
|
mutation TaxClassUpdate($id: ID!, $input: TaxClassUpdateInput!) {
|
||||||
|
taxClassUpdate(id: $id, input: $input) {
|
||||||
|
errors {
|
||||||
|
...TaxClassUpdateErrorFragment
|
||||||
|
}
|
||||||
|
taxClass {
|
||||||
|
...TaxClass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
${TaxClassUpdateErrorFragmentFragmentDoc}
|
||||||
|
${TaxClassFragmentDoc}`;
|
||||||
|
export type TaxClassUpdateMutationFn = Apollo.MutationFunction<Types.TaxClassUpdateMutation, Types.TaxClassUpdateMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useTaxClassUpdateMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useTaxClassUpdateMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useTaxClassUpdateMutation` returns a tuple that includes:
|
||||||
|
* - A mutate function that you can call at any time to execute the mutation
|
||||||
|
* - An object with fields that represent the current status of the mutation's execution
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const [taxClassUpdateMutation, { data, loading, error }] = useTaxClassUpdateMutation({
|
||||||
|
* variables: {
|
||||||
|
* id: // value for 'id'
|
||||||
|
* input: // value for 'input'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useTaxClassUpdateMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<Types.TaxClassUpdateMutation, Types.TaxClassUpdateMutationVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return ApolloReactHooks.useMutation<Types.TaxClassUpdateMutation, Types.TaxClassUpdateMutationVariables>(TaxClassUpdateDocument, options);
|
||||||
|
}
|
||||||
|
export type TaxClassUpdateMutationHookResult = ReturnType<typeof useTaxClassUpdateMutation>;
|
||||||
|
export type TaxClassUpdateMutationResult = Apollo.MutationResult<Types.TaxClassUpdateMutation>;
|
||||||
|
export type TaxClassUpdateMutationOptions = Apollo.BaseMutationOptions<Types.TaxClassUpdateMutation, Types.TaxClassUpdateMutationVariables>;
|
||||||
|
export const TaxClassCreateDocument = gql`
|
||||||
|
mutation TaxClassCreate($input: TaxClassCreateInput!) {
|
||||||
|
taxClassCreate(input: $input) {
|
||||||
|
errors {
|
||||||
|
...TaxClassCreateErrorFragment
|
||||||
|
}
|
||||||
|
taxClass {
|
||||||
|
...TaxClass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
${TaxClassCreateErrorFragmentFragmentDoc}
|
||||||
|
${TaxClassFragmentDoc}`;
|
||||||
|
export type TaxClassCreateMutationFn = Apollo.MutationFunction<Types.TaxClassCreateMutation, Types.TaxClassCreateMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useTaxClassCreateMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useTaxClassCreateMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useTaxClassCreateMutation` returns a tuple that includes:
|
||||||
|
* - A mutate function that you can call at any time to execute the mutation
|
||||||
|
* - An object with fields that represent the current status of the mutation's execution
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const [taxClassCreateMutation, { data, loading, error }] = useTaxClassCreateMutation({
|
||||||
* variables: {
|
* variables: {
|
||||||
* input: // value for 'input'
|
* input: // value for 'input'
|
||||||
* },
|
* },
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
export function useUpdateTaxSettingsMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<Types.UpdateTaxSettingsMutation, Types.UpdateTaxSettingsMutationVariables>) {
|
export function useTaxClassCreateMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<Types.TaxClassCreateMutation, Types.TaxClassCreateMutationVariables>) {
|
||||||
const options = {...defaultOptions, ...baseOptions}
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
return ApolloReactHooks.useMutation<Types.UpdateTaxSettingsMutation, Types.UpdateTaxSettingsMutationVariables>(UpdateTaxSettingsDocument, options);
|
return ApolloReactHooks.useMutation<Types.TaxClassCreateMutation, Types.TaxClassCreateMutationVariables>(TaxClassCreateDocument, options);
|
||||||
}
|
}
|
||||||
export type UpdateTaxSettingsMutationHookResult = ReturnType<typeof useUpdateTaxSettingsMutation>;
|
export type TaxClassCreateMutationHookResult = ReturnType<typeof useTaxClassCreateMutation>;
|
||||||
export type UpdateTaxSettingsMutationResult = Apollo.MutationResult<Types.UpdateTaxSettingsMutation>;
|
export type TaxClassCreateMutationResult = Apollo.MutationResult<Types.TaxClassCreateMutation>;
|
||||||
export type UpdateTaxSettingsMutationOptions = Apollo.BaseMutationOptions<Types.UpdateTaxSettingsMutation, Types.UpdateTaxSettingsMutationVariables>;
|
export type TaxClassCreateMutationOptions = Apollo.BaseMutationOptions<Types.TaxClassCreateMutation, Types.TaxClassCreateMutationVariables>;
|
||||||
export const FetchTaxesDocument = gql`
|
export const TaxClassDeleteDocument = gql`
|
||||||
mutation FetchTaxes {
|
mutation TaxClassDelete($id: ID!) {
|
||||||
shopFetchTaxRates {
|
taxClassDelete(id: $id) {
|
||||||
errors {
|
errors {
|
||||||
...ShopFetchTaxRatesErrorFragment
|
...TaxClassDeleteErrorFragment
|
||||||
}
|
|
||||||
shop {
|
|
||||||
countries {
|
|
||||||
...Country
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
${ShopFetchTaxRatesErrorFragmentFragmentDoc}
|
${TaxClassDeleteErrorFragmentFragmentDoc}`;
|
||||||
${CountryFragmentDoc}`;
|
export type TaxClassDeleteMutationFn = Apollo.MutationFunction<Types.TaxClassDeleteMutation, Types.TaxClassDeleteMutationVariables>;
|
||||||
export type FetchTaxesMutationFn = Apollo.MutationFunction<Types.FetchTaxesMutation, Types.FetchTaxesMutationVariables>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __useFetchTaxesMutation__
|
* __useTaxClassDeleteMutation__
|
||||||
*
|
*
|
||||||
* To run a mutation, you first call `useFetchTaxesMutation` within a React component and pass it any options that fit your needs.
|
* To run a mutation, you first call `useTaxClassDeleteMutation` within a React component and pass it any options that fit your needs.
|
||||||
* When your component renders, `useFetchTaxesMutation` returns a tuple that includes:
|
* When your component renders, `useTaxClassDeleteMutation` returns a tuple that includes:
|
||||||
* - A mutate function that you can call at any time to execute the mutation
|
* - A mutate function that you can call at any time to execute the mutation
|
||||||
* - An object with fields that represent the current status of the mutation's execution
|
* - An object with fields that represent the current status of the mutation's execution
|
||||||
*
|
*
|
||||||
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* const [fetchTaxesMutation, { data, loading, error }] = useFetchTaxesMutation({
|
* const [taxClassDeleteMutation, { data, loading, error }] = useTaxClassDeleteMutation({
|
||||||
* variables: {
|
* variables: {
|
||||||
|
* id: // value for 'id'
|
||||||
* },
|
* },
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
export function useFetchTaxesMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<Types.FetchTaxesMutation, Types.FetchTaxesMutationVariables>) {
|
export function useTaxClassDeleteMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<Types.TaxClassDeleteMutation, Types.TaxClassDeleteMutationVariables>) {
|
||||||
const options = {...defaultOptions, ...baseOptions}
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
return ApolloReactHooks.useMutation<Types.FetchTaxesMutation, Types.FetchTaxesMutationVariables>(FetchTaxesDocument, options);
|
return ApolloReactHooks.useMutation<Types.TaxClassDeleteMutation, Types.TaxClassDeleteMutationVariables>(TaxClassDeleteDocument, options);
|
||||||
|
}
|
||||||
|
export type TaxClassDeleteMutationHookResult = ReturnType<typeof useTaxClassDeleteMutation>;
|
||||||
|
export type TaxClassDeleteMutationResult = Apollo.MutationResult<Types.TaxClassDeleteMutation>;
|
||||||
|
export type TaxClassDeleteMutationOptions = Apollo.BaseMutationOptions<Types.TaxClassDeleteMutation, Types.TaxClassDeleteMutationVariables>;
|
||||||
|
export const TaxConfigurationsListDocument = gql`
|
||||||
|
query TaxConfigurationsList($before: String, $after: String, $first: Int, $last: Int, $filter: TaxConfigurationFilterInput) {
|
||||||
|
taxConfigurations(
|
||||||
|
before: $before
|
||||||
|
after: $after
|
||||||
|
first: $first
|
||||||
|
last: $last
|
||||||
|
filter: $filter
|
||||||
|
) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
...TaxConfiguration
|
||||||
}
|
}
|
||||||
export type FetchTaxesMutationHookResult = ReturnType<typeof useFetchTaxesMutation>;
|
|
||||||
export type FetchTaxesMutationResult = Apollo.MutationResult<Types.FetchTaxesMutation>;
|
|
||||||
export type FetchTaxesMutationOptions = Apollo.BaseMutationOptions<Types.FetchTaxesMutation, Types.FetchTaxesMutationVariables>;
|
|
||||||
export const CountryListDocument = gql`
|
|
||||||
query CountryList {
|
|
||||||
shop {
|
|
||||||
...ShopTaxes
|
|
||||||
countries {
|
|
||||||
...CountryWithTaxes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
${ShopTaxesFragmentDoc}
|
${TaxConfigurationFragmentDoc}`;
|
||||||
${CountryWithTaxesFragmentDoc}`;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __useCountryListQuery__
|
* __useTaxConfigurationsListQuery__
|
||||||
*
|
*
|
||||||
* To run a query within a React component, call `useCountryListQuery` and pass it any options that fit your needs.
|
* To run a query within a React component, call `useTaxConfigurationsListQuery` and pass it any options that fit your needs.
|
||||||
* When your component renders, `useCountryListQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
* When your component renders, `useTaxConfigurationsListQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||||
* you can use to render your UI.
|
* you can use to render your UI.
|
||||||
*
|
*
|
||||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* const { data, loading, error } = useCountryListQuery({
|
* const { data, loading, error } = useTaxConfigurationsListQuery({
|
||||||
* variables: {
|
* variables: {
|
||||||
|
* before: // value for 'before'
|
||||||
|
* after: // value for 'after'
|
||||||
|
* first: // value for 'first'
|
||||||
|
* last: // value for 'last'
|
||||||
|
* filter: // value for 'filter'
|
||||||
* },
|
* },
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
export function useCountryListQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<Types.CountryListQuery, Types.CountryListQueryVariables>) {
|
export function useTaxConfigurationsListQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<Types.TaxConfigurationsListQuery, Types.TaxConfigurationsListQueryVariables>) {
|
||||||
const options = {...defaultOptions, ...baseOptions}
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
return ApolloReactHooks.useQuery<Types.CountryListQuery, Types.CountryListQueryVariables>(CountryListDocument, options);
|
return ApolloReactHooks.useQuery<Types.TaxConfigurationsListQuery, Types.TaxConfigurationsListQueryVariables>(TaxConfigurationsListDocument, options);
|
||||||
}
|
}
|
||||||
export function useCountryListLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types.CountryListQuery, Types.CountryListQueryVariables>) {
|
export function useTaxConfigurationsListLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types.TaxConfigurationsListQuery, Types.TaxConfigurationsListQueryVariables>) {
|
||||||
const options = {...defaultOptions, ...baseOptions}
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
return ApolloReactHooks.useLazyQuery<Types.CountryListQuery, Types.CountryListQueryVariables>(CountryListDocument, options);
|
return ApolloReactHooks.useLazyQuery<Types.TaxConfigurationsListQuery, Types.TaxConfigurationsListQueryVariables>(TaxConfigurationsListDocument, options);
|
||||||
}
|
}
|
||||||
export type CountryListQueryHookResult = ReturnType<typeof useCountryListQuery>;
|
export type TaxConfigurationsListQueryHookResult = ReturnType<typeof useTaxConfigurationsListQuery>;
|
||||||
export type CountryListLazyQueryHookResult = ReturnType<typeof useCountryListLazyQuery>;
|
export type TaxConfigurationsListLazyQueryHookResult = ReturnType<typeof useTaxConfigurationsListLazyQuery>;
|
||||||
export type CountryListQueryResult = Apollo.QueryResult<Types.CountryListQuery, Types.CountryListQueryVariables>;
|
export type TaxConfigurationsListQueryResult = Apollo.QueryResult<Types.TaxConfigurationsListQuery, Types.TaxConfigurationsListQueryVariables>;
|
||||||
export const TaxTypeListDocument = gql`
|
export const TaxCountriesListDocument = gql`
|
||||||
query TaxTypeList {
|
query TaxCountriesList {
|
||||||
taxTypes {
|
taxCountryConfigurations {
|
||||||
...TaxType
|
...TaxCountryConfiguration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
${TaxTypeFragmentDoc}`;
|
${TaxCountryConfigurationFragmentDoc}`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __useTaxTypeListQuery__
|
* __useTaxCountriesListQuery__
|
||||||
*
|
*
|
||||||
* To run a query within a React component, call `useTaxTypeListQuery` and pass it any options that fit your needs.
|
* To run a query within a React component, call `useTaxCountriesListQuery` and pass it any options that fit your needs.
|
||||||
* When your component renders, `useTaxTypeListQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
* When your component renders, `useTaxCountriesListQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||||
* you can use to render your UI.
|
* you can use to render your UI.
|
||||||
*
|
*
|
||||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* const { data, loading, error } = useTaxTypeListQuery({
|
* const { data, loading, error } = useTaxCountriesListQuery({
|
||||||
* variables: {
|
* variables: {
|
||||||
* },
|
* },
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
export function useTaxTypeListQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<Types.TaxTypeListQuery, Types.TaxTypeListQueryVariables>) {
|
export function useTaxCountriesListQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<Types.TaxCountriesListQuery, Types.TaxCountriesListQueryVariables>) {
|
||||||
const options = {...defaultOptions, ...baseOptions}
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
return ApolloReactHooks.useQuery<Types.TaxTypeListQuery, Types.TaxTypeListQueryVariables>(TaxTypeListDocument, options);
|
return ApolloReactHooks.useQuery<Types.TaxCountriesListQuery, Types.TaxCountriesListQueryVariables>(TaxCountriesListDocument, options);
|
||||||
}
|
}
|
||||||
export function useTaxTypeListLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types.TaxTypeListQuery, Types.TaxTypeListQueryVariables>) {
|
export function useTaxCountriesListLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types.TaxCountriesListQuery, Types.TaxCountriesListQueryVariables>) {
|
||||||
const options = {...defaultOptions, ...baseOptions}
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
return ApolloReactHooks.useLazyQuery<Types.TaxTypeListQuery, Types.TaxTypeListQueryVariables>(TaxTypeListDocument, options);
|
return ApolloReactHooks.useLazyQuery<Types.TaxCountriesListQuery, Types.TaxCountriesListQueryVariables>(TaxCountriesListDocument, options);
|
||||||
}
|
}
|
||||||
export type TaxTypeListQueryHookResult = ReturnType<typeof useTaxTypeListQuery>;
|
export type TaxCountriesListQueryHookResult = ReturnType<typeof useTaxCountriesListQuery>;
|
||||||
export type TaxTypeListLazyQueryHookResult = ReturnType<typeof useTaxTypeListLazyQuery>;
|
export type TaxCountriesListLazyQueryHookResult = ReturnType<typeof useTaxCountriesListLazyQuery>;
|
||||||
export type TaxTypeListQueryResult = Apollo.QueryResult<Types.TaxTypeListQuery, Types.TaxTypeListQueryVariables>;
|
export type TaxCountriesListQueryResult = Apollo.QueryResult<Types.TaxCountriesListQuery, Types.TaxCountriesListQueryVariables>;
|
||||||
|
export const TaxClassesListDocument = gql`
|
||||||
|
query TaxClassesList($before: String, $after: String, $first: Int, $last: Int, $filter: TaxClassFilterInput, $sortBy: TaxClassSortingInput) {
|
||||||
|
taxClasses(
|
||||||
|
before: $before
|
||||||
|
after: $after
|
||||||
|
first: $first
|
||||||
|
last: $last
|
||||||
|
filter: $filter
|
||||||
|
sortBy: $sortBy
|
||||||
|
) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
...TaxClass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
${TaxClassFragmentDoc}`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useTaxClassesListQuery__
|
||||||
|
*
|
||||||
|
* To run a query within a React component, call `useTaxClassesListQuery` and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useTaxClassesListQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||||
|
* you can use to render your UI.
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const { data, loading, error } = useTaxClassesListQuery({
|
||||||
|
* variables: {
|
||||||
|
* before: // value for 'before'
|
||||||
|
* after: // value for 'after'
|
||||||
|
* first: // value for 'first'
|
||||||
|
* last: // value for 'last'
|
||||||
|
* filter: // value for 'filter'
|
||||||
|
* sortBy: // value for 'sortBy'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useTaxClassesListQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<Types.TaxClassesListQuery, Types.TaxClassesListQueryVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return ApolloReactHooks.useQuery<Types.TaxClassesListQuery, Types.TaxClassesListQueryVariables>(TaxClassesListDocument, options);
|
||||||
|
}
|
||||||
|
export function useTaxClassesListLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types.TaxClassesListQuery, Types.TaxClassesListQueryVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return ApolloReactHooks.useLazyQuery<Types.TaxClassesListQuery, Types.TaxClassesListQueryVariables>(TaxClassesListDocument, options);
|
||||||
|
}
|
||||||
|
export type TaxClassesListQueryHookResult = ReturnType<typeof useTaxClassesListQuery>;
|
||||||
|
export type TaxClassesListLazyQueryHookResult = ReturnType<typeof useTaxClassesListLazyQuery>;
|
||||||
|
export type TaxClassesListQueryResult = Apollo.QueryResult<Types.TaxClassesListQuery, Types.TaxClassesListQueryVariables>;
|
||||||
|
export const TaxClassAssignDocument = gql`
|
||||||
|
query TaxClassAssign($first: Int, $after: String) {
|
||||||
|
taxClasses(first: $first, after: $after) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pageInfo {
|
||||||
|
hasNextPage
|
||||||
|
endCursor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useTaxClassAssignQuery__
|
||||||
|
*
|
||||||
|
* To run a query within a React component, call `useTaxClassAssignQuery` and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useTaxClassAssignQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||||
|
* you can use to render your UI.
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const { data, loading, error } = useTaxClassAssignQuery({
|
||||||
|
* variables: {
|
||||||
|
* first: // value for 'first'
|
||||||
|
* after: // value for 'after'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useTaxClassAssignQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<Types.TaxClassAssignQuery, Types.TaxClassAssignQueryVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return ApolloReactHooks.useQuery<Types.TaxClassAssignQuery, Types.TaxClassAssignQueryVariables>(TaxClassAssignDocument, options);
|
||||||
|
}
|
||||||
|
export function useTaxClassAssignLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types.TaxClassAssignQuery, Types.TaxClassAssignQueryVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return ApolloReactHooks.useLazyQuery<Types.TaxClassAssignQuery, Types.TaxClassAssignQueryVariables>(TaxClassAssignDocument, options);
|
||||||
|
}
|
||||||
|
export type TaxClassAssignQueryHookResult = ReturnType<typeof useTaxClassAssignQuery>;
|
||||||
|
export type TaxClassAssignLazyQueryHookResult = ReturnType<typeof useTaxClassAssignLazyQuery>;
|
||||||
|
export type TaxClassAssignQueryResult = Apollo.QueryResult<Types.TaxClassAssignQuery, Types.TaxClassAssignQueryVariables>;
|
||||||
export const UpdateProductTranslationsDocument = gql`
|
export const UpdateProductTranslationsDocument = gql`
|
||||||
mutation UpdateProductTranslations($id: ID!, $input: TranslationInput!, $language: LanguageCodeEnum!) {
|
mutation UpdateProductTranslations($id: ID!, $input: TranslationInput!, $language: LanguageCodeEnum!) {
|
||||||
productTranslate(id: $id, input: $input, languageCode: $language) {
|
productTranslate(id: $id, input: $input, languageCode: $language) {
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -34,6 +34,7 @@ export interface UseFormOpts<T> {
|
||||||
formId?: FormId;
|
formId?: FormId;
|
||||||
checkIfSaveIsDisabled?: CheckIfSaveIsDisabledFnType<T>;
|
checkIfSaveIsDisabled?: CheckIfSaveIsDisabledFnType<T>;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
mergeData?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UseFormResult<TData>
|
export interface UseFormResult<TData>
|
||||||
|
@ -87,10 +88,11 @@ function useForm<T extends FormData, TErrors>(
|
||||||
formId: propsFormId,
|
formId: propsFormId,
|
||||||
checkIfSaveIsDisabled,
|
checkIfSaveIsDisabled,
|
||||||
disabled,
|
disabled,
|
||||||
|
mergeData = true,
|
||||||
} = opts;
|
} = opts;
|
||||||
const [errors, setErrors] = useState<FormErrors<T>>({});
|
const [errors, setErrors] = useState<FormErrors<T>>({});
|
||||||
const [data, setData] = useStateFromProps(initialData, {
|
const [data, setData] = useStateFromProps(initialData, {
|
||||||
mergeFunc: merge,
|
mergeFunc: mergeData ? merge : undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const isSaveDisabled = () => {
|
const isSaveDisabled = () => {
|
||||||
|
|
37
src/hooks/useLocalSearch.ts
Normal file
37
src/hooks/useLocalSearch.ts
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function removes characters which break
|
||||||
|
* regexps but are rarely useful in searches
|
||||||
|
*/
|
||||||
|
const parseQuery = (query: string) =>
|
||||||
|
query.replace(/([.?*+\-=:^$\\[\]<>(){}|])/g, "\\$&");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* useLocalSearch is a hook that is useful when client-side
|
||||||
|
* search is used on particular array of items.
|
||||||
|
*
|
||||||
|
* @param array Array to search through
|
||||||
|
* @param getStringToSearch Function which specifies object
|
||||||
|
* property (possibly nested) on which search is used, eg:
|
||||||
|
* (element) => element.name where name is a string
|
||||||
|
* @returns query, setQuery - useState result
|
||||||
|
* searchResult - filtered array
|
||||||
|
*/
|
||||||
|
export function useLocalSearch<T>(
|
||||||
|
array: T[] | undefined,
|
||||||
|
getStringToSearch: (element: T) => string,
|
||||||
|
) {
|
||||||
|
const [query, setQuery] = React.useState("");
|
||||||
|
const searchResult = React.useMemo(
|
||||||
|
() =>
|
||||||
|
array?.filter(
|
||||||
|
element =>
|
||||||
|
getStringToSearch(element).search(
|
||||||
|
new RegExp(parseQuery(query), "i"),
|
||||||
|
) >= 0,
|
||||||
|
),
|
||||||
|
[array, query],
|
||||||
|
);
|
||||||
|
return { query, setQuery, searchResult };
|
||||||
|
}
|
|
@ -5,7 +5,11 @@ export interface UseStateFromPropsOpts<T> {
|
||||||
mergeFunc?: (prevData: T, state: T, newData: T) => T;
|
mergeFunc?: (prevData: T, state: T, newData: T) => T;
|
||||||
onRefresh?: (prevData: T, data: T) => void;
|
onRefresh?: (prevData: T, data: T) => void;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @deprecated This function updates state every time initial
|
||||||
|
* value changes, but uses deep comparisons to detect changes.
|
||||||
|
* You're most likely looking for `useStateUpdate` instead.
|
||||||
|
*/
|
||||||
function useStateFromProps<T>(
|
function useStateFromProps<T>(
|
||||||
data: T,
|
data: T,
|
||||||
opts: UseStateFromPropsOpts<T> = {},
|
opts: UseStateFromPropsOpts<T> = {},
|
||||||
|
|
14
src/hooks/useStateUpdate.ts
Normal file
14
src/hooks/useStateUpdate.ts
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
/** useState, but updates state every time initial value changes. */
|
||||||
|
export function useStateUpdate<T>(
|
||||||
|
data: T,
|
||||||
|
): [T, React.Dispatch<React.SetStateAction<T>>] {
|
||||||
|
const [state, setState] = React.useState(data);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
setState(data);
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
return [state, setState];
|
||||||
|
}
|
|
@ -229,11 +229,7 @@ const Routes: React.FC = () => {
|
||||||
path="/site-settings"
|
path="/site-settings"
|
||||||
component={SiteSettingsSection}
|
component={SiteSettingsSection}
|
||||||
/>
|
/>
|
||||||
<SectionRoute
|
<SectionRoute path="/taxes" component={TaxesSection} />
|
||||||
permissions={[PermissionEnum.MANAGE_SETTINGS]}
|
|
||||||
path="/taxes"
|
|
||||||
component={TaxesSection}
|
|
||||||
/>
|
|
||||||
<SectionRoute
|
<SectionRoute
|
||||||
permissions={[PermissionEnum.MANAGE_SHIPPING]}
|
permissions={[PermissionEnum.MANAGE_SHIPPING]}
|
||||||
path="/shipping"
|
path="/shipping"
|
||||||
|
|
29
src/intl.ts
29
src/intl.ts
|
@ -1,16 +1,6 @@
|
||||||
import { defineMessages, IntlShape } from "react-intl";
|
import { defineMessages, IntlShape } from "react-intl";
|
||||||
|
|
||||||
export const commonMessages = defineMessages({
|
export const commonMessages = defineMessages({
|
||||||
active: {
|
|
||||||
id: "c24hjq",
|
|
||||||
defaultMessage: "Active",
|
|
||||||
description: "status",
|
|
||||||
},
|
|
||||||
notActive: {
|
|
||||||
id: "NwQXZp",
|
|
||||||
defaultMessage: "Not active",
|
|
||||||
description: "status",
|
|
||||||
},
|
|
||||||
availability: {
|
availability: {
|
||||||
id: "hOxIeP",
|
id: "hOxIeP",
|
||||||
defaultMessage: "Availability",
|
defaultMessage: "Availability",
|
||||||
|
@ -228,6 +218,11 @@ export const buttonMessages = defineMessages({
|
||||||
defaultMessage: "Accept",
|
defaultMessage: "Accept",
|
||||||
description: "button",
|
description: "button",
|
||||||
},
|
},
|
||||||
|
add: {
|
||||||
|
id: "BJtUQI",
|
||||||
|
defaultMessage: "Add",
|
||||||
|
description: "button",
|
||||||
|
},
|
||||||
approve: {
|
approve: {
|
||||||
id: "59XppT",
|
id: "59XppT",
|
||||||
defaultMessage: "Approve",
|
defaultMessage: "Approve",
|
||||||
|
@ -509,11 +504,25 @@ export const sectionNames = defineMessages({
|
||||||
});
|
});
|
||||||
|
|
||||||
export const commonStatusMessages = defineMessages({
|
export const commonStatusMessages = defineMessages({
|
||||||
|
active: {
|
||||||
|
id: "c24hjq",
|
||||||
|
defaultMessage: "Active",
|
||||||
|
description: "status",
|
||||||
|
},
|
||||||
|
notActive: {
|
||||||
|
id: "NwQXZp",
|
||||||
|
defaultMessage: "Not active",
|
||||||
|
description: "status",
|
||||||
|
},
|
||||||
cancelled: {
|
cancelled: {
|
||||||
id: "dOQB9o",
|
id: "dOQB9o",
|
||||||
defaultMessage: "Cancelled",
|
defaultMessage: "Cancelled",
|
||||||
description: "payment status",
|
description: "payment status",
|
||||||
},
|
},
|
||||||
|
disabled: {
|
||||||
|
id: "tthToS",
|
||||||
|
defaultMessage: "Disabled",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const orderStatusMessages = defineMessages({
|
export const orderStatusMessages = defineMessages({
|
||||||
|
|
|
@ -7,18 +7,21 @@ import Metadata, { MetadataFormData } from "@saleor/components/Metadata";
|
||||||
import PageHeader from "@saleor/components/PageHeader";
|
import PageHeader from "@saleor/components/PageHeader";
|
||||||
import Savebar from "@saleor/components/Savebar";
|
import Savebar from "@saleor/components/Savebar";
|
||||||
import {
|
import {
|
||||||
ProductTypeDetailsQuery,
|
|
||||||
ProductTypeKindEnum,
|
ProductTypeKindEnum,
|
||||||
|
TaxClassFragment,
|
||||||
WeightUnitsEnum,
|
WeightUnitsEnum,
|
||||||
} from "@saleor/graphql";
|
} from "@saleor/graphql";
|
||||||
import { ChangeEvent, FormChange, SubmitPromise } from "@saleor/hooks/useForm";
|
import { SubmitPromise } from "@saleor/hooks/useForm";
|
||||||
import useNavigator from "@saleor/hooks/useNavigator";
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
import useStateFromProps from "@saleor/hooks/useStateFromProps";
|
import useStateFromProps from "@saleor/hooks/useStateFromProps";
|
||||||
import { sectionNames } from "@saleor/intl";
|
import { sectionNames } from "@saleor/intl";
|
||||||
import { ConfirmButtonTransitionState } from "@saleor/macaw-ui";
|
import { ConfirmButtonTransitionState } from "@saleor/macaw-ui";
|
||||||
import { makeProductTypeKindChangeHandler } from "@saleor/productTypes/handlers";
|
import {
|
||||||
|
handleTaxClassChange,
|
||||||
|
makeProductTypeKindChangeHandler,
|
||||||
|
} from "@saleor/productTypes/handlers";
|
||||||
import { productTypeListUrl } from "@saleor/productTypes/urls";
|
import { productTypeListUrl } from "@saleor/productTypes/urls";
|
||||||
import { UserError } from "@saleor/types";
|
import { FetchMoreProps, UserError } from "@saleor/types";
|
||||||
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
|
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
|
@ -31,7 +34,7 @@ export interface ProductTypeForm extends MetadataFormData {
|
||||||
name: string;
|
name: string;
|
||||||
kind: ProductTypeKindEnum;
|
kind: ProductTypeKindEnum;
|
||||||
isShippingRequired: boolean;
|
isShippingRequired: boolean;
|
||||||
taxType: string;
|
taxClassId: string;
|
||||||
weight: number;
|
weight: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,10 +44,11 @@ export interface ProductTypeCreatePageProps {
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
pageTitle: string;
|
pageTitle: string;
|
||||||
saveButtonBarState: ConfirmButtonTransitionState;
|
saveButtonBarState: ConfirmButtonTransitionState;
|
||||||
taxTypes: ProductTypeDetailsQuery["taxTypes"];
|
taxClasses: Array<Omit<TaxClassFragment, "countries">>;
|
||||||
kind: ProductTypeKindEnum;
|
kind: ProductTypeKindEnum;
|
||||||
onChangeKind: (kind: ProductTypeKindEnum) => void;
|
onChangeKind: (kind: ProductTypeKindEnum) => void;
|
||||||
onSubmit: (data: ProductTypeForm) => SubmitPromise<any[]>;
|
onSubmit: (data: ProductTypeForm) => SubmitPromise<any[]>;
|
||||||
|
onFetchMoreTaxClasses: FetchMoreProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
const formInitialData: ProductTypeForm = {
|
const formInitialData: ProductTypeForm = {
|
||||||
|
@ -53,38 +57,26 @@ const formInitialData: ProductTypeForm = {
|
||||||
name: "",
|
name: "",
|
||||||
kind: ProductTypeKindEnum.NORMAL,
|
kind: ProductTypeKindEnum.NORMAL,
|
||||||
privateMetadata: [],
|
privateMetadata: [],
|
||||||
taxType: "",
|
taxClassId: "",
|
||||||
weight: 0,
|
weight: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
function handleTaxTypeChange(
|
|
||||||
event: ChangeEvent,
|
|
||||||
taxTypes: ProductTypeDetailsQuery["taxTypes"],
|
|
||||||
formChange: FormChange,
|
|
||||||
displayChange: (name: string) => void,
|
|
||||||
) {
|
|
||||||
formChange(event);
|
|
||||||
displayChange(
|
|
||||||
taxTypes.find(taxType => taxType.taxCode === event.target.value)
|
|
||||||
.description,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const ProductTypeCreatePage: React.FC<ProductTypeCreatePageProps> = ({
|
const ProductTypeCreatePage: React.FC<ProductTypeCreatePageProps> = ({
|
||||||
defaultWeightUnit,
|
defaultWeightUnit,
|
||||||
disabled,
|
disabled,
|
||||||
errors,
|
errors,
|
||||||
pageTitle,
|
pageTitle,
|
||||||
saveButtonBarState,
|
saveButtonBarState,
|
||||||
taxTypes,
|
taxClasses,
|
||||||
kind,
|
kind,
|
||||||
onChangeKind,
|
onChangeKind,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
|
onFetchMoreTaxClasses,
|
||||||
}: ProductTypeCreatePageProps) => {
|
}: ProductTypeCreatePageProps) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const navigate = useNavigator();
|
const navigate = useNavigator();
|
||||||
|
|
||||||
const [taxTypeDisplayName, setTaxTypeDisplayName] = useStateFromProps("");
|
const [taxClassDisplayName, setTaxClassDisplayName] = useStateFromProps("");
|
||||||
const {
|
const {
|
||||||
makeChangeHandler: makeMetadataChangeHandler,
|
makeChangeHandler: makeMetadataChangeHandler,
|
||||||
} = useMetadataChangeTrigger();
|
} = useMetadataChangeTrigger();
|
||||||
|
@ -128,16 +120,17 @@ const ProductTypeCreatePage: React.FC<ProductTypeCreatePageProps> = ({
|
||||||
<ProductTypeTaxes
|
<ProductTypeTaxes
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
data={data}
|
data={data}
|
||||||
taxTypes={taxTypes}
|
taxClasses={taxClasses}
|
||||||
taxTypeDisplayName={taxTypeDisplayName}
|
taxClassDisplayName={taxClassDisplayName}
|
||||||
onChange={event =>
|
onChange={event =>
|
||||||
handleTaxTypeChange(
|
handleTaxClassChange(
|
||||||
event,
|
event,
|
||||||
taxTypes,
|
taxClasses,
|
||||||
change,
|
change,
|
||||||
setTaxTypeDisplayName,
|
setTaxClassDisplayName,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
onFetchMore={onFetchMoreTaxClasses}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
<Metadata data={data} onChange={changeMetadata} />
|
<Metadata data={data} onChange={changeMetadata} />
|
||||||
|
|
|
@ -12,16 +12,23 @@ import {
|
||||||
ProductAttributeType,
|
ProductAttributeType,
|
||||||
ProductTypeDetailsQuery,
|
ProductTypeDetailsQuery,
|
||||||
ProductTypeKindEnum,
|
ProductTypeKindEnum,
|
||||||
|
TaxClassFragment,
|
||||||
WeightUnitsEnum,
|
WeightUnitsEnum,
|
||||||
} from "@saleor/graphql";
|
} from "@saleor/graphql";
|
||||||
import { ChangeEvent, FormChange, SubmitPromise } from "@saleor/hooks/useForm";
|
import { SubmitPromise } from "@saleor/hooks/useForm";
|
||||||
import useNavigator from "@saleor/hooks/useNavigator";
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
import useStateFromProps from "@saleor/hooks/useStateFromProps";
|
import useStateFromProps from "@saleor/hooks/useStateFromProps";
|
||||||
import { sectionNames } from "@saleor/intl";
|
import { sectionNames } from "@saleor/intl";
|
||||||
import { ConfirmButtonTransitionState } from "@saleor/macaw-ui";
|
import { ConfirmButtonTransitionState } from "@saleor/macaw-ui";
|
||||||
import { maybe } from "@saleor/misc";
|
import { maybe } from "@saleor/misc";
|
||||||
|
import { handleTaxClassChange } from "@saleor/productTypes/handlers";
|
||||||
import { productTypeListUrl } from "@saleor/productTypes/urls";
|
import { productTypeListUrl } from "@saleor/productTypes/urls";
|
||||||
import { ListActions, ReorderEvent, UserError } from "@saleor/types";
|
import {
|
||||||
|
FetchMoreProps,
|
||||||
|
ListActions,
|
||||||
|
ReorderEvent,
|
||||||
|
UserError,
|
||||||
|
} from "@saleor/types";
|
||||||
import { mapMetadataItemToInput } from "@saleor/utils/maps";
|
import { mapMetadataItemToInput } from "@saleor/utils/maps";
|
||||||
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
|
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
@ -43,7 +50,7 @@ export interface ProductTypeForm extends MetadataFormData {
|
||||||
kind: ProductTypeKindEnum;
|
kind: ProductTypeKindEnum;
|
||||||
hasVariants: boolean;
|
hasVariants: boolean;
|
||||||
isShippingRequired: boolean;
|
isShippingRequired: boolean;
|
||||||
taxType: string;
|
taxClassId: string;
|
||||||
productAttributes: ChoiceType[];
|
productAttributes: ChoiceType[];
|
||||||
variantAttributes: ChoiceType[];
|
variantAttributes: ChoiceType[];
|
||||||
weight: number;
|
weight: number;
|
||||||
|
@ -57,7 +64,7 @@ export interface ProductTypeDetailsPageProps {
|
||||||
pageTitle: string;
|
pageTitle: string;
|
||||||
productAttributeList: ListActions;
|
productAttributeList: ListActions;
|
||||||
saveButtonBarState: ConfirmButtonTransitionState;
|
saveButtonBarState: ConfirmButtonTransitionState;
|
||||||
taxTypes: ProductTypeDetailsQuery["taxTypes"];
|
taxClasses: Array<Omit<TaxClassFragment, "countries">>;
|
||||||
variantAttributeList: ListActions;
|
variantAttributeList: ListActions;
|
||||||
onAttributeAdd: (type: ProductAttributeType) => void;
|
onAttributeAdd: (type: ProductAttributeType) => void;
|
||||||
onAttributeReorder: (event: ReorderEvent, type: ProductAttributeType) => void;
|
onAttributeReorder: (event: ReorderEvent, type: ProductAttributeType) => void;
|
||||||
|
@ -67,19 +74,7 @@ export interface ProductTypeDetailsPageProps {
|
||||||
onSubmit: (data: ProductTypeForm) => SubmitPromise;
|
onSubmit: (data: ProductTypeForm) => SubmitPromise;
|
||||||
setSelectedVariantAttributes: (data: string[]) => void;
|
setSelectedVariantAttributes: (data: string[]) => void;
|
||||||
selectedVariantAttributes: string[];
|
selectedVariantAttributes: string[];
|
||||||
}
|
onFetchMoreTaxClasses: FetchMoreProps;
|
||||||
|
|
||||||
function handleTaxTypeChange(
|
|
||||||
event: ChangeEvent,
|
|
||||||
taxTypes: ProductTypeDetailsQuery["taxTypes"],
|
|
||||||
formChange: FormChange,
|
|
||||||
displayChange: (name: string) => void,
|
|
||||||
) {
|
|
||||||
formChange(event);
|
|
||||||
displayChange(
|
|
||||||
taxTypes.find(taxType => taxType.taxCode === event.target.value)
|
|
||||||
.description,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProductTypeDetailsPage: React.FC<ProductTypeDetailsPageProps> = ({
|
const ProductTypeDetailsPage: React.FC<ProductTypeDetailsPageProps> = ({
|
||||||
|
@ -90,7 +85,7 @@ const ProductTypeDetailsPage: React.FC<ProductTypeDetailsPageProps> = ({
|
||||||
productType,
|
productType,
|
||||||
productAttributeList,
|
productAttributeList,
|
||||||
saveButtonBarState,
|
saveButtonBarState,
|
||||||
taxTypes,
|
taxClasses,
|
||||||
variantAttributeList,
|
variantAttributeList,
|
||||||
onAttributeAdd,
|
onAttributeAdd,
|
||||||
onAttributeUnassign,
|
onAttributeUnassign,
|
||||||
|
@ -100,6 +95,7 @@ const ProductTypeDetailsPage: React.FC<ProductTypeDetailsPageProps> = ({
|
||||||
onSubmit,
|
onSubmit,
|
||||||
setSelectedVariantAttributes,
|
setSelectedVariantAttributes,
|
||||||
selectedVariantAttributes,
|
selectedVariantAttributes,
|
||||||
|
onFetchMoreTaxClasses,
|
||||||
}) => {
|
}) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const navigate = useNavigator();
|
const navigate = useNavigator();
|
||||||
|
@ -110,8 +106,8 @@ const ProductTypeDetailsPage: React.FC<ProductTypeDetailsPageProps> = ({
|
||||||
makeChangeHandler: makeMetadataChangeHandler,
|
makeChangeHandler: makeMetadataChangeHandler,
|
||||||
} = useMetadataChangeTrigger();
|
} = useMetadataChangeTrigger();
|
||||||
|
|
||||||
const [taxTypeDisplayName, setTaxTypeDisplayName] = useStateFromProps(
|
const [taxClassDisplayName, setTaxClassDisplayName] = useStateFromProps(
|
||||||
maybe(() => productType.taxType.description, ""),
|
productType?.taxClass?.name ?? "",
|
||||||
);
|
);
|
||||||
const formInitialData: ProductTypeForm = {
|
const formInitialData: ProductTypeForm = {
|
||||||
hasVariants:
|
hasVariants:
|
||||||
|
@ -133,7 +129,7 @@ const ProductTypeDetailsPage: React.FC<ProductTypeDetailsPageProps> = ({
|
||||||
value: attribute.id,
|
value: attribute.id,
|
||||||
}))
|
}))
|
||||||
: [],
|
: [],
|
||||||
taxType: maybe(() => productType.taxType.taxCode, ""),
|
taxClassId: productType?.taxClass?.id ?? "",
|
||||||
variantAttributes:
|
variantAttributes:
|
||||||
maybe(() => productType.variantAttributes) !== undefined
|
maybe(() => productType.variantAttributes) !== undefined
|
||||||
? productType.variantAttributes.map(attribute => ({
|
? productType.variantAttributes.map(attribute => ({
|
||||||
|
@ -186,16 +182,17 @@ const ProductTypeDetailsPage: React.FC<ProductTypeDetailsPageProps> = ({
|
||||||
<ProductTypeTaxes
|
<ProductTypeTaxes
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
data={data}
|
data={data}
|
||||||
taxTypes={taxTypes}
|
taxClasses={taxClasses}
|
||||||
taxTypeDisplayName={taxTypeDisplayName}
|
taxClassDisplayName={taxClassDisplayName}
|
||||||
onChange={event =>
|
onChange={event =>
|
||||||
handleTaxTypeChange(
|
handleTaxClassChange(
|
||||||
event,
|
event,
|
||||||
taxTypes,
|
taxClasses,
|
||||||
change,
|
change,
|
||||||
setTaxTypeDisplayName,
|
setTaxClassDisplayName,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
onFetchMore={onFetchMoreTaxClasses}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
<ProductTypeAttributes
|
<ProductTypeAttributes
|
||||||
|
|
|
@ -115,9 +115,9 @@ const ProductTypeList: React.FC<ProductTypeListProps> = props => {
|
||||||
</TableCellHeader>
|
</TableCellHeader>
|
||||||
<TableCell className={classes.colTax}>
|
<TableCell className={classes.colTax}>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id="TalJlD"
|
id="+Jgot0"
|
||||||
defaultMessage="Tax"
|
defaultMessage="Tax class"
|
||||||
description="tax rate for a product type"
|
description="tax class for a product type"
|
||||||
/>
|
/>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
|
@ -194,11 +194,7 @@ const ProductTypeList: React.FC<ProductTypeListProps> = props => {
|
||||||
)}
|
)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className={classes.colTax}>
|
<TableCell className={classes.colTax}>
|
||||||
{maybe(() => productType.taxType) ? (
|
{productType?.taxClass?.name ?? "-"}
|
||||||
productType.taxType.description
|
|
||||||
) : (
|
|
||||||
<Skeleton />
|
|
||||||
)}
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRowLink>
|
</TableRowLink>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,22 +1,25 @@
|
||||||
import { Card, CardContent } from "@material-ui/core";
|
import { Card, CardContent } from "@material-ui/core";
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
import SingleAutocompleteSelectField from "@saleor/components/SingleAutocompleteSelectField";
|
import SingleAutocompleteSelectField from "@saleor/components/SingleAutocompleteSelectField";
|
||||||
import { ProductTypeDetailsQuery } from "@saleor/graphql";
|
import { TaxClassFragment } from "@saleor/graphql";
|
||||||
|
import { sectionNames } from "@saleor/intl";
|
||||||
import { makeStyles } from "@saleor/macaw-ui";
|
import { makeStyles } from "@saleor/macaw-ui";
|
||||||
|
import { taxesMessages } from "@saleor/taxes/messages";
|
||||||
|
import { FetchMoreProps } from "@saleor/types";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
import { maybe } from "../../../misc";
|
|
||||||
import { ProductTypeForm } from "../ProductTypeDetailsPage/ProductTypeDetailsPage";
|
import { ProductTypeForm } from "../ProductTypeDetailsPage/ProductTypeDetailsPage";
|
||||||
|
|
||||||
interface ProductTypeTaxesProps {
|
interface ProductTypeTaxesProps {
|
||||||
data: {
|
data: {
|
||||||
taxType: string;
|
taxClassId: string;
|
||||||
};
|
};
|
||||||
taxTypeDisplayName: string;
|
taxClassDisplayName: string;
|
||||||
taxTypes: ProductTypeDetailsQuery["taxTypes"];
|
taxClasses: Array<Omit<TaxClassFragment, "countries">>;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
|
onFetchMore: FetchMoreProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useStyles = makeStyles(
|
const useStyles = makeStyles(
|
||||||
|
@ -29,39 +32,38 @@ const useStyles = makeStyles(
|
||||||
);
|
);
|
||||||
|
|
||||||
const ProductTypeTaxes: React.FC<ProductTypeTaxesProps> = props => {
|
const ProductTypeTaxes: React.FC<ProductTypeTaxesProps> = props => {
|
||||||
const { data, disabled, taxTypes, taxTypeDisplayName, onChange } = props;
|
const {
|
||||||
|
data,
|
||||||
|
disabled,
|
||||||
|
taxClasses,
|
||||||
|
taxClassDisplayName,
|
||||||
|
onChange,
|
||||||
|
onFetchMore,
|
||||||
|
} = props;
|
||||||
const classes = useStyles(props);
|
const classes = useStyles(props);
|
||||||
|
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className={classes.root}>
|
<Card className={classes.root}>
|
||||||
<CardTitle
|
<CardTitle title={intl.formatMessage(sectionNames.taxes)} />
|
||||||
title={intl.formatMessage({
|
|
||||||
id: "mUb8Gt",
|
|
||||||
defaultMessage: "Taxes",
|
|
||||||
description: "section header",
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<SingleAutocompleteSelectField
|
<SingleAutocompleteSelectField
|
||||||
|
emptyOption
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
displayValue={taxTypeDisplayName}
|
displayValue={taxClassDisplayName}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage(taxesMessages.taxClass)}
|
||||||
id: "9xUIAh",
|
name={"taxClassId" as keyof ProductTypeForm}
|
||||||
defaultMessage: "Tax group",
|
|
||||||
})}
|
|
||||||
name={"taxType" as keyof ProductTypeForm}
|
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
value={data.taxType}
|
value={data.taxClassId}
|
||||||
choices={maybe(
|
choices={taxClasses.map(choice => ({
|
||||||
() =>
|
label: choice.name,
|
||||||
taxTypes.map(c => ({ label: c.description, value: c.taxCode })),
|
value: choice.id,
|
||||||
[],
|
}))}
|
||||||
)}
|
|
||||||
InputProps={{
|
InputProps={{
|
||||||
autoComplete: "off",
|
autoComplete: "off",
|
||||||
}}
|
}}
|
||||||
|
{...onFetchMore}
|
||||||
/>
|
/>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
|
@ -1007,10 +1007,10 @@ export const productTypeSearch: ProductTypeQuery["productType"] = {
|
||||||
id: "UHJvZHVjdFR5cGU6NA==",
|
id: "UHJvZHVjdFR5cGU6NA==",
|
||||||
name: "Candy",
|
name: "Candy",
|
||||||
productAttributes: [attributes[0]],
|
productAttributes: [attributes[0]],
|
||||||
taxType: {
|
taxClass: {
|
||||||
__typename: "TaxType" as "TaxType",
|
__typename: "TaxClass" as "TaxClass",
|
||||||
description: "PB100000",
|
name: "PB100000",
|
||||||
taxCode: "Books / Manuals",
|
id: "Books / Manuals",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1026,10 +1026,10 @@ export const productTypes: Array<RelayToFlat<
|
||||||
name: "Candy",
|
name: "Candy",
|
||||||
kind: ProductTypeKindEnum.NORMAL,
|
kind: ProductTypeKindEnum.NORMAL,
|
||||||
productAttributes: [attributes[0]],
|
productAttributes: [attributes[0]],
|
||||||
taxType: {
|
taxClass: {
|
||||||
__typename: "TaxType" as "TaxType",
|
__typename: "TaxClass" as "TaxClass",
|
||||||
description: "PB100000",
|
name: "Shipping method",
|
||||||
taxCode: "Books / Manuals",
|
id: "VGV4Q2xhc3M6MQ==",
|
||||||
},
|
},
|
||||||
variantAttributes: [attributes[1], attributes[2]],
|
variantAttributes: [attributes[1], attributes[2]],
|
||||||
},
|
},
|
||||||
|
@ -1041,10 +1041,10 @@ export const productTypes: Array<RelayToFlat<
|
||||||
name: "E-books",
|
name: "E-books",
|
||||||
kind: ProductTypeKindEnum.NORMAL,
|
kind: ProductTypeKindEnum.NORMAL,
|
||||||
productAttributes: [attributes[5]],
|
productAttributes: [attributes[5]],
|
||||||
taxType: {
|
taxClass: {
|
||||||
__typename: "TaxType" as "TaxType",
|
__typename: "TaxClass" as "TaxClass",
|
||||||
description: "PH403682",
|
name: "Digital goods",
|
||||||
taxCode: "Holters",
|
id: "VGV4Q4xhc3M6MQ==",
|
||||||
},
|
},
|
||||||
variantAttributes: [attributes[0], attributes[3]],
|
variantAttributes: [attributes[0], attributes[3]],
|
||||||
},
|
},
|
||||||
|
@ -1056,10 +1056,10 @@ export const productTypes: Array<RelayToFlat<
|
||||||
name: "Mugs",
|
name: "Mugs",
|
||||||
kind: ProductTypeKindEnum.NORMAL,
|
kind: ProductTypeKindEnum.NORMAL,
|
||||||
productAttributes: [attributes[7]],
|
productAttributes: [attributes[7]],
|
||||||
taxType: {
|
taxClass: {
|
||||||
__typename: "TaxType" as "TaxType",
|
__typename: "TaxClass" as "TaxClass",
|
||||||
description: "PC077426",
|
name: "Houseware",
|
||||||
taxCode: "Cabling",
|
id: "VGV4Q3xhc3M6MQ==",
|
||||||
},
|
},
|
||||||
variantAttributes: [attributes[2], attributes[5]],
|
variantAttributes: [attributes[2], attributes[5]],
|
||||||
},
|
},
|
||||||
|
@ -1071,10 +1071,10 @@ export const productTypes: Array<RelayToFlat<
|
||||||
name: "Coffee",
|
name: "Coffee",
|
||||||
kind: ProductTypeKindEnum.NORMAL,
|
kind: ProductTypeKindEnum.NORMAL,
|
||||||
productAttributes: [attributes[8]],
|
productAttributes: [attributes[8]],
|
||||||
taxType: {
|
taxClass: {
|
||||||
__typename: "TaxType" as "TaxType",
|
__typename: "TaxClass" as "TaxClass",
|
||||||
description: "PB100000",
|
name: "PB100000",
|
||||||
taxCode: "Books / Manuals",
|
id: "Books / Manuals",
|
||||||
},
|
},
|
||||||
variantAttributes: [attributes[1], attributes[4]],
|
variantAttributes: [attributes[1], attributes[4]],
|
||||||
},
|
},
|
||||||
|
@ -1086,10 +1086,10 @@ export const productTypes: Array<RelayToFlat<
|
||||||
name: "T-Shirt",
|
name: "T-Shirt",
|
||||||
kind: ProductTypeKindEnum.NORMAL,
|
kind: ProductTypeKindEnum.NORMAL,
|
||||||
productAttributes: [attributes[4]],
|
productAttributes: [attributes[4]],
|
||||||
taxType: {
|
taxClass: {
|
||||||
__typename: "TaxType" as "TaxType",
|
__typename: "TaxClass" as "TaxClass",
|
||||||
description: "PH403970",
|
name: "PH403970",
|
||||||
taxCode: "Wheelchair",
|
id: "Wheelchair",
|
||||||
},
|
},
|
||||||
variantAttributes: [attributes[1], attributes[6]],
|
variantAttributes: [attributes[1], attributes[6]],
|
||||||
},
|
},
|
||||||
|
@ -1151,10 +1151,10 @@ export const productType: ProductTypeDetailsQuery["productType"] = {
|
||||||
unit: null,
|
unit: null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
taxType: {
|
taxClass: {
|
||||||
__typename: "TaxType" as "TaxType",
|
__typename: "TaxClass",
|
||||||
description: "PH405458",
|
name: "Shipping method",
|
||||||
taxCode: "Shields",
|
id: "VGV4Q2xhc3M6MQ==",
|
||||||
},
|
},
|
||||||
variantAttributes: [
|
variantAttributes: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { ProductTypeKindEnum } from "@saleor/graphql";
|
import { ProductTypeKindEnum, TaxClassFragment } from "@saleor/graphql";
|
||||||
import { FormChange } from "@saleor/hooks/useForm";
|
import { ChangeEvent, FormChange } from "@saleor/hooks/useForm";
|
||||||
|
|
||||||
export const makeProductTypeKindChangeHandler = (
|
export const makeProductTypeKindChangeHandler = (
|
||||||
onChange: FormChange,
|
onChange: FormChange,
|
||||||
|
@ -9,3 +9,15 @@ export const makeProductTypeKindChangeHandler = (
|
||||||
onKindChange(kind);
|
onKindChange(kind);
|
||||||
onChange(event);
|
onChange(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function handleTaxClassChange(
|
||||||
|
event: ChangeEvent,
|
||||||
|
taxClasses: Array<Omit<TaxClassFragment, "countries">>,
|
||||||
|
formChange: FormChange,
|
||||||
|
displayChange: (name: string) => void,
|
||||||
|
) {
|
||||||
|
formChange(event);
|
||||||
|
displayChange(
|
||||||
|
taxClasses.find(taxClass => taxClass.id === event.target.value)?.name ?? "",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -37,10 +37,6 @@ export const productTypeDetailsQuery = gql`
|
||||||
shop {
|
shop {
|
||||||
defaultWeightUnit
|
defaultWeightUnit
|
||||||
}
|
}
|
||||||
taxTypes {
|
|
||||||
taxCode
|
|
||||||
description
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -49,9 +45,5 @@ export const productTypeCreateDataQuery = gql`
|
||||||
shop {
|
shop {
|
||||||
defaultWeightUnit
|
defaultWeightUnit
|
||||||
}
|
}
|
||||||
taxTypes {
|
|
||||||
taxCode
|
|
||||||
description
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
} from "@saleor/graphql";
|
} from "@saleor/graphql";
|
||||||
import useNavigator from "@saleor/hooks/useNavigator";
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
import useNotifier from "@saleor/hooks/useNotifier";
|
import useNotifier from "@saleor/hooks/useNotifier";
|
||||||
|
import { useTaxClassFetchMore } from "@saleor/taxes/utils/useTaxClassFetchMore";
|
||||||
import createMetadataCreateHandler from "@saleor/utils/handlers/metadataCreateHandler";
|
import createMetadataCreateHandler from "@saleor/utils/handlers/metadataCreateHandler";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
|
@ -47,6 +48,8 @@ export const ProductTypeCreate: React.FC<ProductTypeCreateProps> = ({
|
||||||
displayLoader: true,
|
displayLoader: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { taxClasses, fetchMoreTaxClasses } = useTaxClassFetchMore();
|
||||||
|
|
||||||
const [
|
const [
|
||||||
createProductType,
|
createProductType,
|
||||||
createProductTypeOpts,
|
createProductTypeOpts,
|
||||||
|
@ -73,7 +76,7 @@ export const ProductTypeCreate: React.FC<ProductTypeCreateProps> = ({
|
||||||
isShippingRequired: formData.isShippingRequired,
|
isShippingRequired: formData.isShippingRequired,
|
||||||
name: formData.name,
|
name: formData.name,
|
||||||
kind: formData.kind,
|
kind: formData.kind,
|
||||||
taxCode: formData.taxType,
|
taxClass: formData.taxClassId,
|
||||||
weight: formData.weight,
|
weight: formData.weight,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -110,7 +113,8 @@ export const ProductTypeCreate: React.FC<ProductTypeCreateProps> = ({
|
||||||
description: "header",
|
description: "header",
|
||||||
})}
|
})}
|
||||||
saveButtonBarState={createProductTypeOpts.status}
|
saveButtonBarState={createProductTypeOpts.status}
|
||||||
taxTypes={data?.taxTypes || []}
|
taxClasses={taxClasses ?? []}
|
||||||
|
onFetchMoreTaxClasses={fetchMoreTaxClasses}
|
||||||
kind={params.kind}
|
kind={params.kind}
|
||||||
onChangeKind={handleChangeKind}
|
onChangeKind={handleChangeKind}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import { getStringOrPlaceholder, maybe } from "@saleor/misc";
|
||||||
import useProductTypeDelete from "@saleor/productTypes/hooks/useProductTypeDelete";
|
import useProductTypeDelete from "@saleor/productTypes/hooks/useProductTypeDelete";
|
||||||
import useProductTypeOperations from "@saleor/productTypes/hooks/useProductTypeOperations";
|
import useProductTypeOperations from "@saleor/productTypes/hooks/useProductTypeOperations";
|
||||||
import useAvailableProductAttributeSearch from "@saleor/searches/useAvailableProductAttributeSearch";
|
import useAvailableProductAttributeSearch from "@saleor/searches/useAvailableProductAttributeSearch";
|
||||||
|
import { useTaxClassFetchMore } from "@saleor/taxes/utils/useTaxClassFetchMore";
|
||||||
import { ReorderEvent } from "@saleor/types";
|
import { ReorderEvent } from "@saleor/types";
|
||||||
import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler";
|
import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler";
|
||||||
import { mapEdgesToItems } from "@saleor/utils/maps";
|
import { mapEdgesToItems } from "@saleor/utils/maps";
|
||||||
|
@ -142,7 +143,7 @@ export const ProductTypeUpdate: React.FC<ProductTypeUpdateProps> = ({
|
||||||
productAttributes: formData.productAttributes.map(
|
productAttributes: formData.productAttributes.map(
|
||||||
choice => choice.value,
|
choice => choice.value,
|
||||||
),
|
),
|
||||||
taxCode: formData.taxType,
|
taxClass: formData.taxClassId,
|
||||||
variantAttributes: formData.variantAttributes.map(
|
variantAttributes: formData.variantAttributes.map(
|
||||||
choice => choice.value,
|
choice => choice.value,
|
||||||
),
|
),
|
||||||
|
@ -168,6 +169,8 @@ export const ProductTypeUpdate: React.FC<ProductTypeUpdateProps> = ({
|
||||||
variables: { id },
|
variables: { id },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { taxClasses, fetchMoreTaxClasses } = useTaxClassFetchMore();
|
||||||
|
|
||||||
const productType = data?.productType;
|
const productType = data?.productType;
|
||||||
|
|
||||||
const closeModal = () => navigate(productTypeUrl(id), { replace: true });
|
const closeModal = () => navigate(productTypeUrl(id), { replace: true });
|
||||||
|
@ -321,7 +324,7 @@ export const ProductTypeUpdate: React.FC<ProductTypeUpdateProps> = ({
|
||||||
saveButtonBarState={
|
saveButtonBarState={
|
||||||
updateProductTypeOpts.status || updateProductAttributesOpts.status
|
updateProductTypeOpts.status || updateProductAttributesOpts.status
|
||||||
}
|
}
|
||||||
taxTypes={maybe(() => data.taxTypes, [])}
|
taxClasses={taxClasses ?? []}
|
||||||
selectedVariantAttributes={selectedVariantAttributes}
|
selectedVariantAttributes={selectedVariantAttributes}
|
||||||
setSelectedVariantAttributes={setSelectedVariantAttributes}
|
setSelectedVariantAttributes={setSelectedVariantAttributes}
|
||||||
onAttributeAdd={type =>
|
onAttributeAdd={type =>
|
||||||
|
@ -398,6 +401,7 @@ export const ProductTypeUpdate: React.FC<ProductTypeUpdateProps> = ({
|
||||||
</Button>
|
</Button>
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
|
onFetchMoreTaxClasses={fetchMoreTaxClasses}
|
||||||
/>
|
/>
|
||||||
{!dataLoading && (
|
{!dataLoading && (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -28,7 +28,7 @@ import {
|
||||||
SearchProductsQuery,
|
SearchProductsQuery,
|
||||||
SearchProductTypesQuery,
|
SearchProductTypesQuery,
|
||||||
SearchWarehousesQuery,
|
SearchWarehousesQuery,
|
||||||
TaxTypeFragment,
|
TaxClassFragment,
|
||||||
} from "@saleor/graphql";
|
} from "@saleor/graphql";
|
||||||
import useNavigator from "@saleor/hooks/useNavigator";
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
import useStateFromProps from "@saleor/hooks/useStateFromProps";
|
import useStateFromProps from "@saleor/hooks/useStateFromProps";
|
||||||
|
@ -75,7 +75,8 @@ interface ProductCreatePageProps {
|
||||||
saveButtonBarState: ConfirmButtonTransitionState;
|
saveButtonBarState: ConfirmButtonTransitionState;
|
||||||
weightUnit: string;
|
weightUnit: string;
|
||||||
warehouses: RelayToFlat<SearchWarehousesQuery["search"]>;
|
warehouses: RelayToFlat<SearchWarehousesQuery["search"]>;
|
||||||
taxTypes: TaxTypeFragment[];
|
taxClasses: Array<Omit<TaxClassFragment, "countries">>;
|
||||||
|
fetchMoreTaxClasses: FetchMoreProps;
|
||||||
selectedProductType?: ProductTypeQuery["productType"];
|
selectedProductType?: ProductTypeQuery["productType"];
|
||||||
fetchCategories: (data: string) => void;
|
fetchCategories: (data: string) => void;
|
||||||
fetchCollections: (data: string) => void;
|
fetchCollections: (data: string) => void;
|
||||||
|
@ -117,7 +118,8 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
|
||||||
referenceProducts = [],
|
referenceProducts = [],
|
||||||
saveButtonBarState,
|
saveButtonBarState,
|
||||||
warehouses,
|
warehouses,
|
||||||
taxTypes,
|
taxClasses,
|
||||||
|
fetchMoreTaxClasses,
|
||||||
selectedProductType,
|
selectedProductType,
|
||||||
fetchProductTypes,
|
fetchProductTypes,
|
||||||
weightUnit,
|
weightUnit,
|
||||||
|
@ -149,18 +151,18 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
|
||||||
MultiAutocompleteChoiceType[]
|
MultiAutocompleteChoiceType[]
|
||||||
>([]);
|
>([]);
|
||||||
|
|
||||||
const [selectedTaxType, setSelectedTaxType] = useStateFromProps(
|
const [selectedTaxClass, setSelectedTaxClass] = useStateFromProps(
|
||||||
initial?.taxCode || null,
|
initial?.taxClassId ?? "",
|
||||||
);
|
);
|
||||||
|
|
||||||
const categories = getChoices(categoryChoiceList);
|
const categories = getChoices(categoryChoiceList);
|
||||||
const collections = getChoices(collectionChoiceList);
|
const collections = getChoices(collectionChoiceList);
|
||||||
const productTypes = getChoices(productTypeChoiceList);
|
const productTypes = getChoices(productTypeChoiceList);
|
||||||
const taxTypeChoices =
|
const taxClassChoices =
|
||||||
taxTypes?.map(taxType => ({
|
taxClasses?.map(taxClass => ({
|
||||||
label: taxType.description,
|
label: taxClass.name,
|
||||||
value: taxType.taxCode,
|
value: taxClass.id,
|
||||||
})) || [];
|
})) ?? [];
|
||||||
|
|
||||||
const canOpenAssignReferencesAttributeDialog = !!assignReferencesAttributeId;
|
const canOpenAssignReferencesAttributeDialog = !!assignReferencesAttributeId;
|
||||||
|
|
||||||
|
@ -194,9 +196,9 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
|
||||||
selectedCollections={selectedCollections}
|
selectedCollections={selectedCollections}
|
||||||
setSelectedCategory={setSelectedCategory}
|
setSelectedCategory={setSelectedCategory}
|
||||||
setSelectedCollections={setSelectedCollections}
|
setSelectedCollections={setSelectedCollections}
|
||||||
setSelectedTaxType={setSelectedTaxType}
|
setSelectedTaxClass={setSelectedTaxClass}
|
||||||
setChannels={onChannelsChange}
|
setChannels={onChannelsChange}
|
||||||
taxTypes={taxTypeChoices}
|
taxClasses={taxClassChoices}
|
||||||
warehouses={warehouses}
|
warehouses={warehouses}
|
||||||
currentChannels={currentChannels}
|
currentChannels={currentChannels}
|
||||||
fetchReferencePages={fetchReferencePages}
|
fetchReferencePages={fetchReferencePages}
|
||||||
|
@ -362,12 +364,12 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
|
||||||
)}
|
)}
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
<ProductTaxes
|
<ProductTaxes
|
||||||
data={data}
|
value={data.taxClassId}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
onChange={change}
|
onChange={handlers.selectTaxClass}
|
||||||
onTaxTypeChange={handlers.selectTaxRate}
|
taxClassDisplayName={selectedTaxClass}
|
||||||
selectedTaxTypeDisplayName={selectedTaxType}
|
taxClasses={taxClasses}
|
||||||
taxTypes={taxTypes}
|
onFetchMore={fetchMoreTaxClasses}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
|
@ -74,9 +74,7 @@ import { ProductStockFormsetData, ProductStockInput } from "../ProductStocks";
|
||||||
|
|
||||||
export interface ProductCreateFormData extends MetadataFormData {
|
export interface ProductCreateFormData extends MetadataFormData {
|
||||||
category: string;
|
category: string;
|
||||||
changeTaxCode: boolean;
|
|
||||||
channelListings: ChannelData[];
|
channelListings: ChannelData[];
|
||||||
chargeTaxes: boolean;
|
|
||||||
collections: string[];
|
collections: string[];
|
||||||
description: OutputData;
|
description: OutputData;
|
||||||
isAvailable: boolean;
|
isAvailable: boolean;
|
||||||
|
@ -88,7 +86,6 @@ export interface ProductCreateFormData extends MetadataFormData {
|
||||||
sku: string;
|
sku: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
stockQuantity: number;
|
stockQuantity: number;
|
||||||
taxCode: string;
|
|
||||||
trackInventory: boolean;
|
trackInventory: boolean;
|
||||||
isPreorder: boolean;
|
isPreorder: boolean;
|
||||||
globalThreshold: string;
|
globalThreshold: string;
|
||||||
|
@ -96,6 +93,7 @@ export interface ProductCreateFormData extends MetadataFormData {
|
||||||
hasPreorderEndDate: boolean;
|
hasPreorderEndDate: boolean;
|
||||||
preorderEndDateTime: string;
|
preorderEndDateTime: string;
|
||||||
weight: string;
|
weight: string;
|
||||||
|
taxClassId: string;
|
||||||
}
|
}
|
||||||
export interface ProductCreateData extends ProductCreateFormData {
|
export interface ProductCreateData extends ProductCreateFormData {
|
||||||
attributes: AttributeInput[];
|
attributes: AttributeInput[];
|
||||||
|
@ -109,7 +107,7 @@ export interface ProductCreateHandlers
|
||||||
| "selectCategory"
|
| "selectCategory"
|
||||||
| "selectCollection"
|
| "selectCollection"
|
||||||
| "selectProductType"
|
| "selectProductType"
|
||||||
| "selectTaxRate",
|
| "selectTaxClass",
|
||||||
FormChange
|
FormChange
|
||||||
>,
|
>,
|
||||||
Record<
|
Record<
|
||||||
|
@ -150,14 +148,14 @@ export type UseProductCreateFormRenderProps = Omit<
|
||||||
|
|
||||||
export interface UseProductCreateFormOpts
|
export interface UseProductCreateFormOpts
|
||||||
extends Record<
|
extends Record<
|
||||||
"categories" | "collections" | "taxTypes",
|
"categories" | "collections" | "taxClasses",
|
||||||
SingleAutocompleteChoiceType[]
|
SingleAutocompleteChoiceType[]
|
||||||
> {
|
> {
|
||||||
setSelectedCategory: React.Dispatch<React.SetStateAction<string>>;
|
setSelectedCategory: React.Dispatch<React.SetStateAction<string>>;
|
||||||
setSelectedCollections: React.Dispatch<
|
setSelectedCollections: React.Dispatch<
|
||||||
React.SetStateAction<MultiAutocompleteChoiceType[]>
|
React.SetStateAction<MultiAutocompleteChoiceType[]>
|
||||||
>;
|
>;
|
||||||
setSelectedTaxType: React.Dispatch<React.SetStateAction<string>>;
|
setSelectedTaxClass: React.Dispatch<React.SetStateAction<string>>;
|
||||||
setChannels: (channels: ChannelData[]) => void;
|
setChannels: (channels: ChannelData[]) => void;
|
||||||
selectedCollections: MultiAutocompleteChoiceType[];
|
selectedCollections: MultiAutocompleteChoiceType[];
|
||||||
productTypes: RelayToFlat<SearchProductTypesQuery["search"]>;
|
productTypes: RelayToFlat<SearchProductTypesQuery["search"]>;
|
||||||
|
@ -194,9 +192,7 @@ function useProductCreateForm(
|
||||||
const defaultInitialFormData: ProductCreateFormData &
|
const defaultInitialFormData: ProductCreateFormData &
|
||||||
Record<"productType", string> = {
|
Record<"productType", string> = {
|
||||||
category: "",
|
category: "",
|
||||||
changeTaxCode: false,
|
|
||||||
channelListings: opts.currentChannels,
|
channelListings: opts.currentChannels,
|
||||||
chargeTaxes: false,
|
|
||||||
collections: [],
|
collections: [],
|
||||||
description: null,
|
description: null,
|
||||||
isAvailable: false,
|
isAvailable: false,
|
||||||
|
@ -210,7 +206,7 @@ function useProductCreateForm(
|
||||||
sku: "",
|
sku: "",
|
||||||
slug: "",
|
slug: "",
|
||||||
stockQuantity: null,
|
stockQuantity: null,
|
||||||
taxCode: null,
|
taxClassId: "",
|
||||||
trackInventory: false,
|
trackInventory: false,
|
||||||
weight: "",
|
weight: "",
|
||||||
globalSoldUnits: 0,
|
globalSoldUnits: 0,
|
||||||
|
@ -331,10 +327,10 @@ function useProductCreateForm(
|
||||||
triggerChange();
|
triggerChange();
|
||||||
stocks.remove(id);
|
stocks.remove(id);
|
||||||
};
|
};
|
||||||
const handleTaxTypeSelect = createSingleAutocompleteSelectHandler(
|
const handleTaxClassSelect = createSingleAutocompleteSelectHandler(
|
||||||
handleChange,
|
handleChange,
|
||||||
opts.setSelectedTaxType,
|
opts.setSelectedTaxClass,
|
||||||
opts.taxTypes,
|
opts.taxClasses,
|
||||||
);
|
);
|
||||||
const changeMetadata = makeMetadataChangeHandler(handleChange);
|
const changeMetadata = makeMetadataChangeHandler(handleChange);
|
||||||
const handleChannelsChange = createChannelsChangeHandler(
|
const handleChannelsChange = createChannelsChangeHandler(
|
||||||
|
@ -478,7 +474,7 @@ function useProductCreateForm(
|
||||||
selectCategory: handleCategorySelect,
|
selectCategory: handleCategorySelect,
|
||||||
selectCollection: handleCollectionSelect,
|
selectCollection: handleCollectionSelect,
|
||||||
selectProductType: handleProductTypeSelect,
|
selectProductType: handleProductTypeSelect,
|
||||||
selectTaxRate: handleTaxTypeSelect,
|
selectTaxClass: handleTaxClassSelect,
|
||||||
},
|
},
|
||||||
submit,
|
submit,
|
||||||
isSaveDisabled,
|
isSaveDisabled,
|
||||||
|
|
|
@ -1,114 +1,70 @@
|
||||||
import { Card, CardContent } from "@material-ui/core";
|
import { Card, CardContent } from "@material-ui/core";
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
import ControlledCheckbox from "@saleor/components/ControlledCheckbox";
|
|
||||||
import Hr from "@saleor/components/Hr";
|
|
||||||
import SingleAutocompleteSelectField from "@saleor/components/SingleAutocompleteSelectField";
|
import SingleAutocompleteSelectField from "@saleor/components/SingleAutocompleteSelectField";
|
||||||
import { TaxTypeFragment } from "@saleor/graphql";
|
import { TaxClassFragment } from "@saleor/graphql";
|
||||||
import { FormChange } from "@saleor/hooks/useForm";
|
|
||||||
import { sectionNames } from "@saleor/intl";
|
import { sectionNames } from "@saleor/intl";
|
||||||
import { makeStyles } from "@saleor/macaw-ui";
|
import { makeStyles } from "@saleor/macaw-ui";
|
||||||
|
import { taxesMessages } from "@saleor/taxes/messages";
|
||||||
|
import { FetchMoreProps } from "@saleor/types";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
export interface ProductTaxesProps {
|
import { ProductCreateFormData } from "../ProductCreatePage";
|
||||||
data: {
|
|
||||||
changeTaxCode: boolean;
|
interface ProductTaxesProps {
|
||||||
chargeTaxes: boolean;
|
value: string;
|
||||||
taxCode: string;
|
taxClassDisplayName: string;
|
||||||
};
|
taxClasses: Array<Omit<TaxClassFragment, "countries">>;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
selectedTaxTypeDisplayName: string;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
taxTypes: TaxTypeFragment[];
|
onFetchMore: FetchMoreProps;
|
||||||
onChange: FormChange;
|
|
||||||
onTaxTypeChange: FormChange;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const useStyles = makeStyles(
|
const useStyles = makeStyles(
|
||||||
theme => ({
|
|
||||||
content: {
|
|
||||||
paddingTop: theme.spacing(2),
|
|
||||||
},
|
|
||||||
hr: {
|
|
||||||
margin: theme.spacing(2, 0),
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
margin: theme.spacing(2, 0),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
{
|
{
|
||||||
name: "ProductTaxes",
|
root: {
|
||||||
|
overflow: "visible",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
{ name: "ProductTaxes" },
|
||||||
);
|
);
|
||||||
|
|
||||||
const ProductTaxes: React.FC<ProductTaxesProps> = ({
|
const ProductTaxes: React.FC<ProductTaxesProps> = props => {
|
||||||
data,
|
const {
|
||||||
disabled,
|
value,
|
||||||
selectedTaxTypeDisplayName,
|
disabled,
|
||||||
taxTypes,
|
taxClasses,
|
||||||
onChange,
|
taxClassDisplayName,
|
||||||
onTaxTypeChange,
|
onChange,
|
||||||
}) => {
|
onFetchMore,
|
||||||
|
} = props;
|
||||||
|
const classes = useStyles(props);
|
||||||
|
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const classes = useStyles({});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card className={classes.root}>
|
||||||
<CardTitle title={intl.formatMessage(sectionNames.taxes)} />
|
<CardTitle title={intl.formatMessage(sectionNames.taxes)} />
|
||||||
<CardContent className={classes.content}>
|
<CardContent>
|
||||||
<ControlledCheckbox
|
<SingleAutocompleteSelectField
|
||||||
checked={data.changeTaxCode}
|
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
data-test-id="override-tax-type"
|
displayValue={taxClassDisplayName}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage(taxesMessages.taxClass)}
|
||||||
id: "iYH3Y7",
|
name={"taxClassId" as keyof ProductCreateFormData}
|
||||||
defaultMessage: "Override the product type's tax rate",
|
|
||||||
description: "checkbox",
|
|
||||||
})}
|
|
||||||
name="changeTaxCode"
|
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
|
value={value}
|
||||||
|
choices={taxClasses.map(choice => ({
|
||||||
|
label: choice.name,
|
||||||
|
value: choice.id,
|
||||||
|
}))}
|
||||||
|
InputProps={{
|
||||||
|
autoComplete: "off",
|
||||||
|
}}
|
||||||
|
{...onFetchMore}
|
||||||
/>
|
/>
|
||||||
<Hr className={classes.hr} />
|
|
||||||
<ControlledCheckbox
|
|
||||||
checked={data.chargeTaxes}
|
|
||||||
disabled={disabled}
|
|
||||||
data-test-id="charge-taxes"
|
|
||||||
label={intl.formatMessage({
|
|
||||||
id: "TfY/Pi",
|
|
||||||
defaultMessage: "Charge taxes on this product",
|
|
||||||
description: "checkbox",
|
|
||||||
})}
|
|
||||||
name="chargeTaxes"
|
|
||||||
onChange={onChange}
|
|
||||||
/>
|
|
||||||
{data.changeTaxCode && (
|
|
||||||
<SingleAutocompleteSelectField
|
|
||||||
className={classes.select}
|
|
||||||
disabled={disabled}
|
|
||||||
displayValue={selectedTaxTypeDisplayName}
|
|
||||||
data-test-id="select-tax-type"
|
|
||||||
label={intl.formatMessage({
|
|
||||||
id: "CdIHMu",
|
|
||||||
defaultMessage: "Tax Rate",
|
|
||||||
description: "select tax ratte",
|
|
||||||
})}
|
|
||||||
name="taxCode"
|
|
||||||
onChange={onTaxTypeChange}
|
|
||||||
value={data.taxCode}
|
|
||||||
choices={
|
|
||||||
taxTypes?.map(taxType => ({
|
|
||||||
label: taxType.description,
|
|
||||||
value: taxType.taxCode,
|
|
||||||
})) || []
|
|
||||||
}
|
|
||||||
InputProps={{
|
|
||||||
autoComplete: "off",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
ProductTaxes.displayName = "ProductTaxes";
|
ProductTaxes.displayName = "ProductTaxes";
|
||||||
export default ProductTaxes;
|
export default ProductTaxes;
|
||||||
|
|
|
@ -3,7 +3,6 @@ import { channelsList } from "@saleor/channels/fixtures";
|
||||||
import { collections } from "@saleor/collections/fixtures";
|
import { collections } from "@saleor/collections/fixtures";
|
||||||
import { fetchMoreProps, limits } from "@saleor/fixtures";
|
import { fetchMoreProps, limits } from "@saleor/fixtures";
|
||||||
import { product as productFixture } from "@saleor/products/fixtures";
|
import { product as productFixture } from "@saleor/products/fixtures";
|
||||||
import { taxTypes } from "@saleor/storybook/stories/taxes/fixtures";
|
|
||||||
import { warehouseList } from "@saleor/warehouses/fixtures";
|
import { warehouseList } from "@saleor/warehouses/fixtures";
|
||||||
import Wrapper from "@test/wrapper";
|
import Wrapper from "@test/wrapper";
|
||||||
import { configure, mount } from "enzyme";
|
import { configure, mount } from "enzyme";
|
||||||
|
@ -14,6 +13,7 @@ import ProductUpdatePage, { ProductUpdatePageProps } from "./ProductUpdatePage";
|
||||||
const product = productFixture(placeholderImage);
|
const product = productFixture(placeholderImage);
|
||||||
|
|
||||||
import * as _useNavigator from "@saleor/hooks/useNavigator";
|
import * as _useNavigator from "@saleor/hooks/useNavigator";
|
||||||
|
import { taxClasses } from "@saleor/taxes/fixtures";
|
||||||
import Adapter from "@wojtekmaj/enzyme-adapter-react-17";
|
import Adapter from "@wojtekmaj/enzyme-adapter-react-17";
|
||||||
import { act } from "react-dom/test-utils";
|
import { act } from "react-dom/test-utils";
|
||||||
import { MemoryRouter } from "react-router-dom";
|
import { MemoryRouter } from "react-router-dom";
|
||||||
|
@ -82,7 +82,8 @@ const props: ProductUpdatePageProps = {
|
||||||
referencePages: [],
|
referencePages: [],
|
||||||
referenceProducts: [],
|
referenceProducts: [],
|
||||||
saveButtonBarState: "default",
|
saveButtonBarState: "default",
|
||||||
taxTypes,
|
taxClasses,
|
||||||
|
fetchMoreTaxClasses: undefined,
|
||||||
variants: product.variants,
|
variants: product.variants,
|
||||||
warehouses: warehouseList,
|
warehouses: warehouseList,
|
||||||
attributeValues: [],
|
attributeValues: [],
|
||||||
|
|
|
@ -35,7 +35,7 @@ import {
|
||||||
SearchCollectionsQuery,
|
SearchCollectionsQuery,
|
||||||
SearchPagesQuery,
|
SearchPagesQuery,
|
||||||
SearchProductsQuery,
|
SearchProductsQuery,
|
||||||
TaxTypeFragment,
|
TaxClassFragment,
|
||||||
WarehouseFragment,
|
WarehouseFragment,
|
||||||
} from "@saleor/graphql";
|
} from "@saleor/graphql";
|
||||||
import { SubmitPromise } from "@saleor/hooks/useForm";
|
import { SubmitPromise } from "@saleor/hooks/useForm";
|
||||||
|
@ -89,7 +89,8 @@ export interface ProductUpdatePageProps {
|
||||||
header: string;
|
header: string;
|
||||||
saveButtonBarState: ConfirmButtonTransitionState;
|
saveButtonBarState: ConfirmButtonTransitionState;
|
||||||
warehouses: WarehouseFragment[];
|
warehouses: WarehouseFragment[];
|
||||||
taxTypes: TaxTypeFragment[];
|
taxClasses: Array<Omit<TaxClassFragment, "countries">>;
|
||||||
|
fetchMoreTaxClasses: FetchMoreProps;
|
||||||
referencePages?: RelayToFlat<SearchPagesQuery["search"]>;
|
referencePages?: RelayToFlat<SearchPagesQuery["search"]>;
|
||||||
referenceProducts?: RelayToFlat<SearchProductsQuery["search"]>;
|
referenceProducts?: RelayToFlat<SearchProductsQuery["search"]>;
|
||||||
assignReferencesAttributeId?: string;
|
assignReferencesAttributeId?: string;
|
||||||
|
@ -143,7 +144,8 @@ export const ProductUpdatePage: React.FC<ProductUpdatePageProps> = ({
|
||||||
saveButtonBarState,
|
saveButtonBarState,
|
||||||
variants,
|
variants,
|
||||||
warehouses,
|
warehouses,
|
||||||
taxTypes,
|
taxClasses,
|
||||||
|
fetchMoreTaxClasses,
|
||||||
referencePages = [],
|
referencePages = [],
|
||||||
referenceProducts = [],
|
referenceProducts = [],
|
||||||
onDelete,
|
onDelete,
|
||||||
|
@ -184,17 +186,17 @@ export const ProductUpdatePage: React.FC<ProductUpdatePageProps> = ({
|
||||||
getChoices(maybe(() => product.collections, [])),
|
getChoices(maybe(() => product.collections, [])),
|
||||||
);
|
);
|
||||||
|
|
||||||
const [selectedTaxType, setSelectedTaxType] = useStateFromProps(
|
const [selectedTaxClass, setSelectedTaxClass] = useStateFromProps(
|
||||||
product?.taxType.description,
|
product?.taxClass?.name ?? "",
|
||||||
);
|
);
|
||||||
|
|
||||||
const categories = getChoices(categoryChoiceList);
|
const categories = getChoices(categoryChoiceList);
|
||||||
const collections = getChoices(collectionChoiceList);
|
const collections = getChoices(collectionChoiceList);
|
||||||
const hasVariants = product?.productType?.hasVariants;
|
const hasVariants = product?.productType?.hasVariants;
|
||||||
const taxTypeChoices =
|
const taxClassesChoices =
|
||||||
taxTypes?.map(taxType => ({
|
taxClasses?.map(taxClass => ({
|
||||||
label: taxType.description,
|
label: taxClass.name,
|
||||||
value: taxType.taxCode,
|
value: taxClass.id,
|
||||||
})) || [];
|
})) || [];
|
||||||
|
|
||||||
const canOpenAssignReferencesAttributeDialog = !!assignReferencesAttributeId;
|
const canOpenAssignReferencesAttributeDialog = !!assignReferencesAttributeId;
|
||||||
|
@ -250,8 +252,8 @@ export const ProductUpdatePage: React.FC<ProductUpdatePageProps> = ({
|
||||||
selectedCollections={selectedCollections}
|
selectedCollections={selectedCollections}
|
||||||
setSelectedCategory={setSelectedCategory}
|
setSelectedCategory={setSelectedCategory}
|
||||||
setSelectedCollections={setSelectedCollections}
|
setSelectedCollections={setSelectedCollections}
|
||||||
setSelectedTaxType={setSelectedTaxType}
|
setSelectedTaxClass={setSelectedTaxClass}
|
||||||
taxTypes={taxTypeChoices}
|
taxClasses={taxClassesChoices}
|
||||||
warehouses={warehouses}
|
warehouses={warehouses}
|
||||||
hasVariants={hasVariants}
|
hasVariants={hasVariants}
|
||||||
referencePages={referencePages}
|
referencePages={referencePages}
|
||||||
|
@ -420,12 +422,12 @@ export const ProductUpdatePage: React.FC<ProductUpdatePageProps> = ({
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
<ProductTaxes
|
<ProductTaxes
|
||||||
data={data}
|
value={data.taxClassId}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
selectedTaxTypeDisplayName={selectedTaxType}
|
onChange={handlers.selectTaxClass}
|
||||||
taxTypes={taxTypes}
|
taxClassDisplayName={selectedTaxClass}
|
||||||
onChange={change}
|
taxClasses={taxClasses}
|
||||||
onTaxTypeChange={handlers.selectTaxRate}
|
onFetchMore={fetchMoreTaxClasses}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
|
@ -163,10 +163,10 @@ function useProductUpdateForm(
|
||||||
attributes.data,
|
attributes.data,
|
||||||
triggerChange,
|
triggerChange,
|
||||||
);
|
);
|
||||||
const handleTaxTypeSelect = createSingleAutocompleteSelectHandler(
|
const handleTaxClassSelect = createSingleAutocompleteSelectHandler(
|
||||||
handleChange,
|
handleChange,
|
||||||
opts.setSelectedTaxType,
|
opts.setSelectedTaxClass,
|
||||||
opts.taxTypes,
|
opts.taxClasses,
|
||||||
);
|
);
|
||||||
const changeMetadata = makeMetadataChangeHandler(handleChange);
|
const changeMetadata = makeMetadataChangeHandler(handleChange);
|
||||||
|
|
||||||
|
@ -295,7 +295,7 @@ function useProductUpdateForm(
|
||||||
selectAttributeReference: handleAttributeReferenceChange,
|
selectAttributeReference: handleAttributeReferenceChange,
|
||||||
selectCategory: handleCategorySelect,
|
selectCategory: handleCategorySelect,
|
||||||
selectCollection: handleCollectionSelect,
|
selectCollection: handleCollectionSelect,
|
||||||
selectTaxRate: handleTaxTypeSelect,
|
selectTaxClass: handleTaxClassSelect,
|
||||||
updateChannelList: handleChannelListUpdate,
|
updateChannelList: handleChannelListUpdate,
|
||||||
},
|
},
|
||||||
submit,
|
submit,
|
||||||
|
|
|
@ -35,8 +35,7 @@ import { ProductChannelsListingDialogSubmit } from "./ProductChannelsListingsDia
|
||||||
|
|
||||||
export interface ProductUpdateFormData extends MetadataFormData {
|
export interface ProductUpdateFormData extends MetadataFormData {
|
||||||
category: string | null;
|
category: string | null;
|
||||||
changeTaxCode: boolean;
|
taxClassId: string;
|
||||||
chargeTaxes: boolean;
|
|
||||||
collections: string[];
|
collections: string[];
|
||||||
isAvailable: boolean;
|
isAvailable: boolean;
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -45,7 +44,6 @@ export interface ProductUpdateFormData extends MetadataFormData {
|
||||||
seoDescription: string;
|
seoDescription: string;
|
||||||
seoTitle: string;
|
seoTitle: string;
|
||||||
sku: string;
|
sku: string;
|
||||||
taxCode: string;
|
|
||||||
trackInventory: boolean;
|
trackInventory: boolean;
|
||||||
isPreorder: boolean;
|
isPreorder: boolean;
|
||||||
globalThreshold: string;
|
globalThreshold: string;
|
||||||
|
@ -85,7 +83,7 @@ export interface ProductUpdateHandlers
|
||||||
| "changeMetadata"
|
| "changeMetadata"
|
||||||
| "selectCategory"
|
| "selectCategory"
|
||||||
| "selectCollection"
|
| "selectCollection"
|
||||||
| "selectTaxRate",
|
| "selectTaxClass",
|
||||||
FormChange
|
FormChange
|
||||||
>,
|
>,
|
||||||
Record<
|
Record<
|
||||||
|
@ -119,14 +117,14 @@ export type UseProductUpdateFormRenderProps = Omit<
|
||||||
|
|
||||||
export interface UseProductUpdateFormOpts
|
export interface UseProductUpdateFormOpts
|
||||||
extends Record<
|
extends Record<
|
||||||
"categories" | "collections" | "taxTypes",
|
"categories" | "collections" | "taxClasses",
|
||||||
SingleAutocompleteChoiceType[]
|
SingleAutocompleteChoiceType[]
|
||||||
> {
|
> {
|
||||||
setSelectedCategory: React.Dispatch<React.SetStateAction<string>>;
|
setSelectedCategory: React.Dispatch<React.SetStateAction<string>>;
|
||||||
setSelectedCollections: React.Dispatch<
|
setSelectedCollections: React.Dispatch<
|
||||||
React.SetStateAction<MultiAutocompleteChoiceType[]>
|
React.SetStateAction<MultiAutocompleteChoiceType[]>
|
||||||
>;
|
>;
|
||||||
setSelectedTaxType: React.Dispatch<React.SetStateAction<string>>;
|
setSelectedTaxClass: React.Dispatch<React.SetStateAction<string>>;
|
||||||
selectedCollections: MultiAutocompleteChoiceType[];
|
selectedCollections: MultiAutocompleteChoiceType[];
|
||||||
warehouses: RelayToFlat<SearchWarehousesQuery["search"]>;
|
warehouses: RelayToFlat<SearchWarehousesQuery["search"]>;
|
||||||
hasVariants: boolean;
|
hasVariants: boolean;
|
||||||
|
|
|
@ -464,10 +464,10 @@ export const product: (
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
taxType: {
|
taxClass: {
|
||||||
__typename: "TaxType",
|
__typename: "TaxClass",
|
||||||
description: "standard",
|
name: "standard",
|
||||||
taxCode: "standard",
|
id: "standard",
|
||||||
},
|
},
|
||||||
variantAttributes: [
|
variantAttributes: [
|
||||||
{
|
{
|
||||||
|
@ -591,10 +591,10 @@ export const product: (
|
||||||
seoTitle: "Seo title",
|
seoTitle: "Seo title",
|
||||||
sku: "59661-34207",
|
sku: "59661-34207",
|
||||||
slug: "Borders",
|
slug: "Borders",
|
||||||
taxType: {
|
taxClass: {
|
||||||
__typename: "TaxType",
|
__typename: "TaxClass",
|
||||||
description: "standard",
|
name: "standard",
|
||||||
taxCode: "standard",
|
id: "standard",
|
||||||
},
|
},
|
||||||
thumbnail: { __typename: "Image" as "Image", url: placeholderImage },
|
thumbnail: { __typename: "Image" as "Image", url: placeholderImage },
|
||||||
url: "/example-url",
|
url: "/example-url",
|
||||||
|
|
|
@ -114,9 +114,6 @@ export const productDetailsQuery = gql`
|
||||||
product(id: $id, channel: $channel) {
|
product(id: $id, channel: $channel) {
|
||||||
...Product
|
...Product
|
||||||
}
|
}
|
||||||
taxTypes {
|
|
||||||
...TaxType
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -149,8 +146,9 @@ export const productTypeQuery = gql`
|
||||||
...AttributeValueList
|
...AttributeValueList
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
taxType {
|
taxClass {
|
||||||
...TaxType
|
id
|
||||||
|
name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,8 +201,7 @@ export function getProductUpdatePageFormData(
|
||||||
|
|
||||||
return {
|
return {
|
||||||
category: maybe(() => product.category.id, ""),
|
category: maybe(() => product.category.id, ""),
|
||||||
changeTaxCode: !!product?.taxType.taxCode,
|
taxClassId: product?.taxClass?.id,
|
||||||
chargeTaxes: maybe(() => product.chargeTaxes, false),
|
|
||||||
collections: maybe(
|
collections: maybe(
|
||||||
() => product.collections.map(collection => collection.id),
|
() => product.collections.map(collection => collection.id),
|
||||||
[],
|
[],
|
||||||
|
@ -224,7 +223,6 @@ export function getProductUpdatePageFormData(
|
||||||
"",
|
"",
|
||||||
),
|
),
|
||||||
slug: product?.slug || "",
|
slug: product?.slug || "",
|
||||||
taxCode: product?.taxType.taxCode,
|
|
||||||
trackInventory: !!variant?.trackInventory,
|
trackInventory: !!variant?.trackInventory,
|
||||||
weight: product?.weight?.value.toString() || "",
|
weight: product?.weight?.value.toString() || "",
|
||||||
isPreorder: !!variant?.preorder || false,
|
isPreorder: !!variant?.preorder || false,
|
||||||
|
|
|
@ -16,7 +16,6 @@ import {
|
||||||
useProductDeleteMutation,
|
useProductDeleteMutation,
|
||||||
useProductTypeQuery,
|
useProductTypeQuery,
|
||||||
useProductVariantChannelListingUpdateMutation,
|
useProductVariantChannelListingUpdateMutation,
|
||||||
useTaxTypeListQuery,
|
|
||||||
useUpdateMetadataMutation,
|
useUpdateMetadataMutation,
|
||||||
useUpdatePrivateMetadataMutation,
|
useUpdatePrivateMetadataMutation,
|
||||||
useVariantCreateMutation,
|
useVariantCreateMutation,
|
||||||
|
@ -41,6 +40,7 @@ import useCollectionSearch from "@saleor/searches/useCollectionSearch";
|
||||||
import usePageSearch from "@saleor/searches/usePageSearch";
|
import usePageSearch from "@saleor/searches/usePageSearch";
|
||||||
import useProductSearch from "@saleor/searches/useProductSearch";
|
import useProductSearch from "@saleor/searches/useProductSearch";
|
||||||
import useProductTypeSearch from "@saleor/searches/useProductTypeSearch";
|
import useProductTypeSearch from "@saleor/searches/useProductTypeSearch";
|
||||||
|
import { useTaxClassFetchMore } from "@saleor/taxes/utils/useTaxClassFetchMore";
|
||||||
import { getProductErrorMessage } from "@saleor/utils/errors";
|
import { getProductErrorMessage } from "@saleor/utils/errors";
|
||||||
import useAttributeValueSearchHandler from "@saleor/utils/handlers/attributeValueSearchHandler";
|
import useAttributeValueSearchHandler from "@saleor/utils/handlers/attributeValueSearchHandler";
|
||||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||||
|
@ -123,7 +123,7 @@ export const ProductCreateView: React.FC<ProductCreateProps> = ({ params }) => {
|
||||||
} = useAttributeValueSearchHandler(DEFAULT_INITIAL_SEARCH_DATA);
|
} = useAttributeValueSearchHandler(DEFAULT_INITIAL_SEARCH_DATA);
|
||||||
const [updateMetadata] = useUpdateMetadataMutation({});
|
const [updateMetadata] = useUpdateMetadataMutation({});
|
||||||
const [updatePrivateMetadata] = useUpdatePrivateMetadataMutation({});
|
const [updatePrivateMetadata] = useUpdatePrivateMetadataMutation({});
|
||||||
const taxTypes = useTaxTypeListQuery({});
|
const { taxClasses, fetchMoreTaxClasses } = useTaxClassFetchMore();
|
||||||
const { data: selectedProductType } = useProductTypeQuery({
|
const { data: selectedProductType } = useProductTypeQuery({
|
||||||
variables: {
|
variables: {
|
||||||
id: selectedProductTypeId,
|
id: selectedProductTypeId,
|
||||||
|
@ -355,7 +355,8 @@ export const ProductCreateView: React.FC<ProductCreateProps> = ({ params }) => {
|
||||||
fetchMoreCollections={fetchMoreCollections}
|
fetchMoreCollections={fetchMoreCollections}
|
||||||
fetchMoreProductTypes={fetchMoreProductTypes}
|
fetchMoreProductTypes={fetchMoreProductTypes}
|
||||||
warehouses={mapEdgesToItems(warehouses?.data?.warehouses) || []}
|
warehouses={mapEdgesToItems(warehouses?.data?.warehouses) || []}
|
||||||
taxTypes={taxTypes.data?.taxTypes || []}
|
taxClasses={taxClasses ?? []}
|
||||||
|
fetchMoreTaxClasses={fetchMoreTaxClasses}
|
||||||
weightUnit={shop?.defaultWeightUnit}
|
weightUnit={shop?.defaultWeightUnit}
|
||||||
openChannelsModal={handleChannelsModalOpen}
|
openChannelsModal={handleChannelsModalOpen}
|
||||||
onChannelsChange={setCurrentChannels}
|
onChannelsChange={setCurrentChannels}
|
||||||
|
|
|
@ -113,7 +113,6 @@ export function createHandler(
|
||||||
updatedFileAttributes,
|
updatedFileAttributes,
|
||||||
}),
|
}),
|
||||||
category: formData.category,
|
category: formData.category,
|
||||||
chargeTaxes: formData.chargeTaxes,
|
|
||||||
collections: formData.collections,
|
collections: formData.collections,
|
||||||
description: getParsedDataForJsonStringField(formData.description),
|
description: getParsedDataForJsonStringField(formData.description),
|
||||||
name: formData.name,
|
name: formData.name,
|
||||||
|
@ -124,7 +123,7 @@ export function createHandler(
|
||||||
title: formData.seoTitle,
|
title: formData.seoTitle,
|
||||||
},
|
},
|
||||||
slug: formData.slug,
|
slug: formData.slug,
|
||||||
taxCode: formData.changeTaxCode ? formData.taxCode : undefined,
|
taxClass: formData.taxClassId,
|
||||||
weight: weight(formData.weight),
|
weight: weight(formData.weight),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,12 +28,13 @@ import useCategorySearch from "@saleor/searches/useCategorySearch";
|
||||||
import useCollectionSearch from "@saleor/searches/useCollectionSearch";
|
import useCollectionSearch from "@saleor/searches/useCollectionSearch";
|
||||||
import usePageSearch from "@saleor/searches/usePageSearch";
|
import usePageSearch from "@saleor/searches/usePageSearch";
|
||||||
import useProductSearch from "@saleor/searches/useProductSearch";
|
import useProductSearch from "@saleor/searches/useProductSearch";
|
||||||
|
import { useTaxClassFetchMore } from "@saleor/taxes/utils/useTaxClassFetchMore";
|
||||||
import { getProductErrorMessage } from "@saleor/utils/errors";
|
import { getProductErrorMessage } from "@saleor/utils/errors";
|
||||||
import useAttributeValueSearchHandler from "@saleor/utils/handlers/attributeValueSearchHandler";
|
import useAttributeValueSearchHandler from "@saleor/utils/handlers/attributeValueSearchHandler";
|
||||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||||
import { mapEdgesToItems } from "@saleor/utils/maps";
|
import { mapEdgesToItems } from "@saleor/utils/maps";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { defineMessages, FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
import { getMutationState } from "../../../misc";
|
import { getMutationState } from "../../../misc";
|
||||||
import ProductUpdatePage from "../../components/ProductUpdatePage";
|
import ProductUpdatePage from "../../components/ProductUpdatePage";
|
||||||
|
@ -49,30 +50,7 @@ import {
|
||||||
createImageUploadHandler,
|
createImageUploadHandler,
|
||||||
} from "./handlers";
|
} from "./handlers";
|
||||||
import { useProductUpdateHandler } from "./handlers/useProductUpdateHandler";
|
import { useProductUpdateHandler } from "./handlers/useProductUpdateHandler";
|
||||||
|
import { productUpdatePageMessages as messages } from "./messages";
|
||||||
const messages = defineMessages({
|
|
||||||
deleteProductDialogTitle: {
|
|
||||||
id: "TWVx7O",
|
|
||||||
defaultMessage: "Delete Product",
|
|
||||||
description: "delete product dialog title",
|
|
||||||
},
|
|
||||||
deleteProductDialogSubtitle: {
|
|
||||||
id: "ZHF4Z9",
|
|
||||||
defaultMessage: "Are you sure you want to delete {name}?",
|
|
||||||
description: "delete product dialog subtitle",
|
|
||||||
},
|
|
||||||
deleteVariantDialogTitle: {
|
|
||||||
id: "6iw4VR",
|
|
||||||
defaultMessage: "Delete Product Variants",
|
|
||||||
description: "delete variant dialog title",
|
|
||||||
},
|
|
||||||
deleteVariantDialogSubtitle: {
|
|
||||||
id: "ukdRUv",
|
|
||||||
defaultMessage:
|
|
||||||
"{counter,plural,one{Are you sure you want to delete this variant?} other{Are you sure you want to delete {displayQuantity} variants?}}",
|
|
||||||
description: "delete variant dialog subtitle",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
interface ProductUpdateProps {
|
interface ProductUpdateProps {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -310,6 +288,8 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
|
||||||
onFetchMore: loadMoreAttributeValues,
|
onFetchMore: loadMoreAttributeValues,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const { taxClasses, fetchMoreTaxClasses } = useTaxClassFetchMore();
|
||||||
|
|
||||||
if (product === null) {
|
if (product === null) {
|
||||||
return <NotFoundPage onBack={handleBack} />;
|
return <NotFoundPage onBack={handleBack} />;
|
||||||
}
|
}
|
||||||
|
@ -339,7 +319,8 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
|
||||||
placeholderImage={placeholderImg}
|
placeholderImage={placeholderImg}
|
||||||
product={product}
|
product={product}
|
||||||
warehouses={warehouses}
|
warehouses={warehouses}
|
||||||
taxTypes={data?.taxTypes}
|
taxClasses={taxClasses ?? []}
|
||||||
|
fetchMoreTaxClasses={fetchMoreTaxClasses}
|
||||||
variants={product?.variants}
|
variants={product?.variants}
|
||||||
onDelete={() => openModal("remove")}
|
onDelete={() => openModal("remove")}
|
||||||
onImageReorder={handleImageReorder}
|
onImageReorder={handleImageReorder}
|
||||||
|
|
|
@ -34,7 +34,6 @@ export function getProductUpdateVariables(
|
||||||
updatedFileAttributes,
|
updatedFileAttributes,
|
||||||
}),
|
}),
|
||||||
category: data.category,
|
category: data.category,
|
||||||
chargeTaxes: data.chargeTaxes,
|
|
||||||
collections: data.collections,
|
collections: data.collections,
|
||||||
description: getParsedDataForJsonStringField(data.description),
|
description: getParsedDataForJsonStringField(data.description),
|
||||||
name: data.name,
|
name: data.name,
|
||||||
|
@ -44,7 +43,7 @@ export function getProductUpdateVariables(
|
||||||
title: data.seoTitle,
|
title: data.seoTitle,
|
||||||
},
|
},
|
||||||
slug: data.slug,
|
slug: data.slug,
|
||||||
taxCode: data.changeTaxCode ? data.taxCode : null,
|
taxClass: data.taxClassId,
|
||||||
},
|
},
|
||||||
firstValues: VALUES_PAGINATE_BY,
|
firstValues: VALUES_PAGINATE_BY,
|
||||||
};
|
};
|
||||||
|
|
25
src/products/views/ProductUpdate/messages.ts
Normal file
25
src/products/views/ProductUpdate/messages.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { defineMessages } from "react-intl";
|
||||||
|
|
||||||
|
export const productUpdatePageMessages = defineMessages({
|
||||||
|
deleteProductDialogTitle: {
|
||||||
|
id: "TWVx7O",
|
||||||
|
defaultMessage: "Delete Product",
|
||||||
|
description: "delete product dialog title",
|
||||||
|
},
|
||||||
|
deleteProductDialogSubtitle: {
|
||||||
|
id: "ZHF4Z9",
|
||||||
|
defaultMessage: "Are you sure you want to delete {name}?",
|
||||||
|
description: "delete product dialog subtitle",
|
||||||
|
},
|
||||||
|
deleteVariantDialogTitle: {
|
||||||
|
id: "6iw4VR",
|
||||||
|
defaultMessage: "Delete Product Variants",
|
||||||
|
description: "delete variant dialog title",
|
||||||
|
},
|
||||||
|
deleteVariantDialogSubtitle: {
|
||||||
|
id: "ukdRUv",
|
||||||
|
defaultMessage:
|
||||||
|
"{counter,plural,one{Are you sure you want to delete this variant?} other{Are you sure you want to delete {displayQuantity} variants?}}",
|
||||||
|
description: "delete variant dialog subtitle",
|
||||||
|
},
|
||||||
|
});
|
|
@ -0,0 +1,71 @@
|
||||||
|
import { Card, CardContent } from "@material-ui/core";
|
||||||
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
|
import SingleAutocompleteSelectField from "@saleor/components/SingleAutocompleteSelectField";
|
||||||
|
import { TaxClassFragment } from "@saleor/graphql";
|
||||||
|
import { sectionNames } from "@saleor/intl";
|
||||||
|
import { makeStyles } from "@saleor/macaw-ui";
|
||||||
|
import { taxesMessages } from "@saleor/taxes/messages";
|
||||||
|
import { FetchMoreProps } from "@saleor/types";
|
||||||
|
import React from "react";
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import { ShippingZoneRateUpdateFormData } from "../ShippingZoneRatesPage/types";
|
||||||
|
|
||||||
|
interface ShippingMethodTaxesProps {
|
||||||
|
value: string;
|
||||||
|
taxClassDisplayName: string;
|
||||||
|
taxClasses: Array<Omit<TaxClassFragment, "countries">>;
|
||||||
|
disabled: boolean;
|
||||||
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
|
onFetchMore: FetchMoreProps;
|
||||||
|
}
|
||||||
|
|
||||||
|
const useStyles = makeStyles(
|
||||||
|
{
|
||||||
|
root: {
|
||||||
|
overflow: "visible",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ name: "ShippingMethodTaxes" },
|
||||||
|
);
|
||||||
|
|
||||||
|
const ShippingMethodTaxes: React.FC<ShippingMethodTaxesProps> = props => {
|
||||||
|
const {
|
||||||
|
value,
|
||||||
|
disabled,
|
||||||
|
taxClasses,
|
||||||
|
taxClassDisplayName,
|
||||||
|
onChange,
|
||||||
|
onFetchMore,
|
||||||
|
} = props;
|
||||||
|
const classes = useStyles(props);
|
||||||
|
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card className={classes.root}>
|
||||||
|
<CardTitle title={intl.formatMessage(sectionNames.taxes)} />
|
||||||
|
<CardContent>
|
||||||
|
<SingleAutocompleteSelectField
|
||||||
|
emptyOption
|
||||||
|
disabled={disabled}
|
||||||
|
displayValue={taxClassDisplayName}
|
||||||
|
label={intl.formatMessage(taxesMessages.taxClass)}
|
||||||
|
name={"taxClassId" as keyof ShippingZoneRateUpdateFormData}
|
||||||
|
onChange={onChange}
|
||||||
|
value={value}
|
||||||
|
choices={taxClasses.map(choice => ({
|
||||||
|
label: choice.name,
|
||||||
|
value: choice.id,
|
||||||
|
}))}
|
||||||
|
InputProps={{
|
||||||
|
autoComplete: "off",
|
||||||
|
}}
|
||||||
|
{...onFetchMore}
|
||||||
|
/>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
ShippingMethodTaxes.displayName = "ShippingMethodTaxes";
|
||||||
|
export default ShippingMethodTaxes;
|
2
src/shipping/components/ShippingMethodTaxes/index.ts
Normal file
2
src/shipping/components/ShippingMethodTaxes/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export { default } from "./ShippingMethodTaxes";
|
||||||
|
export * from "./ShippingMethodTaxes";
|
|
@ -3,6 +3,7 @@ import {
|
||||||
ShippingMethodTypeEnum,
|
ShippingMethodTypeEnum,
|
||||||
} from "@saleor/graphql";
|
} from "@saleor/graphql";
|
||||||
import Decorator from "@saleor/storybook//Decorator";
|
import Decorator from "@saleor/storybook//Decorator";
|
||||||
|
import { taxClasses } from "@saleor/taxes/fixtures";
|
||||||
import { storiesOf } from "@storybook/react";
|
import { storiesOf } from "@storybook/react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
|
@ -73,6 +74,8 @@ const props: ShippingZoneRatesCreatePageProps = {
|
||||||
saveButtonBarState: "default",
|
saveButtonBarState: "default",
|
||||||
shippingChannels: defaultChannels,
|
shippingChannels: defaultChannels,
|
||||||
variant: ShippingMethodTypeEnum.PRICE,
|
variant: ShippingMethodTypeEnum.PRICE,
|
||||||
|
taxClasses,
|
||||||
|
fetchMoreTaxClasses: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
storiesOf("Shipping / ShippingZoneRatesCreatePage page", module)
|
storiesOf("Shipping / ShippingZoneRatesCreatePage page", module)
|
||||||
|
|
|
@ -14,22 +14,26 @@ import {
|
||||||
ShippingErrorFragment,
|
ShippingErrorFragment,
|
||||||
ShippingMethodTypeEnum,
|
ShippingMethodTypeEnum,
|
||||||
ShippingMethodTypeFragment,
|
ShippingMethodTypeFragment,
|
||||||
|
TaxClassFragment,
|
||||||
} from "@saleor/graphql";
|
} from "@saleor/graphql";
|
||||||
import useForm, { SubmitPromise } from "@saleor/hooks/useForm";
|
import useForm, { SubmitPromise } from "@saleor/hooks/useForm";
|
||||||
import useHandleFormSubmit from "@saleor/hooks/useHandleFormSubmit";
|
import useHandleFormSubmit from "@saleor/hooks/useHandleFormSubmit";
|
||||||
import useNavigator from "@saleor/hooks/useNavigator";
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
import { ConfirmButtonTransitionState } from "@saleor/macaw-ui";
|
import { ConfirmButtonTransitionState } from "@saleor/macaw-ui";
|
||||||
import { validatePrice } from "@saleor/products/utils/validation";
|
import { validatePrice } from "@saleor/products/utils/validation";
|
||||||
|
import { handleTaxClassChange } from "@saleor/productTypes/handlers";
|
||||||
import OrderValue from "@saleor/shipping/components/OrderValue";
|
import OrderValue from "@saleor/shipping/components/OrderValue";
|
||||||
import OrderWeight from "@saleor/shipping/components/OrderWeight";
|
import OrderWeight from "@saleor/shipping/components/OrderWeight";
|
||||||
import PricingCard from "@saleor/shipping/components/PricingCard";
|
import PricingCard from "@saleor/shipping/components/PricingCard";
|
||||||
import ShippingRateInfo from "@saleor/shipping/components/ShippingRateInfo";
|
import ShippingRateInfo from "@saleor/shipping/components/ShippingRateInfo";
|
||||||
import { createChannelsChangeHandler } from "@saleor/shipping/handlers";
|
import { createChannelsChangeHandler } from "@saleor/shipping/handlers";
|
||||||
|
import { FetchMoreProps } from "@saleor/types";
|
||||||
import { RichTextContext } from "@saleor/utils/richText/context";
|
import { RichTextContext } from "@saleor/utils/richText/context";
|
||||||
import useRichText from "@saleor/utils/richText/useRichText";
|
import useRichText from "@saleor/utils/richText/useRichText";
|
||||||
import React, { FormEventHandler } from "react";
|
import React, { FormEventHandler } from "react";
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import ShippingMethodTaxes from "../ShippingMethodTaxes";
|
||||||
import ShippingZonePostalCodes from "../ShippingZonePostalCodes";
|
import ShippingZonePostalCodes from "../ShippingZonePostalCodes";
|
||||||
import { ShippingZoneRateCommonFormData } from "../ShippingZoneRatesPage/types";
|
import { ShippingZoneRateCommonFormData } from "../ShippingZoneRatesPage/types";
|
||||||
|
|
||||||
|
@ -52,6 +56,8 @@ export interface ShippingZoneRatesCreatePageProps extends WithFormId {
|
||||||
onChannelsChange: (data: ChannelShippingData[]) => void;
|
onChannelsChange: (data: ChannelShippingData[]) => void;
|
||||||
openChannelsModal: () => void;
|
openChannelsModal: () => void;
|
||||||
variant: ShippingMethodTypeEnum;
|
variant: ShippingMethodTypeEnum;
|
||||||
|
taxClasses: Array<Omit<TaxClassFragment, "countries">>;
|
||||||
|
fetchMoreTaxClasses: FetchMoreProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ShippingZoneRatesCreatePage: React.FC<ShippingZoneRatesCreatePageProps> = ({
|
export const ShippingZoneRatesCreatePage: React.FC<ShippingZoneRatesCreatePageProps> = ({
|
||||||
|
@ -72,6 +78,8 @@ export const ShippingZoneRatesCreatePage: React.FC<ShippingZoneRatesCreatePagePr
|
||||||
variant,
|
variant,
|
||||||
postalCodes,
|
postalCodes,
|
||||||
formId,
|
formId,
|
||||||
|
taxClasses,
|
||||||
|
fetchMoreTaxClasses,
|
||||||
}) => {
|
}) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const navigate = useNavigator();
|
const navigate = useNavigator();
|
||||||
|
@ -87,8 +95,11 @@ export const ShippingZoneRatesCreatePage: React.FC<ShippingZoneRatesCreatePagePr
|
||||||
description: null,
|
description: null,
|
||||||
orderValueRestricted: true,
|
orderValueRestricted: true,
|
||||||
type: null,
|
type: null,
|
||||||
|
taxClassId: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const [taxClassDisplayName, setTaxClassDisplayName] = React.useState("");
|
||||||
|
|
||||||
const {
|
const {
|
||||||
change,
|
change,
|
||||||
data: formData,
|
data: formData,
|
||||||
|
@ -207,6 +218,22 @@ export const ShippingZoneRatesCreatePage: React.FC<ShippingZoneRatesCreatePagePr
|
||||||
channelsList={data.channelListings}
|
channelsList={data.channelListings}
|
||||||
openModal={openChannelsModal}
|
openModal={openChannelsModal}
|
||||||
/>
|
/>
|
||||||
|
<CardSpacer />
|
||||||
|
<ShippingMethodTaxes
|
||||||
|
value={formData.taxClassId}
|
||||||
|
taxClassDisplayName={taxClassDisplayName}
|
||||||
|
taxClasses={taxClasses}
|
||||||
|
disabled={false}
|
||||||
|
onChange={event =>
|
||||||
|
handleTaxClassChange(
|
||||||
|
event,
|
||||||
|
taxClasses,
|
||||||
|
change,
|
||||||
|
setTaxClassDisplayName,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onFetchMore={fetchMoreTaxClasses}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Savebar
|
<Savebar
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { ShippingMethodTypeEnum } from "@saleor/graphql";
|
||||||
import { shippingZone } from "@saleor/shipping/fixtures";
|
import { shippingZone } from "@saleor/shipping/fixtures";
|
||||||
import Decorator from "@saleor/storybook//Decorator";
|
import Decorator from "@saleor/storybook//Decorator";
|
||||||
import { PaginatorContextDecorator } from "@saleor/storybook/PaginatorContextDecorator";
|
import { PaginatorContextDecorator } from "@saleor/storybook/PaginatorContextDecorator";
|
||||||
|
import { taxClasses } from "@saleor/taxes/fixtures";
|
||||||
import { storiesOf } from "@storybook/react";
|
import { storiesOf } from "@storybook/react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
|
@ -65,6 +66,8 @@ const props: ShippingZoneRatesPageProps = {
|
||||||
toolbar: () => undefined,
|
toolbar: () => undefined,
|
||||||
variant: ShippingMethodTypeEnum.PRICE,
|
variant: ShippingMethodTypeEnum.PRICE,
|
||||||
formId: Symbol(),
|
formId: Symbol(),
|
||||||
|
taxClasses,
|
||||||
|
fetchMoreTaxClasses: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
storiesOf("Views / Shipping / Shipping rate", module)
|
storiesOf("Views / Shipping / Shipping rate", module)
|
||||||
|
|
|
@ -16,19 +16,22 @@ import {
|
||||||
ShippingMethodTypeEnum,
|
ShippingMethodTypeEnum,
|
||||||
ShippingMethodTypeFragment,
|
ShippingMethodTypeFragment,
|
||||||
ShippingZoneQuery,
|
ShippingZoneQuery,
|
||||||
|
TaxClassFragment,
|
||||||
} from "@saleor/graphql";
|
} from "@saleor/graphql";
|
||||||
import useForm, { SubmitPromise } from "@saleor/hooks/useForm";
|
import useForm, { SubmitPromise } from "@saleor/hooks/useForm";
|
||||||
import useHandleFormSubmit from "@saleor/hooks/useHandleFormSubmit";
|
import useHandleFormSubmit from "@saleor/hooks/useHandleFormSubmit";
|
||||||
import useNavigator from "@saleor/hooks/useNavigator";
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
|
import { useStateUpdate } from "@saleor/hooks/useStateUpdate";
|
||||||
import { ConfirmButtonTransitionState } from "@saleor/macaw-ui";
|
import { ConfirmButtonTransitionState } from "@saleor/macaw-ui";
|
||||||
import { validatePrice } from "@saleor/products/utils/validation";
|
import { validatePrice } from "@saleor/products/utils/validation";
|
||||||
|
import { handleTaxClassChange } from "@saleor/productTypes/handlers";
|
||||||
import OrderValue from "@saleor/shipping/components/OrderValue";
|
import OrderValue from "@saleor/shipping/components/OrderValue";
|
||||||
import OrderWeight from "@saleor/shipping/components/OrderWeight";
|
import OrderWeight from "@saleor/shipping/components/OrderWeight";
|
||||||
import PricingCard from "@saleor/shipping/components/PricingCard";
|
import PricingCard from "@saleor/shipping/components/PricingCard";
|
||||||
import ShippingMethodProducts from "@saleor/shipping/components/ShippingMethodProducts";
|
import ShippingMethodProducts from "@saleor/shipping/components/ShippingMethodProducts";
|
||||||
import ShippingRateInfo from "@saleor/shipping/components/ShippingRateInfo";
|
import ShippingRateInfo from "@saleor/shipping/components/ShippingRateInfo";
|
||||||
import { createChannelsChangeHandler } from "@saleor/shipping/handlers";
|
import { createChannelsChangeHandler } from "@saleor/shipping/handlers";
|
||||||
import { ListActions, ListProps } from "@saleor/types";
|
import { FetchMoreProps, ListActions, ListProps } from "@saleor/types";
|
||||||
import { mapEdgesToItems, mapMetadataItemToInput } from "@saleor/utils/maps";
|
import { mapEdgesToItems, mapMetadataItemToInput } from "@saleor/utils/maps";
|
||||||
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
|
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
|
||||||
import { RichTextContext } from "@saleor/utils/richText/context";
|
import { RichTextContext } from "@saleor/utils/richText/context";
|
||||||
|
@ -36,6 +39,7 @@ import useRichText from "@saleor/utils/richText/useRichText";
|
||||||
import React, { FormEventHandler } from "react";
|
import React, { FormEventHandler } from "react";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
|
import ShippingMethodTaxes from "../ShippingMethodTaxes";
|
||||||
import ShippingZonePostalCodes from "../ShippingZonePostalCodes";
|
import ShippingZonePostalCodes from "../ShippingZonePostalCodes";
|
||||||
import { ShippingZoneRateUpdateFormData } from "./types";
|
import { ShippingZoneRateUpdateFormData } from "./types";
|
||||||
|
|
||||||
|
@ -66,6 +70,8 @@ export interface ShippingZoneRatesPageProps
|
||||||
onProductAssign: () => void;
|
onProductAssign: () => void;
|
||||||
onProductUnassign: (ids: string[]) => void;
|
onProductUnassign: (ids: string[]) => void;
|
||||||
variant: ShippingMethodTypeEnum;
|
variant: ShippingMethodTypeEnum;
|
||||||
|
taxClasses: Array<Omit<TaxClassFragment, "countries">>;
|
||||||
|
fetchMoreTaxClasses: FetchMoreProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ShippingZoneRatesPage: React.FC<ShippingZoneRatesPageProps> = ({
|
export const ShippingZoneRatesPage: React.FC<ShippingZoneRatesPageProps> = ({
|
||||||
|
@ -89,6 +95,8 @@ export const ShippingZoneRatesPage: React.FC<ShippingZoneRatesPageProps> = ({
|
||||||
postalCodeRules,
|
postalCodeRules,
|
||||||
variant,
|
variant,
|
||||||
formId,
|
formId,
|
||||||
|
taxClasses,
|
||||||
|
fetchMoreTaxClasses,
|
||||||
...listProps
|
...listProps
|
||||||
}) => {
|
}) => {
|
||||||
const navigate = useNavigator();
|
const navigate = useNavigator();
|
||||||
|
@ -110,6 +118,7 @@ export const ShippingZoneRatesPage: React.FC<ShippingZoneRatesPageProps> = ({
|
||||||
orderValueRestricted: !!rate?.channelListings.length,
|
orderValueRestricted: !!rate?.channelListings.length,
|
||||||
privateMetadata: rate?.privateMetadata.map(mapMetadataItemToInput),
|
privateMetadata: rate?.privateMetadata.map(mapMetadataItemToInput),
|
||||||
type: rate?.type || null,
|
type: rate?.type || null,
|
||||||
|
taxClassId: rate?.taxClass?.id || "",
|
||||||
}),
|
}),
|
||||||
[shippingChannels, rate],
|
[shippingChannels, rate],
|
||||||
);
|
);
|
||||||
|
@ -121,6 +130,10 @@ export const ShippingZoneRatesPage: React.FC<ShippingZoneRatesPageProps> = ({
|
||||||
triggerChange,
|
triggerChange,
|
||||||
} = useForm(initialForm, undefined, { confirmLeave: true, formId });
|
} = useForm(initialForm, undefined, { confirmLeave: true, formId });
|
||||||
|
|
||||||
|
const [taxClassDisplayName, setTaxClassDisplayName] = useStateUpdate(
|
||||||
|
rate?.taxClass?.name ?? "",
|
||||||
|
);
|
||||||
|
|
||||||
const handleFormSubmit = useHandleFormSubmit({
|
const handleFormSubmit = useHandleFormSubmit({
|
||||||
formId,
|
formId,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
|
@ -239,6 +252,22 @@ export const ShippingZoneRatesPage: React.FC<ShippingZoneRatesPageProps> = ({
|
||||||
}))}
|
}))}
|
||||||
openModal={openChannelsModal}
|
openModal={openChannelsModal}
|
||||||
/>
|
/>
|
||||||
|
<CardSpacer />
|
||||||
|
<ShippingMethodTaxes
|
||||||
|
value={formData.taxClassId}
|
||||||
|
taxClassDisplayName={taxClassDisplayName}
|
||||||
|
taxClasses={taxClasses}
|
||||||
|
disabled={false}
|
||||||
|
onChange={event =>
|
||||||
|
handleTaxClassChange(
|
||||||
|
event,
|
||||||
|
taxClasses,
|
||||||
|
change,
|
||||||
|
setTaxClassDisplayName,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onFetchMore={fetchMoreTaxClasses}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Savebar
|
<Savebar
|
||||||
|
|
|
@ -13,6 +13,7 @@ export interface ShippingZoneRateCommonFormData {
|
||||||
minDays: string;
|
minDays: string;
|
||||||
maxDays: string;
|
maxDays: string;
|
||||||
type: ShippingMethodTypeEnum;
|
type: ShippingMethodTypeEnum;
|
||||||
|
taxClassId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ShippingZoneRateUpdateFormData = ShippingZoneRateCommonFormData &
|
export type ShippingZoneRateUpdateFormData = ShippingZoneRateCommonFormData &
|
||||||
|
|
|
@ -1575,6 +1575,11 @@ export const shippingZone: ShippingZoneQuery["shippingZone"] = {
|
||||||
shippingMethods: [
|
shippingMethods: [
|
||||||
{
|
{
|
||||||
__typename: "ShippingMethodType",
|
__typename: "ShippingMethodType",
|
||||||
|
taxClass: {
|
||||||
|
__typename: "TaxClass",
|
||||||
|
name: "Shipping method",
|
||||||
|
id: "VGV4Q2xhc3M6MQ==",
|
||||||
|
},
|
||||||
channelListings: [
|
channelListings: [
|
||||||
{
|
{
|
||||||
__typename: "ShippingMethodChannelListing",
|
__typename: "ShippingMethodChannelListing",
|
||||||
|
@ -1670,6 +1675,11 @@ export const shippingZone: ShippingZoneQuery["shippingZone"] = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
__typename: "ShippingMethodType",
|
__typename: "ShippingMethodType",
|
||||||
|
taxClass: {
|
||||||
|
__typename: "TaxClass",
|
||||||
|
name: "Shipping method",
|
||||||
|
id: "VGV4Q2xhc3M6MQ==",
|
||||||
|
},
|
||||||
channelListings: [],
|
channelListings: [],
|
||||||
excludedProducts: {
|
excludedProducts: {
|
||||||
__typename: "ProductCountableConnection",
|
__typename: "ProductCountableConnection",
|
||||||
|
@ -1735,6 +1745,11 @@ export const shippingZone: ShippingZoneQuery["shippingZone"] = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
__typename: "ShippingMethodType",
|
__typename: "ShippingMethodType",
|
||||||
|
taxClass: {
|
||||||
|
__typename: "TaxClass",
|
||||||
|
name: "Shipping method",
|
||||||
|
id: "VGV4Q2xhc3M6MQ==",
|
||||||
|
},
|
||||||
channelListings: [],
|
channelListings: [],
|
||||||
excludedProducts: {
|
excludedProducts: {
|
||||||
__typename: "ProductCountableConnection",
|
__typename: "ProductCountableConnection",
|
||||||
|
@ -1800,6 +1815,11 @@ export const shippingZone: ShippingZoneQuery["shippingZone"] = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
__typename: "ShippingMethodType",
|
__typename: "ShippingMethodType",
|
||||||
|
taxClass: {
|
||||||
|
__typename: "TaxClass",
|
||||||
|
name: "Shipping method",
|
||||||
|
id: "VGV4Q2xhc3M6MQ==",
|
||||||
|
},
|
||||||
channelListings: [],
|
channelListings: [],
|
||||||
excludedProducts: {
|
excludedProducts: {
|
||||||
__typename: "ProductCountableConnection",
|
__typename: "ProductCountableConnection",
|
||||||
|
|
|
@ -134,6 +134,7 @@ export function getUpdateShippingPriceRateVariables(
|
||||||
shippingZone: id,
|
shippingZone: id,
|
||||||
type: ShippingMethodTypeEnum.PRICE,
|
type: ShippingMethodTypeEnum.PRICE,
|
||||||
description: getParsedDataForJsonStringField(data.description),
|
description: getParsedDataForJsonStringField(data.description),
|
||||||
|
taxClass: data.taxClassId,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -167,6 +168,7 @@ export function getUpdateShippingWeightRateVariables(
|
||||||
shippingZone: id,
|
shippingZone: id,
|
||||||
type: ShippingMethodTypeEnum.WEIGHT,
|
type: ShippingMethodTypeEnum.WEIGHT,
|
||||||
description: getParsedDataForJsonStringField(data.description),
|
description: getParsedDataForJsonStringField(data.description),
|
||||||
|
taxClass: data.taxClassId,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import {
|
||||||
getPostalCodeRuleByMinMax,
|
getPostalCodeRuleByMinMax,
|
||||||
getRuleObject,
|
getRuleObject,
|
||||||
} from "@saleor/shipping/views/utils";
|
} from "@saleor/shipping/views/utils";
|
||||||
|
import { useTaxClassFetchMore } from "@saleor/taxes/utils/useTaxClassFetchMore";
|
||||||
import { MinMax } from "@saleor/types";
|
import { MinMax } from "@saleor/types";
|
||||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
@ -52,6 +53,8 @@ export const RateCreate: React.FC<RateCreateProps> = ({ id, params }) => {
|
||||||
variables: { id },
|
variables: { id },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { taxClasses, fetchMoreTaxClasses } = useTaxClassFetchMore();
|
||||||
|
|
||||||
const allChannels = createSortedShippingChannels(
|
const allChannels = createSortedShippingChannels(
|
||||||
shippingZoneData?.shippingZone?.channels,
|
shippingZoneData?.shippingZone?.channels,
|
||||||
);
|
);
|
||||||
|
@ -164,6 +167,8 @@ export const RateCreate: React.FC<RateCreateProps> = ({ id, params }) => {
|
||||||
onPostalCodeUnassign={onPostalCodeUnassign}
|
onPostalCodeUnassign={onPostalCodeUnassign}
|
||||||
onPostalCodeInclusionChange={onPostalCodeInclusionChange}
|
onPostalCodeInclusionChange={onPostalCodeInclusionChange}
|
||||||
variant={params.type}
|
variant={params.type}
|
||||||
|
taxClasses={taxClasses ?? []}
|
||||||
|
fetchMoreTaxClasses={fetchMoreTaxClasses}
|
||||||
/>
|
/>
|
||||||
<ShippingZonePostalCodeRangeDialog
|
<ShippingZonePostalCodeRangeDialog
|
||||||
confirmButtonState="default"
|
confirmButtonState="default"
|
||||||
|
|
|
@ -55,6 +55,7 @@ import {
|
||||||
getPostalCodeRuleByMinMax,
|
getPostalCodeRuleByMinMax,
|
||||||
getRuleObject,
|
getRuleObject,
|
||||||
} from "@saleor/shipping/views/utils";
|
} from "@saleor/shipping/views/utils";
|
||||||
|
import { useTaxClassFetchMore } from "@saleor/taxes/utils/useTaxClassFetchMore";
|
||||||
import { MinMax } from "@saleor/types";
|
import { MinMax } from "@saleor/types";
|
||||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||||
import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler";
|
import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler";
|
||||||
|
@ -166,6 +167,8 @@ export const RateUpdate: React.FC<RateUpdateProps> = ({
|
||||||
{ formId: FORM_ID },
|
{ formId: FORM_ID },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const { taxClasses, fetchMoreTaxClasses } = useTaxClassFetchMore();
|
||||||
|
|
||||||
const [
|
const [
|
||||||
updateShippingRate,
|
updateShippingRate,
|
||||||
updateShippingRateOpts,
|
updateShippingRateOpts,
|
||||||
|
@ -410,6 +413,8 @@ export const RateUpdate: React.FC<RateUpdateProps> = ({
|
||||||
onPostalCodeAssign={() => openModal("add-range")}
|
onPostalCodeAssign={() => openModal("add-range")}
|
||||||
onPostalCodeUnassign={onPostalCodeUnassign}
|
onPostalCodeUnassign={onPostalCodeUnassign}
|
||||||
postalCodeRules={state.postalCodeRules}
|
postalCodeRules={state.postalCodeRules}
|
||||||
|
taxClasses={taxClasses ?? []}
|
||||||
|
fetchMoreTaxClasses={fetchMoreTaxClasses}
|
||||||
/>
|
/>
|
||||||
<ShippingZonePostalCodeRangeDialog
|
<ShippingZonePostalCodeRangeDialog
|
||||||
confirmButtonState={"default"}
|
confirmButtonState={"default"}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -138,10 +138,6 @@ function loadStories() {
|
||||||
// Site settings
|
// Site settings
|
||||||
require("./stories/siteSettings/SiteSettingsPage");
|
require("./stories/siteSettings/SiteSettingsPage");
|
||||||
|
|
||||||
// Taxes
|
|
||||||
require("./stories/taxes/CountryListPage");
|
|
||||||
require("./stories/taxes/CountryTaxesPage");
|
|
||||||
|
|
||||||
// Translations
|
// Translations
|
||||||
require("./stories/translations/TranslationsEntitiesListPage");
|
require("./stories/translations/TranslationsEntitiesListPage");
|
||||||
require("./stories/translations/TranslationsLanguageListPage");
|
require("./stories/translations/TranslationsLanguageListPage");
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { ProductTypeKindEnum, WeightUnitsEnum } from "@saleor/graphql";
|
import { ProductTypeKindEnum, WeightUnitsEnum } from "@saleor/graphql";
|
||||||
import { formError } from "@saleor/storybook/misc";
|
import { formError } from "@saleor/storybook/misc";
|
||||||
|
import { taxClasses } from "@saleor/taxes/fixtures";
|
||||||
import { storiesOf } from "@storybook/react";
|
import { storiesOf } from "@storybook/react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
|
@ -16,7 +17,8 @@ const props: Omit<ProductTypeCreatePageProps, "classes"> = {
|
||||||
onSubmit: () => undefined,
|
onSubmit: () => undefined,
|
||||||
pageTitle: "Create product type",
|
pageTitle: "Create product type",
|
||||||
saveButtonBarState: "default",
|
saveButtonBarState: "default",
|
||||||
taxTypes: [],
|
taxClasses,
|
||||||
|
onFetchMoreTaxClasses: undefined,
|
||||||
kind: ProductTypeKindEnum.NORMAL,
|
kind: ProductTypeKindEnum.NORMAL,
|
||||||
onChangeKind: () => undefined,
|
onChangeKind: () => undefined,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { listActionsProps } from "@saleor/fixtures";
|
import { listActionsProps } from "@saleor/fixtures";
|
||||||
import { WeightUnitsEnum } from "@saleor/graphql";
|
import { WeightUnitsEnum } from "@saleor/graphql";
|
||||||
import { formError } from "@saleor/storybook/misc";
|
import { formError } from "@saleor/storybook/misc";
|
||||||
|
import { taxClasses } from "@saleor/taxes/fixtures";
|
||||||
import { storiesOf } from "@storybook/react";
|
import { storiesOf } from "@storybook/react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
|
@ -25,7 +26,8 @@ const props: Omit<ProductTypeDetailsPageProps, "classes"> = {
|
||||||
productAttributeList: listActionsProps,
|
productAttributeList: listActionsProps,
|
||||||
productType,
|
productType,
|
||||||
saveButtonBarState: "default",
|
saveButtonBarState: "default",
|
||||||
taxTypes: [],
|
taxClasses,
|
||||||
|
onFetchMoreTaxClasses: undefined,
|
||||||
variantAttributeList: listActionsProps,
|
variantAttributeList: listActionsProps,
|
||||||
setSelectedVariantAttributes: () => undefined,
|
setSelectedVariantAttributes: () => undefined,
|
||||||
selectedVariantAttributes: [],
|
selectedVariantAttributes: [],
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { channelsList } from "@saleor/channels/fixtures";
|
||||||
import { createChannelsData } from "@saleor/channels/utils";
|
import { createChannelsData } from "@saleor/channels/utils";
|
||||||
import { fetchMoreProps } from "@saleor/fixtures";
|
import { fetchMoreProps } from "@saleor/fixtures";
|
||||||
import { ProductErrorCode } from "@saleor/graphql";
|
import { ProductErrorCode } from "@saleor/graphql";
|
||||||
|
import { taxClasses } from "@saleor/taxes/fixtures";
|
||||||
import { warehouseList } from "@saleor/warehouses/fixtures";
|
import { warehouseList } from "@saleor/warehouses/fixtures";
|
||||||
import { storiesOf } from "@storybook/react";
|
import { storiesOf } from "@storybook/react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
@ -15,7 +16,6 @@ import {
|
||||||
productTypeSearch,
|
productTypeSearch,
|
||||||
} from "../../../productTypes/fixtures";
|
} from "../../../productTypes/fixtures";
|
||||||
import Decorator from "../../Decorator";
|
import Decorator from "../../Decorator";
|
||||||
import { taxTypes } from "../taxes/fixtures";
|
|
||||||
|
|
||||||
const product = productFixture("");
|
const product = productFixture("");
|
||||||
const channels = createChannelsData(channelsList);
|
const channels = createChannelsData(channelsList);
|
||||||
|
@ -47,7 +47,8 @@ storiesOf("Views / Products / Create product", module)
|
||||||
saveButtonBarState="default"
|
saveButtonBarState="default"
|
||||||
warehouses={warehouseList}
|
warehouses={warehouseList}
|
||||||
onWarehouseConfigure={() => undefined}
|
onWarehouseConfigure={() => undefined}
|
||||||
taxTypes={taxTypes}
|
taxClasses={taxClasses}
|
||||||
|
fetchMoreTaxClasses={undefined}
|
||||||
weightUnit="kg"
|
weightUnit="kg"
|
||||||
referencePages={[]}
|
referencePages={[]}
|
||||||
referenceProducts={[]}
|
referenceProducts={[]}
|
||||||
|
@ -83,7 +84,8 @@ storiesOf("Views / Products / Create product", module)
|
||||||
saveButtonBarState="default"
|
saveButtonBarState="default"
|
||||||
warehouses={undefined}
|
warehouses={undefined}
|
||||||
onWarehouseConfigure={() => undefined}
|
onWarehouseConfigure={() => undefined}
|
||||||
taxTypes={taxTypes}
|
taxClasses={taxClasses}
|
||||||
|
fetchMoreTaxClasses={undefined}
|
||||||
weightUnit="kg"
|
weightUnit="kg"
|
||||||
referencePages={[]}
|
referencePages={[]}
|
||||||
referenceProducts={[]}
|
referenceProducts={[]}
|
||||||
|
@ -135,7 +137,8 @@ storiesOf("Views / Products / Create product", module)
|
||||||
saveButtonBarState="default"
|
saveButtonBarState="default"
|
||||||
warehouses={warehouseList}
|
warehouses={warehouseList}
|
||||||
onWarehouseConfigure={() => undefined}
|
onWarehouseConfigure={() => undefined}
|
||||||
taxTypes={taxTypes}
|
taxClasses={taxClasses}
|
||||||
|
fetchMoreTaxClasses={undefined}
|
||||||
weightUnit="kg"
|
weightUnit="kg"
|
||||||
referencePages={[]}
|
referencePages={[]}
|
||||||
referenceProducts={[]}
|
referenceProducts={[]}
|
||||||
|
|
|
@ -8,12 +8,12 @@ import ProductUpdatePage, {
|
||||||
} from "@saleor/products/components/ProductUpdatePage";
|
} from "@saleor/products/components/ProductUpdatePage";
|
||||||
import { ProductUpdateFormData } from "@saleor/products/components/ProductUpdatePage/types";
|
import { ProductUpdateFormData } from "@saleor/products/components/ProductUpdatePage/types";
|
||||||
import { product as productFixture } from "@saleor/products/fixtures";
|
import { product as productFixture } from "@saleor/products/fixtures";
|
||||||
|
import { taxClasses } from "@saleor/taxes/fixtures";
|
||||||
import { warehouseList } from "@saleor/warehouses/fixtures";
|
import { warehouseList } from "@saleor/warehouses/fixtures";
|
||||||
import { storiesOf } from "@storybook/react";
|
import { storiesOf } from "@storybook/react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import Decorator from "../../Decorator";
|
import Decorator from "../../Decorator";
|
||||||
import { taxTypes } from "../taxes/fixtures";
|
|
||||||
|
|
||||||
const product = productFixture(placeholderImage);
|
const product = productFixture(placeholderImage);
|
||||||
|
|
||||||
|
@ -60,7 +60,8 @@ const props: ProductUpdatePageProps = {
|
||||||
referencePages: [],
|
referencePages: [],
|
||||||
referenceProducts: [],
|
referenceProducts: [],
|
||||||
saveButtonBarState: "default",
|
saveButtonBarState: "default",
|
||||||
taxTypes,
|
taxClasses,
|
||||||
|
fetchMoreTaxClasses: undefined,
|
||||||
variants: product.variants,
|
variants: product.variants,
|
||||||
warehouses: warehouseList,
|
warehouses: warehouseList,
|
||||||
attributeValues: [],
|
attributeValues: [],
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { countries } from "@saleor/fixtures";
|
||||||
import { mapCountriesToCountriesCodes } from "@saleor/utils/maps";
|
import { mapCountriesToCountriesCodes } from "@saleor/utils/maps";
|
||||||
import { storiesOf } from "@storybook/react";
|
import { storiesOf } from "@storybook/react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
@ -6,13 +7,18 @@ import ShippingZoneCountriesAssignDialog, {
|
||||||
ShippingZoneCountriesAssignDialogProps,
|
ShippingZoneCountriesAssignDialogProps,
|
||||||
} from "../../../shipping/components/ShippingZoneCountriesAssignDialog";
|
} from "../../../shipping/components/ShippingZoneCountriesAssignDialog";
|
||||||
import Decorator from "../../Decorator";
|
import Decorator from "../../Decorator";
|
||||||
import { countries } from "../taxes/fixtures";
|
|
||||||
|
|
||||||
const initialCountries = ["PL", "GB", "DE"];
|
const initialCountries = ["PL", "GB", "DE"];
|
||||||
|
|
||||||
|
const mappedCountries = countries.map(({ code, name }) => ({
|
||||||
|
__typename: "CountryDisplay" as const,
|
||||||
|
code,
|
||||||
|
country: name,
|
||||||
|
}));
|
||||||
|
|
||||||
const props: ShippingZoneCountriesAssignDialogProps = {
|
const props: ShippingZoneCountriesAssignDialogProps = {
|
||||||
confirmButtonState: "default",
|
confirmButtonState: "default",
|
||||||
countries,
|
countries: mappedCountries,
|
||||||
restWorldCountries: mapCountriesToCountriesCodes(countries).filter(
|
restWorldCountries: mapCountriesToCountriesCodes(countries).filter(
|
||||||
countryCode => !initialCountries.includes(countryCode),
|
countryCode => !initialCountries.includes(countryCode),
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
import { storiesOf } from "@storybook/react";
|
|
||||||
import React from "react";
|
|
||||||
|
|
||||||
import { pageListProps } from "../../../fixtures";
|
|
||||||
import CountryListPage, {
|
|
||||||
CountryListPageProps,
|
|
||||||
} from "../../../taxes/components/CountryListPage";
|
|
||||||
import Decorator from "../../Decorator";
|
|
||||||
import { countries } from "./fixtures";
|
|
||||||
|
|
||||||
const props: CountryListPageProps = {
|
|
||||||
...pageListProps.default,
|
|
||||||
onSubmit: () => undefined,
|
|
||||||
onTaxFetch: () => undefined,
|
|
||||||
saveButtonBarState: "default",
|
|
||||||
shop: {
|
|
||||||
__typename: "Shop",
|
|
||||||
chargeTaxesOnShipping: false,
|
|
||||||
countries,
|
|
||||||
displayGrossPrices: true,
|
|
||||||
includeTaxesInPrices: false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
storiesOf("Views / Taxes / Country List", module)
|
|
||||||
.addDecorator(Decorator)
|
|
||||||
.add("default", () => <CountryListPage {...props} />)
|
|
||||||
.add("loading", () => (
|
|
||||||
<CountryListPage {...props} shop={undefined} disabled={true} />
|
|
||||||
));
|
|
|
@ -1,24 +0,0 @@
|
||||||
import { storiesOf } from "@storybook/react";
|
|
||||||
import React from "react";
|
|
||||||
|
|
||||||
import CountryTaxesPage, {
|
|
||||||
CountryTaxesPageProps,
|
|
||||||
} from "../../../taxes/components/CountryTaxesPage";
|
|
||||||
import Decorator from "../../Decorator";
|
|
||||||
import { countries } from "./fixtures";
|
|
||||||
|
|
||||||
const props: CountryTaxesPageProps = {
|
|
||||||
countryName: "Austria",
|
|
||||||
taxCategories: countries[0].vat.reducedRates,
|
|
||||||
};
|
|
||||||
|
|
||||||
storiesOf("Views / Taxes / Reduced Tax Categories", module)
|
|
||||||
.addDecorator(Decorator)
|
|
||||||
.add("default", () => <CountryTaxesPage {...props} />)
|
|
||||||
.add("loading", () => (
|
|
||||||
<CountryTaxesPage
|
|
||||||
{...props}
|
|
||||||
countryName={undefined}
|
|
||||||
taxCategories={undefined}
|
|
||||||
/>
|
|
||||||
));
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,97 +0,0 @@
|
||||||
import { Card, TableBody, TableCell, TableHead } from "@material-ui/core";
|
|
||||||
import ResponsiveTable from "@saleor/components/ResponsiveTable";
|
|
||||||
import Skeleton from "@saleor/components/Skeleton";
|
|
||||||
import TableRowLink from "@saleor/components/TableRowLink";
|
|
||||||
import { CountryListQuery } from "@saleor/graphql";
|
|
||||||
import { makeStyles } from "@saleor/macaw-ui";
|
|
||||||
import { countryTaxRatesUrl } from "@saleor/taxes/urls";
|
|
||||||
import classNames from "classnames";
|
|
||||||
import React from "react";
|
|
||||||
import { FormattedMessage } from "react-intl";
|
|
||||||
|
|
||||||
import { maybe, renderCollection } from "../../../misc";
|
|
||||||
|
|
||||||
const useStyles = makeStyles(
|
|
||||||
{
|
|
||||||
tableRow: {
|
|
||||||
cursor: "pointer",
|
|
||||||
},
|
|
||||||
textRight: {
|
|
||||||
textAlign: "right",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ name: "CountryList" },
|
|
||||||
);
|
|
||||||
|
|
||||||
interface CountryListProps {
|
|
||||||
countries: CountryListQuery["shop"]["countries"];
|
|
||||||
}
|
|
||||||
|
|
||||||
const CountryList: React.FC<CountryListProps> = props => {
|
|
||||||
const { countries } = props;
|
|
||||||
|
|
||||||
const classes = useStyles(props);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Card>
|
|
||||||
<ResponsiveTable>
|
|
||||||
<TableHead>
|
|
||||||
<TableRowLink>
|
|
||||||
<TableCell>
|
|
||||||
<FormattedMessage id="07KB2d" defaultMessage="Country Code" />
|
|
||||||
</TableCell>
|
|
||||||
<TableCell>
|
|
||||||
<FormattedMessage id="0GJfWd" defaultMessage="Country Name" />
|
|
||||||
</TableCell>
|
|
||||||
<TableCell className={classes.textRight}>
|
|
||||||
<FormattedMessage
|
|
||||||
id="/JENWS"
|
|
||||||
defaultMessage="Reduced Tax Rates"
|
|
||||||
/>
|
|
||||||
</TableCell>
|
|
||||||
</TableRowLink>
|
|
||||||
</TableHead>
|
|
||||||
<TableBody>
|
|
||||||
{renderCollection(
|
|
||||||
countries,
|
|
||||||
country => (
|
|
||||||
<TableRowLink
|
|
||||||
className={classNames({
|
|
||||||
[classes.tableRow]: !!country,
|
|
||||||
})}
|
|
||||||
hover={!!country}
|
|
||||||
href={country && countryTaxRatesUrl(country.code)}
|
|
||||||
key={country ? country.code : "skeleton"}
|
|
||||||
>
|
|
||||||
<TableCell>
|
|
||||||
{maybe<React.ReactNode>(() => country.code, <Skeleton />)}
|
|
||||||
</TableCell>
|
|
||||||
<TableCell>
|
|
||||||
{maybe<React.ReactNode>(() => country.country, <Skeleton />)}
|
|
||||||
</TableCell>
|
|
||||||
<TableCell className={classes.textRight}>
|
|
||||||
{maybe<React.ReactNode>(
|
|
||||||
() => country.vat.reducedRates.length,
|
|
||||||
<Skeleton />,
|
|
||||||
)}
|
|
||||||
</TableCell>
|
|
||||||
</TableRowLink>
|
|
||||||
),
|
|
||||||
() => (
|
|
||||||
<TableRowLink>
|
|
||||||
<TableCell colSpan={3}>
|
|
||||||
<FormattedMessage
|
|
||||||
id="3BTtL2"
|
|
||||||
defaultMessage="No countries found"
|
|
||||||
/>
|
|
||||||
</TableCell>
|
|
||||||
</TableRowLink>
|
|
||||||
),
|
|
||||||
)}
|
|
||||||
</TableBody>
|
|
||||||
</ResponsiveTable>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
CountryList.displayName = "CountryList";
|
|
||||||
export default CountryList;
|
|
|
@ -1,2 +0,0 @@
|
||||||
export { default } from "./CountryList";
|
|
||||||
export * from "./CountryList";
|
|
|
@ -1,94 +0,0 @@
|
||||||
import { Backlink } from "@saleor/components/Backlink";
|
|
||||||
import { Container } from "@saleor/components/Container";
|
|
||||||
import Form from "@saleor/components/Form";
|
|
||||||
import Grid from "@saleor/components/Grid";
|
|
||||||
import PageHeader from "@saleor/components/PageHeader";
|
|
||||||
import Savebar from "@saleor/components/Savebar";
|
|
||||||
import { configurationMenuUrl } from "@saleor/configuration";
|
|
||||||
import { CountryListQuery } from "@saleor/graphql";
|
|
||||||
import { SubmitPromise } from "@saleor/hooks/useForm";
|
|
||||||
import useNavigator from "@saleor/hooks/useNavigator";
|
|
||||||
import { sectionNames } from "@saleor/intl";
|
|
||||||
import { ConfirmButtonTransitionState } from "@saleor/macaw-ui";
|
|
||||||
import React from "react";
|
|
||||||
import { useIntl } from "react-intl";
|
|
||||||
|
|
||||||
import CountryList from "../CountryList";
|
|
||||||
import TaxConfiguration from "../TaxConfiguration";
|
|
||||||
|
|
||||||
export interface TaxesConfigurationFormData {
|
|
||||||
includeTax: boolean;
|
|
||||||
showGross: boolean;
|
|
||||||
chargeTaxesOnShipping: boolean;
|
|
||||||
}
|
|
||||||
export interface CountryListPageProps {
|
|
||||||
disabled: boolean;
|
|
||||||
saveButtonBarState: ConfirmButtonTransitionState;
|
|
||||||
shop: CountryListQuery["shop"];
|
|
||||||
onSubmit: (data: TaxesConfigurationFormData) => SubmitPromise;
|
|
||||||
onTaxFetch: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const CountryListPage: React.FC<CountryListPageProps> = ({
|
|
||||||
disabled,
|
|
||||||
saveButtonBarState,
|
|
||||||
shop,
|
|
||||||
onSubmit,
|
|
||||||
onTaxFetch,
|
|
||||||
}) => {
|
|
||||||
const intl = useIntl();
|
|
||||||
const navigate = useNavigator();
|
|
||||||
|
|
||||||
const initialForm: TaxesConfigurationFormData = {
|
|
||||||
chargeTaxesOnShipping: shop?.chargeTaxesOnShipping || false,
|
|
||||||
includeTax: shop?.includeTaxesInPrices || false,
|
|
||||||
showGross: shop?.displayGrossPrices || false,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Form
|
|
||||||
confirmLeave
|
|
||||||
initial={initialForm}
|
|
||||||
onSubmit={onSubmit}
|
|
||||||
disabled={disabled}
|
|
||||||
>
|
|
||||||
{({ change, data, isSaveDisabled, submit }) => (
|
|
||||||
<>
|
|
||||||
<Container>
|
|
||||||
<Backlink href={configurationMenuUrl}>
|
|
||||||
{intl.formatMessage(sectionNames.configuration)}
|
|
||||||
</Backlink>
|
|
||||||
<PageHeader
|
|
||||||
title={intl.formatMessage({
|
|
||||||
id: "lnQAos",
|
|
||||||
defaultMessage: "Taxes",
|
|
||||||
description: "header",
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
<Grid variant="inverted">
|
|
||||||
<div>
|
|
||||||
<TaxConfiguration
|
|
||||||
data={data}
|
|
||||||
disabled={disabled}
|
|
||||||
onChange={event => change(event)}
|
|
||||||
onTaxFetch={onTaxFetch}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<CountryList countries={shop?.countries} />
|
|
||||||
</div>
|
|
||||||
</Grid>
|
|
||||||
</Container>
|
|
||||||
<Savebar
|
|
||||||
disabled={isSaveDisabled}
|
|
||||||
state={saveButtonBarState}
|
|
||||||
onCancel={() => navigate(configurationMenuUrl)}
|
|
||||||
onSubmit={submit}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Form>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
CountryListPage.displayName = "CountryListPage";
|
|
||||||
export default CountryListPage;
|
|
|
@ -1,2 +0,0 @@
|
||||||
export { default } from "./CountryListPage";
|
|
||||||
export * from "./CountryListPage";
|
|
|
@ -1,111 +0,0 @@
|
||||||
import { Card, TableBody, TableCell, TableHead } from "@material-ui/core";
|
|
||||||
import { Backlink } from "@saleor/components/Backlink";
|
|
||||||
import { Container } from "@saleor/components/Container";
|
|
||||||
import Grid from "@saleor/components/Grid";
|
|
||||||
import PageHeader from "@saleor/components/PageHeader";
|
|
||||||
import ResponsiveTable from "@saleor/components/ResponsiveTable";
|
|
||||||
import Skeleton from "@saleor/components/Skeleton";
|
|
||||||
import TableRowLink from "@saleor/components/TableRowLink";
|
|
||||||
import { CountryListQuery } from "@saleor/graphql";
|
|
||||||
import { sectionNames } from "@saleor/intl";
|
|
||||||
import { makeStyles } from "@saleor/macaw-ui";
|
|
||||||
import { countryListUrl } from "@saleor/taxes/urls";
|
|
||||||
import React from "react";
|
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
|
||||||
|
|
||||||
import { maybe, renderCollection } from "../../../misc";
|
|
||||||
|
|
||||||
const useStyles = makeStyles(
|
|
||||||
{
|
|
||||||
wideColumn: {
|
|
||||||
width: "80%",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ name: "CountryTaxesPage" },
|
|
||||||
);
|
|
||||||
|
|
||||||
export interface CountryTaxesPageProps {
|
|
||||||
countryName: string;
|
|
||||||
taxCategories: CountryListQuery["shop"]["countries"][0]["vat"]["reducedRates"];
|
|
||||||
}
|
|
||||||
|
|
||||||
const CountryTaxesPage: React.FC<CountryTaxesPageProps> = props => {
|
|
||||||
const { countryName, taxCategories } = props;
|
|
||||||
|
|
||||||
const classes = useStyles(props);
|
|
||||||
const intl = useIntl();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Container>
|
|
||||||
<Backlink href={countryListUrl}>
|
|
||||||
{intl.formatMessage(sectionNames.taxes)}
|
|
||||||
</Backlink>
|
|
||||||
<PageHeader
|
|
||||||
title={
|
|
||||||
countryName
|
|
||||||
? intl.formatMessage(
|
|
||||||
{
|
|
||||||
id: "QHB48n",
|
|
||||||
defaultMessage: "Tax Rates in {countryName}",
|
|
||||||
description: "header",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
countryName,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Grid>
|
|
||||||
<div>
|
|
||||||
<Card>
|
|
||||||
<ResponsiveTable>
|
|
||||||
<TableHead>
|
|
||||||
<TableRowLink>
|
|
||||||
<TableCell className={classes.wideColumn}>
|
|
||||||
<FormattedMessage id="ccXLVi" defaultMessage="Category" />
|
|
||||||
</TableCell>
|
|
||||||
<TableCell>
|
|
||||||
<FormattedMessage id="la9cZ4" defaultMessage="Tax Rate" />
|
|
||||||
</TableCell>
|
|
||||||
</TableRowLink>
|
|
||||||
</TableHead>
|
|
||||||
<TableBody>
|
|
||||||
{renderCollection(
|
|
||||||
taxCategories,
|
|
||||||
taxCategory => (
|
|
||||||
<TableRowLink
|
|
||||||
key={taxCategory ? taxCategory.rateType : "skeleton"}
|
|
||||||
>
|
|
||||||
<TableCell>
|
|
||||||
{taxCategory?.rateType ?? <Skeleton />}
|
|
||||||
</TableCell>
|
|
||||||
<TableCell>
|
|
||||||
{maybe<React.ReactNode>(
|
|
||||||
() => taxCategory.rate,
|
|
||||||
<Skeleton />,
|
|
||||||
)}
|
|
||||||
</TableCell>
|
|
||||||
</TableRowLink>
|
|
||||||
),
|
|
||||||
() => (
|
|
||||||
<TableRowLink>
|
|
||||||
<TableCell colSpan={2}>
|
|
||||||
<FormattedMessage
|
|
||||||
id="Ubath+"
|
|
||||||
defaultMessage="No reduced tax categories found"
|
|
||||||
/>
|
|
||||||
</TableCell>
|
|
||||||
</TableRowLink>
|
|
||||||
),
|
|
||||||
)}
|
|
||||||
</TableBody>
|
|
||||||
</ResponsiveTable>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
</Grid>
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
CountryTaxesPage.displayName = "CountryTaxesPage";
|
|
||||||
export default CountryTaxesPage;
|
|
|
@ -1,2 +0,0 @@
|
||||||
export { default } from "./CountryTaxesPage";
|
|
||||||
export * from "./CountryTaxesPage";
|
|
|
@ -1,85 +0,0 @@
|
||||||
import { Card, CardActions, CardContent } from "@material-ui/core";
|
|
||||||
import { Button } from "@saleor/components/Button";
|
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
|
||||||
import ControlledCheckbox from "@saleor/components/ControlledCheckbox";
|
|
||||||
import FormSpacer from "@saleor/components/FormSpacer";
|
|
||||||
import { sectionNames } from "@saleor/intl";
|
|
||||||
import { makeStyles } from "@saleor/macaw-ui";
|
|
||||||
import React from "react";
|
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
|
||||||
|
|
||||||
import { TaxesConfigurationFormData } from "../CountryListPage";
|
|
||||||
|
|
||||||
interface TaxConfigurationProps {
|
|
||||||
data: TaxesConfigurationFormData;
|
|
||||||
disabled: boolean;
|
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
|
||||||
onTaxFetch: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const useStyles = makeStyles(
|
|
||||||
{
|
|
||||||
content: {
|
|
||||||
paddingBottom: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ name: "TaxConfiguration" },
|
|
||||||
);
|
|
||||||
|
|
||||||
export const TaxConfiguration: React.FC<TaxConfigurationProps> = props => {
|
|
||||||
const { data, disabled, onChange, onTaxFetch } = props;
|
|
||||||
|
|
||||||
const classes = useStyles(props);
|
|
||||||
const intl = useIntl();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Card>
|
|
||||||
<CardTitle title={intl.formatMessage(sectionNames.configuration)} />
|
|
||||||
<CardContent className={classes.content}>
|
|
||||||
<ControlledCheckbox
|
|
||||||
name={"includeTax" as keyof FormData}
|
|
||||||
label={intl.formatMessage({
|
|
||||||
id: "4EuJKs",
|
|
||||||
defaultMessage: "All products prices are entered with tax included",
|
|
||||||
})}
|
|
||||||
checked={data.includeTax}
|
|
||||||
onChange={onChange}
|
|
||||||
disabled={disabled}
|
|
||||||
/>
|
|
||||||
<FormSpacer />
|
|
||||||
<ControlledCheckbox
|
|
||||||
name={"showGross" as keyof FormData}
|
|
||||||
label={intl.formatMessage({
|
|
||||||
id: "98isC5",
|
|
||||||
defaultMessage: "Show gross prices to customers in the storefront",
|
|
||||||
})}
|
|
||||||
checked={data.showGross}
|
|
||||||
onChange={onChange}
|
|
||||||
disabled={disabled}
|
|
||||||
/>
|
|
||||||
<FormSpacer />
|
|
||||||
<ControlledCheckbox
|
|
||||||
name={"chargeTaxesOnShipping" as keyof FormData}
|
|
||||||
label={intl.formatMessage({
|
|
||||||
id: "FNKhkx",
|
|
||||||
defaultMessage: "Charge taxes on shipping rates",
|
|
||||||
})}
|
|
||||||
checked={data.chargeTaxesOnShipping}
|
|
||||||
onChange={onChange}
|
|
||||||
disabled={disabled}
|
|
||||||
/>
|
|
||||||
<FormSpacer />
|
|
||||||
</CardContent>
|
|
||||||
<CardActions>
|
|
||||||
<Button disabled={disabled} onClick={onTaxFetch}>
|
|
||||||
<FormattedMessage
|
|
||||||
id="+OV+Gj"
|
|
||||||
defaultMessage="Fetch taxes"
|
|
||||||
description="button"
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
</CardActions>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
export default TaxConfiguration;
|
|
|
@ -1,2 +0,0 @@
|
||||||
export { default } from "./TaxConfiguration";
|
|
||||||
export * from "./TaxConfiguration";
|
|
105
src/taxes/components/TaxCountryDialog/TaxCountryDialog.tsx
Normal file
105
src/taxes/components/TaxCountryDialog/TaxCountryDialog.tsx
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogActions,
|
||||||
|
DialogContent,
|
||||||
|
Divider,
|
||||||
|
FormControlLabel,
|
||||||
|
InputAdornment,
|
||||||
|
Radio,
|
||||||
|
TextField,
|
||||||
|
} from "@material-ui/core";
|
||||||
|
import VerticalSpacer from "@saleor/apps/components/VerticalSpacer";
|
||||||
|
import { CountryFragment } from "@saleor/graphql";
|
||||||
|
import { useLocalSearch } from "@saleor/hooks/useLocalSearch";
|
||||||
|
import useModalDialogOpen from "@saleor/hooks/useModalDialogOpen";
|
||||||
|
import { buttonMessages } from "@saleor/intl";
|
||||||
|
import { Button, DialogHeader, SearchIcon } from "@saleor/macaw-ui";
|
||||||
|
import { taxesMessages } from "@saleor/taxes/messages";
|
||||||
|
import React from "react";
|
||||||
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import { useStyles } from "./styles";
|
||||||
|
|
||||||
|
interface TaxCountryDialogProps {
|
||||||
|
open: boolean;
|
||||||
|
countries: CountryFragment[];
|
||||||
|
onConfirm: (countries: CountryFragment) => void;
|
||||||
|
onClose: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TaxCountryDialog: React.FC<TaxCountryDialogProps> = ({
|
||||||
|
open,
|
||||||
|
countries,
|
||||||
|
onConfirm,
|
||||||
|
onClose,
|
||||||
|
}) => {
|
||||||
|
const classes = useStyles();
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const [selectedCountry, setSelectedCountry] = React.useState<
|
||||||
|
CountryFragment
|
||||||
|
>();
|
||||||
|
|
||||||
|
useModalDialogOpen(open, {
|
||||||
|
onClose: () => {
|
||||||
|
setSelectedCountry(undefined);
|
||||||
|
setQuery("");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const { query, setQuery, searchResult: filteredCountries } = useLocalSearch<
|
||||||
|
CountryFragment
|
||||||
|
>(countries, country => country.country);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={open} fullWidth onClose={onClose}>
|
||||||
|
<DialogHeader onClose={onClose}>
|
||||||
|
<FormattedMessage {...taxesMessages.chooseCountryDialogTitle} />
|
||||||
|
</DialogHeader>
|
||||||
|
<DialogContent className={classes.wrapper}>
|
||||||
|
<TextField
|
||||||
|
value={query}
|
||||||
|
onChange={e => setQuery(e.target.value)}
|
||||||
|
variant="outlined"
|
||||||
|
placeholder={intl.formatMessage(taxesMessages.country)}
|
||||||
|
fullWidth
|
||||||
|
InputProps={{
|
||||||
|
startAdornment: (
|
||||||
|
<InputAdornment position="start">
|
||||||
|
<SearchIcon />
|
||||||
|
</InputAdornment>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
inputProps={{ className: classes.inputPadding }}
|
||||||
|
/>
|
||||||
|
<VerticalSpacer spacing={2} />
|
||||||
|
<div className={classes.scrollable}>
|
||||||
|
{filteredCountries.map(country => (
|
||||||
|
<React.Fragment key={country.code}>
|
||||||
|
<FormControlLabel
|
||||||
|
label={country.country}
|
||||||
|
checked={country.code === selectedCountry?.code}
|
||||||
|
onChange={() => setSelectedCountry(country)}
|
||||||
|
control={<Radio />}
|
||||||
|
/>
|
||||||
|
<Divider />
|
||||||
|
</React.Fragment>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button
|
||||||
|
variant="primary"
|
||||||
|
onClick={() => {
|
||||||
|
onConfirm(selectedCountry);
|
||||||
|
}}
|
||||||
|
disabled={!selectedCountry}
|
||||||
|
>
|
||||||
|
<FormattedMessage {...buttonMessages.add} />
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TaxCountryDialog;
|
2
src/taxes/components/TaxCountryDialog/index.ts
Normal file
2
src/taxes/components/TaxCountryDialog/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export { default } from "./TaxCountryDialog";
|
||||||
|
export * from "./TaxCountryDialog";
|
22
src/taxes/components/TaxCountryDialog/styles.ts
Normal file
22
src/taxes/components/TaxCountryDialog/styles.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import { makeStyles } from "@saleor/macaw-ui";
|
||||||
|
|
||||||
|
export const useStyles = makeStyles(
|
||||||
|
theme => ({
|
||||||
|
inputPadding: {
|
||||||
|
padding: theme.spacing(2, 0),
|
||||||
|
},
|
||||||
|
wrapper: {
|
||||||
|
overflowX: "visible",
|
||||||
|
padding: 0,
|
||||||
|
},
|
||||||
|
scrollable: {
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
overflowY: "scroll",
|
||||||
|
maxHeight: 450,
|
||||||
|
marginLeft: -15,
|
||||||
|
paddingLeft: 15,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{ name: "TaxCountryDialog" },
|
||||||
|
);
|
70
src/taxes/components/TaxInput/TaxInput.tsx
Normal file
70
src/taxes/components/TaxInput/TaxInput.tsx
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
import { InputAdornment, TextField, TextFieldProps } from "@material-ui/core";
|
||||||
|
import { findPriceSeparator } from "@saleor/components/PriceField/utils";
|
||||||
|
import { FormChange } from "@saleor/hooks/useForm";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import { useStyles } from "./styles";
|
||||||
|
|
||||||
|
interface TaxInputProps {
|
||||||
|
placeholder?: string;
|
||||||
|
value: string | undefined;
|
||||||
|
change: FormChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TaxInput: React.FC<TaxInputProps> = ({
|
||||||
|
placeholder,
|
||||||
|
value,
|
||||||
|
change,
|
||||||
|
}) => {
|
||||||
|
const classes = useStyles();
|
||||||
|
|
||||||
|
const handleChange: FormChange = e => {
|
||||||
|
let value = e.target.value;
|
||||||
|
const splitCharacter = findPriceSeparator(value);
|
||||||
|
const [integerPart, decimalPart] = value.split(splitCharacter);
|
||||||
|
|
||||||
|
if (decimalPart?.length > 3) {
|
||||||
|
const shortenedDecimalPart = decimalPart.slice(0, 3);
|
||||||
|
value = `${integerPart}${splitCharacter}${shortenedDecimalPart}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
change({
|
||||||
|
target: {
|
||||||
|
name: e.target.name,
|
||||||
|
value,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const handleKeyDown: TextFieldProps["onKeyDown"] = event => {
|
||||||
|
switch (event.key.toLowerCase()) {
|
||||||
|
case "e":
|
||||||
|
case "-": {
|
||||||
|
event.preventDefault();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TextField
|
||||||
|
type="number"
|
||||||
|
fullWidth
|
||||||
|
placeholder={placeholder}
|
||||||
|
value={value}
|
||||||
|
InputProps={{
|
||||||
|
startAdornment: <InputAdornment position="start">%</InputAdornment>,
|
||||||
|
className: classes.hideSpinboxes,
|
||||||
|
}}
|
||||||
|
inputProps={{
|
||||||
|
className: classes.inputPadding,
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
step: 0.001,
|
||||||
|
}}
|
||||||
|
onChange={handleChange}
|
||||||
|
onKeyDown={handleKeyDown}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TaxInput;
|
2
src/taxes/components/TaxInput/index.ts
Normal file
2
src/taxes/components/TaxInput/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export { default } from "./TaxInput";
|
||||||
|
export * from "./TaxInput";
|
26
src/taxes/components/TaxInput/styles.ts
Normal file
26
src/taxes/components/TaxInput/styles.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import { makeStyles } from "@saleor/macaw-ui";
|
||||||
|
|
||||||
|
export const useStyles = makeStyles(
|
||||||
|
() => ({
|
||||||
|
/**
|
||||||
|
* Spinboxes are up & down arrows that are used to change the value of a number
|
||||||
|
* in html input elements with type=number. There is a different styling for
|
||||||
|
* hiding them, dependent on browser (as of mid-2022).
|
||||||
|
*/
|
||||||
|
hideSpinboxes: {
|
||||||
|
// chrome, safari
|
||||||
|
"& input::-webkit-outer-spin-button, input::-webkit-inner-spin-button": {
|
||||||
|
appearance: "none",
|
||||||
|
margin: 0,
|
||||||
|
},
|
||||||
|
// firefox
|
||||||
|
"& input": {
|
||||||
|
"-moz-appearance": "textfield",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
inputPadding: {
|
||||||
|
padding: "16px 0 16px 0",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{ name: "TaxInput" },
|
||||||
|
);
|
195
src/taxes/fixtures.ts
Normal file
195
src/taxes/fixtures.ts
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
import {
|
||||||
|
TaxCalculationStrategy,
|
||||||
|
TaxClassFragment,
|
||||||
|
TaxConfigurationFragment,
|
||||||
|
TaxCountryConfigurationFragment,
|
||||||
|
} from "@saleor/graphql";
|
||||||
|
|
||||||
|
export const taxConfigurations: TaxConfigurationFragment[] = [
|
||||||
|
{
|
||||||
|
__typename: "TaxConfiguration",
|
||||||
|
id: "taxConf1",
|
||||||
|
channel: {
|
||||||
|
__typename: "Channel",
|
||||||
|
id: "taxChannel1",
|
||||||
|
name: "Channel USD",
|
||||||
|
},
|
||||||
|
displayGrossPrices: true,
|
||||||
|
pricesEnteredWithTax: false,
|
||||||
|
chargeTaxes: true,
|
||||||
|
taxCalculationStrategy: TaxCalculationStrategy.FLAT_RATES,
|
||||||
|
countries: [
|
||||||
|
{
|
||||||
|
__typename: "TaxConfigurationPerCountry",
|
||||||
|
country: {
|
||||||
|
__typename: "CountryDisplay",
|
||||||
|
code: "AF",
|
||||||
|
country: "Afghanistan",
|
||||||
|
},
|
||||||
|
chargeTaxes: false,
|
||||||
|
taxCalculationStrategy: null,
|
||||||
|
displayGrossPrices: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
__typename: "TaxConfigurationPerCountry",
|
||||||
|
country: {
|
||||||
|
__typename: "CountryDisplay",
|
||||||
|
code: "AX",
|
||||||
|
country: "Åland Islands",
|
||||||
|
},
|
||||||
|
chargeTaxes: true,
|
||||||
|
taxCalculationStrategy: TaxCalculationStrategy.TAX_APP,
|
||||||
|
displayGrossPrices: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
__typename: "TaxConfiguration",
|
||||||
|
id: "taxConf2",
|
||||||
|
channel: {
|
||||||
|
__typename: "Channel",
|
||||||
|
id: "taxChannel2",
|
||||||
|
name: "Channel PLN",
|
||||||
|
},
|
||||||
|
displayGrossPrices: false,
|
||||||
|
pricesEnteredWithTax: true,
|
||||||
|
chargeTaxes: true,
|
||||||
|
taxCalculationStrategy: TaxCalculationStrategy.TAX_APP,
|
||||||
|
countries: [
|
||||||
|
{
|
||||||
|
__typename: "TaxConfigurationPerCountry",
|
||||||
|
country: {
|
||||||
|
__typename: "CountryDisplay",
|
||||||
|
code: "AL",
|
||||||
|
country: "Albania",
|
||||||
|
},
|
||||||
|
chargeTaxes: true,
|
||||||
|
taxCalculationStrategy: TaxCalculationStrategy.FLAT_RATES,
|
||||||
|
displayGrossPrices: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
__typename: "TaxConfigurationPerCountry",
|
||||||
|
country: {
|
||||||
|
__typename: "CountryDisplay",
|
||||||
|
code: "DZ",
|
||||||
|
country: "Algeria",
|
||||||
|
},
|
||||||
|
chargeTaxes: false,
|
||||||
|
taxCalculationStrategy: null,
|
||||||
|
displayGrossPrices: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const taxCountryConfigurations: TaxCountryConfigurationFragment[] = [
|
||||||
|
{
|
||||||
|
__typename: "TaxCountryConfiguration",
|
||||||
|
country: {
|
||||||
|
__typename: "CountryDisplay",
|
||||||
|
code: "AF",
|
||||||
|
country: "Afghanistan",
|
||||||
|
},
|
||||||
|
taxClassCountryRates: [
|
||||||
|
{
|
||||||
|
__typename: "TaxClassCountryRate",
|
||||||
|
rate: 0.31,
|
||||||
|
taxClass: {
|
||||||
|
__typename: "TaxClass",
|
||||||
|
id: "taxCountryConfigurations.0.taxClassCountryRates.0.taxClass.id",
|
||||||
|
name: "Default tax class",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
__typename: "TaxClassCountryRate",
|
||||||
|
rate: 0.05,
|
||||||
|
taxClass: {
|
||||||
|
__typename: "TaxClass",
|
||||||
|
id: "taxCountryConfigurations.0.taxClassCountryRates.0.taxClass.id",
|
||||||
|
name: "Perfume",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
__typename: "TaxCountryConfiguration",
|
||||||
|
country: {
|
||||||
|
__typename: "CountryDisplay",
|
||||||
|
code: "AX",
|
||||||
|
country: "Åland Islands",
|
||||||
|
},
|
||||||
|
taxClassCountryRates: [
|
||||||
|
{
|
||||||
|
__typename: "TaxClassCountryRate",
|
||||||
|
rate: 0.21,
|
||||||
|
taxClass: {
|
||||||
|
__typename: "TaxClass",
|
||||||
|
id: "taxCountryConfigurations.0.taxClassCountryRates.0.taxClass.id",
|
||||||
|
name: "Default tax class",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
__typename: "TaxClassCountryRate",
|
||||||
|
rate: 0.05,
|
||||||
|
taxClass: {
|
||||||
|
__typename: "TaxClass",
|
||||||
|
id: "taxCountryConfigurations.0.taxClassCountryRates.0.taxClass.id",
|
||||||
|
name: "Food",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const taxClasses: TaxClassFragment[] = [
|
||||||
|
{
|
||||||
|
__typename: "TaxClass",
|
||||||
|
id: "taxClassNode1",
|
||||||
|
name: "Default tax class",
|
||||||
|
countries: [
|
||||||
|
{
|
||||||
|
__typename: "TaxClassCountryRate",
|
||||||
|
country: {
|
||||||
|
__typename: "CountryDisplay",
|
||||||
|
code: "AX",
|
||||||
|
country: "Åland Islands",
|
||||||
|
},
|
||||||
|
rate: 0.2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
__typename: "TaxClassCountryRate",
|
||||||
|
country: {
|
||||||
|
__typename: "CountryDisplay",
|
||||||
|
code: "AF",
|
||||||
|
country: "Afghanistan",
|
||||||
|
},
|
||||||
|
rate: 0.15,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
__typename: "TaxClass",
|
||||||
|
id: "taxClassesNode2",
|
||||||
|
name: "Food",
|
||||||
|
countries: [
|
||||||
|
{
|
||||||
|
__typename: "TaxClassCountryRate",
|
||||||
|
country: {
|
||||||
|
__typename: "CountryDisplay",
|
||||||
|
code: "AX",
|
||||||
|
country: "Åland Islands",
|
||||||
|
},
|
||||||
|
rate: 0.05,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
__typename: "TaxClassCountryRate",
|
||||||
|
country: {
|
||||||
|
__typename: "CountryDisplay",
|
||||||
|
code: "AF",
|
||||||
|
country: "Afghanistan",
|
||||||
|
},
|
||||||
|
rate: 0.0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
|
@ -1,18 +1,50 @@
|
||||||
import { sectionNames } from "@saleor/intl";
|
import { sectionNames } from "@saleor/intl";
|
||||||
|
import { parse as parseQs } from "qs";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
import { Route, RouteComponentProps, Switch } from "react-router-dom";
|
import { Route, RouteComponentProps, Switch } from "react-router-dom";
|
||||||
|
|
||||||
import { WindowTitle } from "../components/WindowTitle";
|
import { WindowTitle } from "../components/WindowTitle";
|
||||||
import { countryListPath, countryTaxRatesPath } from "./urls";
|
import {
|
||||||
import CountryList from "./views/CountryList";
|
taxClassesListUrl,
|
||||||
import CountryTaxesComponent, {
|
taxConfigurationListPath,
|
||||||
CountryTaxesParams,
|
taxCountriesListPath,
|
||||||
} from "./views/CountryTaxes";
|
TaxesUrlQueryParams,
|
||||||
|
} from "./urls";
|
||||||
|
import TaxChannelsListComponent from "./views/TaxChannelsList";
|
||||||
|
import TaxClassesListComponent from "./views/TaxClassesList";
|
||||||
|
import TaxCountriesListComponent from "./views/TaxCountriesList";
|
||||||
|
|
||||||
const CountryTaxes: React.FC<RouteComponentProps<CountryTaxesParams>> = ({
|
const TaxChannelsList: React.FC<RouteComponentProps<{ id: string }>> = ({
|
||||||
match,
|
match,
|
||||||
}) => <CountryTaxesComponent code={match.params.code} />;
|
location,
|
||||||
|
}) => {
|
||||||
|
const qs: TaxesUrlQueryParams = parseQs(location.search.substring(1));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TaxChannelsListComponent
|
||||||
|
id={decodeURIComponent(match.params.id)}
|
||||||
|
params={qs}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const TaxCountriesList: React.FC<RouteComponentProps<{ id: string }>> = ({
|
||||||
|
match,
|
||||||
|
}) => {
|
||||||
|
const qs: TaxesUrlQueryParams = parseQs(location.search.substring(1));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TaxCountriesListComponent
|
||||||
|
id={decodeURIComponent(match.params.id)}
|
||||||
|
params={qs}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const TaxClassesList: React.FC<RouteComponentProps<{ id: string }>> = ({
|
||||||
|
match,
|
||||||
|
}) => <TaxClassesListComponent id={decodeURIComponent(match.params.id)} />;
|
||||||
|
|
||||||
const Component = () => {
|
const Component = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
@ -21,12 +53,18 @@ const Component = () => {
|
||||||
<>
|
<>
|
||||||
<WindowTitle title={intl.formatMessage(sectionNames.taxes)} />
|
<WindowTitle title={intl.formatMessage(sectionNames.taxes)} />
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact path={countryListPath} component={CountryList} />
|
|
||||||
<Route
|
<Route
|
||||||
exact
|
path={taxConfigurationListPath(":id")}
|
||||||
path={countryTaxRatesPath(":code")}
|
component={TaxChannelsList}
|
||||||
component={CountryTaxes}
|
|
||||||
/>
|
/>
|
||||||
|
<Route path={taxConfigurationListPath()} component={TaxChannelsList} />
|
||||||
|
<Route
|
||||||
|
path={taxCountriesListPath(":id")}
|
||||||
|
component={TaxCountriesList}
|
||||||
|
/>
|
||||||
|
<Route path={taxCountriesListPath()} component={TaxCountriesList} />
|
||||||
|
<Route path={taxClassesListUrl(":id")} component={TaxClassesList} />
|
||||||
|
<Route path={taxClassesListUrl()} component={TaxClassesList} />
|
||||||
</Switch>
|
</Switch>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
200
src/taxes/messages.ts
Normal file
200
src/taxes/messages.ts
Normal file
|
@ -0,0 +1,200 @@
|
||||||
|
import { defineMessages } from "react-intl";
|
||||||
|
|
||||||
|
export const taxesMessages = defineMessages({
|
||||||
|
taxClass: {
|
||||||
|
id: "bDBiac",
|
||||||
|
defaultMessage: "Tax class",
|
||||||
|
description: "dropdown or column label",
|
||||||
|
},
|
||||||
|
channelsSection: {
|
||||||
|
id: "b2DlTO",
|
||||||
|
defaultMessage: "Channels",
|
||||||
|
description: "Taxes section title",
|
||||||
|
},
|
||||||
|
countriesSection: {
|
||||||
|
id: "ZAaXfz",
|
||||||
|
defaultMessage: "Countries",
|
||||||
|
description: "Taxes section title",
|
||||||
|
},
|
||||||
|
taxClassesSection: {
|
||||||
|
id: "aJm/by",
|
||||||
|
defaultMessage: "Tax classes",
|
||||||
|
description: "Taxes section title",
|
||||||
|
},
|
||||||
|
channelList: {
|
||||||
|
id: "yLfbSh",
|
||||||
|
defaultMessage: "Channel name",
|
||||||
|
description: "support label",
|
||||||
|
},
|
||||||
|
defaultSettings: {
|
||||||
|
id: "pWClYm",
|
||||||
|
defaultMessage: "Default settings",
|
||||||
|
description: "card title",
|
||||||
|
},
|
||||||
|
countryExceptions: {
|
||||||
|
id: "+2VydL",
|
||||||
|
defaultMessage: "Country exceptions",
|
||||||
|
description: "card title",
|
||||||
|
},
|
||||||
|
enteredPrices: {
|
||||||
|
id: "puRlnN",
|
||||||
|
defaultMessage: "Entered prices",
|
||||||
|
description: "card subtitle",
|
||||||
|
},
|
||||||
|
renderedPrices: {
|
||||||
|
id: "98Nw4g",
|
||||||
|
defaultMessage: "Rendered prices",
|
||||||
|
description: "card subtitle",
|
||||||
|
},
|
||||||
|
chargeTaxes: {
|
||||||
|
id: "EYkW1J",
|
||||||
|
defaultMessage: "Charge taxes for this channel",
|
||||||
|
description: "checkbox label",
|
||||||
|
},
|
||||||
|
pricesWithTaxLabel: {
|
||||||
|
id: "cVjewM",
|
||||||
|
defaultMessage: "Product prices are entered with tax",
|
||||||
|
description: "label for radio button",
|
||||||
|
},
|
||||||
|
pricesWithoutTaxLabel: {
|
||||||
|
id: "QpBqa9",
|
||||||
|
defaultMessage: "Product prices are entered without tax",
|
||||||
|
description: "label for radio button",
|
||||||
|
},
|
||||||
|
addCountryLabel: {
|
||||||
|
id: "/5r4he",
|
||||||
|
defaultMessage: "Add country",
|
||||||
|
description: "label for button",
|
||||||
|
},
|
||||||
|
countryNameHeader: {
|
||||||
|
id: "D5Wtf/",
|
||||||
|
defaultMessage: "Country name",
|
||||||
|
description: "table header column",
|
||||||
|
},
|
||||||
|
chargeTaxesHeader: {
|
||||||
|
id: "kXqn6A",
|
||||||
|
defaultMessage: "Charge taxes",
|
||||||
|
description: "table header column",
|
||||||
|
},
|
||||||
|
showGrossHeader: {
|
||||||
|
id: "skklRz",
|
||||||
|
defaultMessage: "Show gross prices in storefront",
|
||||||
|
description: "table header column",
|
||||||
|
},
|
||||||
|
countryList: {
|
||||||
|
id: "CFT171",
|
||||||
|
defaultMessage: "Country list",
|
||||||
|
description: "card header title",
|
||||||
|
},
|
||||||
|
taxClassRatesHeader: {
|
||||||
|
id: "WIxSDm",
|
||||||
|
defaultMessage: "{country} class rates",
|
||||||
|
description: "card header",
|
||||||
|
},
|
||||||
|
searchTaxClasses: {
|
||||||
|
id: "Ww69SE",
|
||||||
|
defaultMessage: "Search tax classes",
|
||||||
|
description: "search input placeholder",
|
||||||
|
},
|
||||||
|
taxNameHeader: {
|
||||||
|
id: "qbcNjQ",
|
||||||
|
defaultMessage: "Tax name",
|
||||||
|
description: "table header column",
|
||||||
|
},
|
||||||
|
taxRateHeader: {
|
||||||
|
id: "Nj9iSB",
|
||||||
|
defaultMessage: "Tax rate",
|
||||||
|
description: "table header column",
|
||||||
|
},
|
||||||
|
generalInformation: {
|
||||||
|
id: "TfzIXS",
|
||||||
|
defaultMessage: "General information",
|
||||||
|
description: "tax classes card header",
|
||||||
|
},
|
||||||
|
taxRateName: {
|
||||||
|
id: "720c51",
|
||||||
|
defaultMessage: "Tax rate name",
|
||||||
|
description: "tax classes name input placeholder",
|
||||||
|
},
|
||||||
|
taxClassRates: {
|
||||||
|
id: "RqtZQ6",
|
||||||
|
defaultMessage: "Tax class rates",
|
||||||
|
description: "tax classes card header",
|
||||||
|
},
|
||||||
|
taxClassList: {
|
||||||
|
id: "jMzyU8",
|
||||||
|
defaultMessage: "Tax classes",
|
||||||
|
description: "tax classes card header",
|
||||||
|
},
|
||||||
|
addTaxClassLabel: {
|
||||||
|
id: "NlEVVT",
|
||||||
|
defaultMessage: "Create class",
|
||||||
|
description: "label for button",
|
||||||
|
},
|
||||||
|
taxClassNameHeader: {
|
||||||
|
id: "/ILyIf",
|
||||||
|
defaultMessage: "Tax class label",
|
||||||
|
description: "tax classes menu header",
|
||||||
|
},
|
||||||
|
noExceptionsForChannel: {
|
||||||
|
id: "u34css",
|
||||||
|
defaultMessage: "There are no exceptions for this channel",
|
||||||
|
description: "label for empty list in channels list",
|
||||||
|
},
|
||||||
|
chooseCountryDialogTitle: {
|
||||||
|
id: "0V1q0d",
|
||||||
|
defaultMessage: "Choose country you want to add",
|
||||||
|
description: "add country dialog header",
|
||||||
|
},
|
||||||
|
country: {
|
||||||
|
id: "UBuKZ9",
|
||||||
|
defaultMessage: "Country",
|
||||||
|
description: "searchbar placeholder",
|
||||||
|
},
|
||||||
|
noCountriesAssigned: {
|
||||||
|
id: "0a0fLZ",
|
||||||
|
defaultMessage: "There are no countries assigned",
|
||||||
|
description: "countries list menu label when no countries are assigned",
|
||||||
|
},
|
||||||
|
addCountryToAccessClass: {
|
||||||
|
id: "7U/NPm",
|
||||||
|
defaultMessage: "Add country to access tax classes",
|
||||||
|
description: "tax class rates list label when no country is selected",
|
||||||
|
},
|
||||||
|
countryDefaultRate: {
|
||||||
|
id: "lnteBJ",
|
||||||
|
defaultMessage: "Country default rate",
|
||||||
|
description: "country rates list label for the default rate",
|
||||||
|
},
|
||||||
|
noRatesInTaxClass: {
|
||||||
|
id: "ngAgBy",
|
||||||
|
defaultMessage:
|
||||||
|
"There are no countries using this tax class yet, use {tab} tab to assign tax rates.",
|
||||||
|
description: "tax class rates list label when no countries are assigned",
|
||||||
|
},
|
||||||
|
newTaxClass: {
|
||||||
|
id: "8BBMRj",
|
||||||
|
defaultMessage: "New tax class",
|
||||||
|
description: "default tax class name for new tax classes",
|
||||||
|
},
|
||||||
|
taxStrategyTaxApp: {
|
||||||
|
id: "TJ7WHA",
|
||||||
|
defaultMessage: "Use tax app",
|
||||||
|
description: "tax strategy combobox choice",
|
||||||
|
},
|
||||||
|
taxStrategyFlatRates: {
|
||||||
|
id: "4p3bjX",
|
||||||
|
defaultMessage: "Use flat rates",
|
||||||
|
description: "tax strategy combobox choice",
|
||||||
|
},
|
||||||
|
taxStrategyHint: {
|
||||||
|
id: "6HHPFy",
|
||||||
|
defaultMessage: "Select the method of tax calculation",
|
||||||
|
description: "tax strategy combobox hint",
|
||||||
|
},
|
||||||
|
noTaxClasses: {
|
||||||
|
id: "Rfk+8B",
|
||||||
|
defaultMessage: "There are no tax classes",
|
||||||
|
description: "tax classes menu label when there are no tax classes",
|
||||||
|
},
|
||||||
|
});
|
|
@ -1,28 +1,84 @@
|
||||||
import { gql } from "@apollo/client";
|
import { gql } from "@apollo/client";
|
||||||
|
|
||||||
export const updateTaxSettings = gql`
|
export const taxConfigurationUpdate = gql`
|
||||||
mutation UpdateTaxSettings($input: ShopSettingsInput!) {
|
mutation TaxConfigurationUpdate(
|
||||||
shopSettingsUpdate(input: $input) {
|
$id: ID!
|
||||||
|
$input: TaxConfigurationUpdateInput!
|
||||||
|
) {
|
||||||
|
taxConfigurationUpdate(id: $id, input: $input) {
|
||||||
errors {
|
errors {
|
||||||
...ShopSettingsUpdateErrorFragment
|
...TaxConfigurationUpdateErrorFragment
|
||||||
}
|
}
|
||||||
shop {
|
taxConfiguration {
|
||||||
...ShopTaxes
|
...TaxConfiguration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const fetchTaxes = gql`
|
export const taxCountryConfigurationUpdate = gql`
|
||||||
mutation FetchTaxes {
|
mutation TaxCountryConfigurationUpdate(
|
||||||
shopFetchTaxRates {
|
$countryCode: CountryCode!
|
||||||
|
$updateTaxClassRates: [TaxClassRateInput!]!
|
||||||
|
) {
|
||||||
|
taxCountryConfigurationUpdate(
|
||||||
|
countryCode: $countryCode
|
||||||
|
updateTaxClassRates: $updateTaxClassRates
|
||||||
|
) {
|
||||||
errors {
|
errors {
|
||||||
...ShopFetchTaxRatesErrorFragment
|
...TaxCountryConfigurationUpdateErrorFragment
|
||||||
}
|
}
|
||||||
shop {
|
taxCountryConfiguration {
|
||||||
countries {
|
...TaxCountryConfiguration
|
||||||
...Country
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const taxCountryConfigurationDelete = gql`
|
||||||
|
mutation TaxCountryConfigurationDelete($countryCode: CountryCode!) {
|
||||||
|
taxCountryConfigurationDelete(countryCode: $countryCode) {
|
||||||
|
errors {
|
||||||
|
...TaxCountryConfigurationDeleteErrorFragment
|
||||||
|
}
|
||||||
|
taxCountryConfiguration {
|
||||||
|
...TaxCountryConfiguration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const taxClassUpdate = gql`
|
||||||
|
mutation TaxClassUpdate($id: ID!, $input: TaxClassUpdateInput!) {
|
||||||
|
taxClassUpdate(id: $id, input: $input) {
|
||||||
|
errors {
|
||||||
|
...TaxClassUpdateErrorFragment
|
||||||
|
}
|
||||||
|
taxClass {
|
||||||
|
...TaxClass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const taxClassCreate = gql`
|
||||||
|
mutation TaxClassCreate($input: TaxClassCreateInput!) {
|
||||||
|
taxClassCreate(input: $input) {
|
||||||
|
errors {
|
||||||
|
...TaxClassCreateErrorFragment
|
||||||
|
}
|
||||||
|
taxClass {
|
||||||
|
...TaxClass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const taxClassDelete = gql`
|
||||||
|
mutation TaxClassDelete($id: ID!) {
|
||||||
|
taxClassDelete(id: $id) {
|
||||||
|
errors {
|
||||||
|
...TaxClassDeleteErrorFragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
import { Card, Divider } from "@material-ui/core";
|
||||||
|
import ListItemLink from "@saleor/components/ListItemLink";
|
||||||
|
import Skeleton from "@saleor/components/Skeleton";
|
||||||
|
import { TaxConfigurationFragment } from "@saleor/graphql";
|
||||||
|
import { List, ListHeader, ListItem, ListItemCell } from "@saleor/macaw-ui";
|
||||||
|
import { taxesMessages } from "@saleor/taxes/messages";
|
||||||
|
import { taxConfigurationListUrl } from "@saleor/taxes/urls";
|
||||||
|
import { isLastElement } from "@saleor/taxes/utils/utils";
|
||||||
|
import clsx from "classnames";
|
||||||
|
import React from "react";
|
||||||
|
import { FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
|
import { useStyles } from "./styles";
|
||||||
|
|
||||||
|
interface TaxChannelsMenuProps {
|
||||||
|
configurations: TaxConfigurationFragment[] | undefined;
|
||||||
|
selectedConfigurationId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TaxChannelsMenu: React.FC<TaxChannelsMenuProps> = ({
|
||||||
|
configurations,
|
||||||
|
selectedConfigurationId,
|
||||||
|
}) => {
|
||||||
|
const classes = useStyles();
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<List gridTemplate={["1fr"]}>
|
||||||
|
<ListHeader>
|
||||||
|
<ListItem className={classes.tableRow}>
|
||||||
|
<ListItemCell>
|
||||||
|
<FormattedMessage {...taxesMessages.channelList} />
|
||||||
|
</ListItemCell>
|
||||||
|
</ListItem>
|
||||||
|
</ListHeader>
|
||||||
|
<Divider />
|
||||||
|
{configurations?.map((configuration, confIndex) => (
|
||||||
|
<React.Fragment key={configuration.id}>
|
||||||
|
<ListItemLink
|
||||||
|
className={clsx(classes.clickable, classes.tableRow, {
|
||||||
|
[classes.selected]:
|
||||||
|
configuration.id === selectedConfigurationId,
|
||||||
|
})}
|
||||||
|
href={taxConfigurationListUrl(configuration.id)}
|
||||||
|
>
|
||||||
|
<ListItemCell className={classes.ellipsis}>
|
||||||
|
{configuration.channel.name}
|
||||||
|
</ListItemCell>
|
||||||
|
</ListItemLink>
|
||||||
|
{!isLastElement(configurations, confIndex) && <Divider />}
|
||||||
|
</React.Fragment>
|
||||||
|
)) ?? <Skeleton />}
|
||||||
|
</List>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TaxChannelsMenu;
|
2
src/taxes/pages/TaxChannelsPage/TaxChannelsMenu/index.ts
Normal file
2
src/taxes/pages/TaxChannelsPage/TaxChannelsMenu/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export { default } from "./TaxChannelsMenu";
|
||||||
|
export * from "./TaxChannelsMenu";
|
30
src/taxes/pages/TaxChannelsPage/TaxChannelsMenu/styles.ts
Normal file
30
src/taxes/pages/TaxChannelsPage/TaxChannelsMenu/styles.ts
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import { makeStyles } from "@saleor/macaw-ui";
|
||||||
|
|
||||||
|
export const useStyles = makeStyles(
|
||||||
|
theme => ({
|
||||||
|
clickable: {
|
||||||
|
cursor: "pointer",
|
||||||
|
},
|
||||||
|
ellipsis: {
|
||||||
|
textOverflow: "ellipsis",
|
||||||
|
overflow: "hidden",
|
||||||
|
},
|
||||||
|
tableRow: {
|
||||||
|
minHeight: "48px",
|
||||||
|
"&::after": {
|
||||||
|
display: "none",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
selected: {
|
||||||
|
"&&&:before": {
|
||||||
|
display: "visible",
|
||||||
|
position: "absolute",
|
||||||
|
left: 0,
|
||||||
|
width: "4px",
|
||||||
|
height: "100%",
|
||||||
|
backgroundColor: theme.palette.saleor.active[1],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{ name: "TaxChannelsMenu" },
|
||||||
|
);
|
37
src/taxes/pages/TaxChannelsPage/TaxChannelsPage.stories.tsx
Normal file
37
src/taxes/pages/TaxChannelsPage/TaxChannelsPage.stories.tsx
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import { countries } from "@saleor/fixtures";
|
||||||
|
import { CountryFragment } from "@saleor/graphql";
|
||||||
|
import Decorator from "@saleor/storybook/Decorator";
|
||||||
|
import { taxConfigurations } from "@saleor/taxes/fixtures";
|
||||||
|
import { storiesOf } from "@storybook/react";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import TaxChannelsPage from "./TaxChannelsPage";
|
||||||
|
|
||||||
|
export const castedCountries = countries.map(
|
||||||
|
({ code, name }): CountryFragment => ({
|
||||||
|
code,
|
||||||
|
country: name,
|
||||||
|
__typename: "CountryDisplay",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
taxConfigurations,
|
||||||
|
selectedConfigurationId: taxConfigurations[0].id,
|
||||||
|
handleTabChange: () => undefined,
|
||||||
|
allCountries: castedCountries,
|
||||||
|
isDialogOpen: false,
|
||||||
|
openDialog: () => undefined,
|
||||||
|
closeDialog: () => undefined,
|
||||||
|
onSubmit: () => undefined,
|
||||||
|
savebarState: "default" as const,
|
||||||
|
disabled: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
storiesOf("Views / Taxes / Channels view", module)
|
||||||
|
.addDecorator(Decorator)
|
||||||
|
.add("loading", () => (
|
||||||
|
<TaxChannelsPage {...props} taxConfigurations={undefined} />
|
||||||
|
))
|
||||||
|
.add("default", () => <TaxChannelsPage {...props} />)
|
||||||
|
.add("add country", () => <TaxChannelsPage {...props} isDialogOpen={true} />);
|
303
src/taxes/pages/TaxChannelsPage/TaxChannelsPage.tsx
Normal file
303
src/taxes/pages/TaxChannelsPage/TaxChannelsPage.tsx
Normal file
|
@ -0,0 +1,303 @@
|
||||||
|
import { Card, CardContent, Divider } from "@material-ui/core";
|
||||||
|
import VerticalSpacer from "@saleor/apps/components/VerticalSpacer";
|
||||||
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
|
import Container from "@saleor/components/Container";
|
||||||
|
import Form from "@saleor/components/Form";
|
||||||
|
import Grid from "@saleor/components/Grid";
|
||||||
|
import PageHeader from "@saleor/components/PageHeader";
|
||||||
|
import Savebar from "@saleor/components/Savebar";
|
||||||
|
import Skeleton from "@saleor/components/Skeleton";
|
||||||
|
import { configurationMenuUrl } from "@saleor/configuration";
|
||||||
|
import {
|
||||||
|
CountryCode,
|
||||||
|
CountryFragment,
|
||||||
|
TaxCalculationStrategy,
|
||||||
|
TaxConfigurationFragment,
|
||||||
|
TaxConfigurationPerCountryFragment,
|
||||||
|
TaxConfigurationUpdateInput,
|
||||||
|
} from "@saleor/graphql";
|
||||||
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
|
import { sectionNames } from "@saleor/intl";
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
ConfirmButtonTransitionState,
|
||||||
|
List,
|
||||||
|
ListHeader,
|
||||||
|
ListItem,
|
||||||
|
ListItemCell,
|
||||||
|
PageTab,
|
||||||
|
PageTabs,
|
||||||
|
} from "@saleor/macaw-ui";
|
||||||
|
import TaxCountryDialog from "@saleor/taxes/components/TaxCountryDialog";
|
||||||
|
import { taxesMessages } from "@saleor/taxes/messages";
|
||||||
|
import { isLastElement } from "@saleor/taxes/utils/utils";
|
||||||
|
import React from "react";
|
||||||
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import { useStyles } from "./styles";
|
||||||
|
import TaxChannelsMenu from "./TaxChannelsMenu";
|
||||||
|
import TaxCountryExceptionListItem from "./TaxCountryExceptionListItem";
|
||||||
|
import TaxSettingsCard from "./TaxSettingsCard";
|
||||||
|
|
||||||
|
interface TaxChannelsPageProps {
|
||||||
|
taxConfigurations: TaxConfigurationFragment[] | undefined;
|
||||||
|
selectedConfigurationId: string;
|
||||||
|
handleTabChange: (tab: string) => void;
|
||||||
|
allCountries: CountryFragment[] | undefined;
|
||||||
|
isDialogOpen: boolean;
|
||||||
|
openDialog: (action?: string) => void;
|
||||||
|
closeDialog: () => void;
|
||||||
|
onSubmit: (input: TaxConfigurationUpdateInput) => void;
|
||||||
|
savebarState: ConfirmButtonTransitionState;
|
||||||
|
disabled: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TaxConfigurationFormData {
|
||||||
|
chargeTaxes: boolean;
|
||||||
|
taxCalculationStrategy: TaxCalculationStrategy;
|
||||||
|
displayGrossPrices: boolean;
|
||||||
|
pricesEnteredWithTax: boolean;
|
||||||
|
updateCountriesConfiguration: TaxConfigurationPerCountryFragment[];
|
||||||
|
removeCountriesConfiguration: CountryCode[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TaxChannelsPage: React.FC<TaxChannelsPageProps> = props => {
|
||||||
|
const {
|
||||||
|
taxConfigurations,
|
||||||
|
selectedConfigurationId,
|
||||||
|
handleTabChange,
|
||||||
|
allCountries,
|
||||||
|
isDialogOpen,
|
||||||
|
openDialog,
|
||||||
|
closeDialog,
|
||||||
|
onSubmit,
|
||||||
|
savebarState,
|
||||||
|
disabled,
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const intl = useIntl();
|
||||||
|
const classes = useStyles();
|
||||||
|
const navigate = useNavigator();
|
||||||
|
|
||||||
|
const currentTaxConfiguration = taxConfigurations?.find(
|
||||||
|
taxConfigurations => taxConfigurations.id === selectedConfigurationId,
|
||||||
|
);
|
||||||
|
|
||||||
|
const initialForm: TaxConfigurationFormData = {
|
||||||
|
chargeTaxes: currentTaxConfiguration?.chargeTaxes ?? false,
|
||||||
|
taxCalculationStrategy: currentTaxConfiguration?.taxCalculationStrategy,
|
||||||
|
displayGrossPrices: currentTaxConfiguration?.displayGrossPrices ?? false,
|
||||||
|
pricesEnteredWithTax:
|
||||||
|
currentTaxConfiguration?.pricesEnteredWithTax ?? false,
|
||||||
|
updateCountriesConfiguration: currentTaxConfiguration?.countries ?? [],
|
||||||
|
removeCountriesConfiguration: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = (data: TaxConfigurationFormData) => {
|
||||||
|
const { updateCountriesConfiguration, removeCountriesConfiguration } = data;
|
||||||
|
const parsedUpdate: TaxConfigurationUpdateInput["updateCountriesConfiguration"] = updateCountriesConfiguration.map(
|
||||||
|
config => ({
|
||||||
|
countryCode: config.country.code as CountryCode,
|
||||||
|
chargeTaxes: config.chargeTaxes,
|
||||||
|
taxCalculationStrategy: config.taxCalculationStrategy,
|
||||||
|
displayGrossPrices: config.displayGrossPrices,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
onSubmit({
|
||||||
|
chargeTaxes: data.chargeTaxes,
|
||||||
|
taxCalculationStrategy: data.chargeTaxes
|
||||||
|
? data.taxCalculationStrategy
|
||||||
|
: null,
|
||||||
|
displayGrossPrices: data.displayGrossPrices,
|
||||||
|
pricesEnteredWithTax: data.pricesEnteredWithTax,
|
||||||
|
updateCountriesConfiguration: parsedUpdate,
|
||||||
|
removeCountriesConfiguration,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const taxStrategyChoices = [
|
||||||
|
{
|
||||||
|
label: intl.formatMessage(taxesMessages.taxStrategyTaxApp),
|
||||||
|
value: TaxCalculationStrategy.TAX_APP,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: intl.formatMessage(taxesMessages.taxStrategyFlatRates),
|
||||||
|
value: TaxCalculationStrategy.FLAT_RATES,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Form initial={initialForm} onSubmit={handleSubmit} mergeData={false}>
|
||||||
|
{({ data, change, submit, set, triggerChange }) => {
|
||||||
|
const countryExceptions = data.updateCountriesConfiguration;
|
||||||
|
|
||||||
|
const handleExceptionChange = (event, index) => {
|
||||||
|
const { name, value } = event.target;
|
||||||
|
const currentExceptions = [...data.updateCountriesConfiguration];
|
||||||
|
const exceptionToChange = {
|
||||||
|
...data.updateCountriesConfiguration[index],
|
||||||
|
[name]: value,
|
||||||
|
};
|
||||||
|
currentExceptions[index] = exceptionToChange;
|
||||||
|
triggerChange();
|
||||||
|
set({ updateCountriesConfiguration: currentExceptions });
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCountryChange = (country: CountryFragment) => {
|
||||||
|
closeDialog();
|
||||||
|
const input: TaxConfigurationPerCountryFragment = {
|
||||||
|
__typename: "TaxConfigurationPerCountry",
|
||||||
|
country,
|
||||||
|
chargeTaxes: data.chargeTaxes,
|
||||||
|
displayGrossPrices: data.displayGrossPrices,
|
||||||
|
taxCalculationStrategy: data.taxCalculationStrategy,
|
||||||
|
};
|
||||||
|
const currentExceptions = data.updateCountriesConfiguration;
|
||||||
|
triggerChange();
|
||||||
|
set({
|
||||||
|
updateCountriesConfiguration: [input, ...currentExceptions],
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<PageHeader title={intl.formatMessage(sectionNames.taxes)} />
|
||||||
|
<PageTabs value="channels" onChange={handleTabChange}>
|
||||||
|
<PageTab
|
||||||
|
label={intl.formatMessage(taxesMessages.channelsSection)}
|
||||||
|
value="channels"
|
||||||
|
/>
|
||||||
|
<PageTab
|
||||||
|
label={intl.formatMessage(taxesMessages.countriesSection)}
|
||||||
|
value="countries"
|
||||||
|
/>
|
||||||
|
<PageTab
|
||||||
|
label={intl.formatMessage(taxesMessages.taxClassesSection)}
|
||||||
|
value="tax-classes"
|
||||||
|
/>
|
||||||
|
</PageTabs>
|
||||||
|
<VerticalSpacer spacing={2} />
|
||||||
|
<Grid variant="inverted">
|
||||||
|
<div>
|
||||||
|
<TaxChannelsMenu
|
||||||
|
configurations={taxConfigurations}
|
||||||
|
selectedConfigurationId={selectedConfigurationId}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<TaxSettingsCard
|
||||||
|
values={data}
|
||||||
|
strategyChoices={taxStrategyChoices}
|
||||||
|
onChange={change}
|
||||||
|
/>
|
||||||
|
<VerticalSpacer spacing={3} />
|
||||||
|
<Card>
|
||||||
|
<CardTitle
|
||||||
|
className={classes.toolbarMargin}
|
||||||
|
title={intl.formatMessage(taxesMessages.countryExceptions)}
|
||||||
|
toolbar={
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
onClick={() => openDialog("add-country")}
|
||||||
|
>
|
||||||
|
<FormattedMessage {...taxesMessages.addCountryLabel} />
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{countryExceptions?.length === 0 ? (
|
||||||
|
<CardContent>
|
||||||
|
<FormattedMessage
|
||||||
|
{...taxesMessages.noExceptionsForChannel}
|
||||||
|
/>
|
||||||
|
</CardContent>
|
||||||
|
) : (
|
||||||
|
<List gridTemplate={["4fr 3fr 3fr 1fr"]}>
|
||||||
|
<ListHeader>
|
||||||
|
<ListItem>
|
||||||
|
<ListItemCell>
|
||||||
|
<FormattedMessage
|
||||||
|
{...taxesMessages.countryNameHeader}
|
||||||
|
/>
|
||||||
|
</ListItemCell>
|
||||||
|
<ListItemCell className={classes.left}>
|
||||||
|
<FormattedMessage
|
||||||
|
{...taxesMessages.chargeTaxesHeader}
|
||||||
|
/>
|
||||||
|
</ListItemCell>
|
||||||
|
<ListItemCell className={classes.center}>
|
||||||
|
<FormattedMessage
|
||||||
|
{...taxesMessages.showGrossHeader}
|
||||||
|
/>
|
||||||
|
</ListItemCell>
|
||||||
|
<ListItemCell>
|
||||||
|
{/* This is required for the header row to be aligned with list items */}
|
||||||
|
<div className={classes.dummy}></div>
|
||||||
|
</ListItemCell>
|
||||||
|
</ListItem>
|
||||||
|
</ListHeader>
|
||||||
|
<Divider />
|
||||||
|
{countryExceptions?.map((country, countryIndex) => (
|
||||||
|
<TaxCountryExceptionListItem
|
||||||
|
divider={
|
||||||
|
!isLastElement(countryExceptions, countryIndex)
|
||||||
|
}
|
||||||
|
strategyChoices={taxStrategyChoices}
|
||||||
|
country={country}
|
||||||
|
key={country.country.code}
|
||||||
|
onDelete={() => {
|
||||||
|
const currentRemovals =
|
||||||
|
data.removeCountriesConfiguration;
|
||||||
|
const currentExceptions = [
|
||||||
|
...data.updateCountriesConfiguration,
|
||||||
|
];
|
||||||
|
set({
|
||||||
|
removeCountriesConfiguration: [
|
||||||
|
...currentRemovals,
|
||||||
|
country.country.code as CountryCode,
|
||||||
|
],
|
||||||
|
updateCountriesConfiguration: currentExceptions.filter(
|
||||||
|
exception =>
|
||||||
|
exception.country.code !==
|
||||||
|
country.country.code,
|
||||||
|
),
|
||||||
|
});
|
||||||
|
triggerChange();
|
||||||
|
}}
|
||||||
|
onChange={event =>
|
||||||
|
handleExceptionChange(event, countryIndex)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)) ?? <Skeleton />}
|
||||||
|
</List>
|
||||||
|
)}
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</Grid>
|
||||||
|
<Savebar
|
||||||
|
state={savebarState}
|
||||||
|
disabled={disabled}
|
||||||
|
onSubmit={submit}
|
||||||
|
onCancel={() => navigate(configurationMenuUrl)}
|
||||||
|
/>
|
||||||
|
{allCountries && (
|
||||||
|
<TaxCountryDialog
|
||||||
|
open={isDialogOpen}
|
||||||
|
countries={allCountries
|
||||||
|
.filter(
|
||||||
|
({ code }) =>
|
||||||
|
!countryExceptions?.some(
|
||||||
|
({ country }) => country.code === code,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.map(country => ({ checked: false, ...country }))}
|
||||||
|
onConfirm={handleCountryChange}
|
||||||
|
onClose={closeDialog}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Form>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default TaxChannelsPage;
|
|
@ -0,0 +1,75 @@
|
||||||
|
import { Divider } from "@material-ui/core";
|
||||||
|
import ControlledCheckbox from "@saleor/components/ControlledCheckbox";
|
||||||
|
import SingleSelectField, {
|
||||||
|
Choice,
|
||||||
|
} from "@saleor/components/SingleSelectField";
|
||||||
|
import {
|
||||||
|
TaxConfigurationPerCountryFragment,
|
||||||
|
TaxConfigurationUpdateInput,
|
||||||
|
} from "@saleor/graphql";
|
||||||
|
import { FormChange } from "@saleor/hooks/useForm";
|
||||||
|
import {
|
||||||
|
DeleteIcon,
|
||||||
|
IconButton,
|
||||||
|
ListItem,
|
||||||
|
ListItemCell,
|
||||||
|
} from "@saleor/macaw-ui";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import { useStyles } from "../styles";
|
||||||
|
|
||||||
|
interface TaxCountryExceptionListItemProps {
|
||||||
|
country: TaxConfigurationPerCountryFragment | undefined;
|
||||||
|
onDelete: () => void;
|
||||||
|
onChange: FormChange;
|
||||||
|
divider: boolean;
|
||||||
|
strategyChoices: Choice[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TaxCountryExceptionListItem: React.FC<TaxCountryExceptionListItemProps> = ({
|
||||||
|
country,
|
||||||
|
onDelete,
|
||||||
|
onChange,
|
||||||
|
strategyChoices,
|
||||||
|
divider = true,
|
||||||
|
}) => {
|
||||||
|
const classes = useStyles();
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ListItem hover={false} className={classes.noDivider}>
|
||||||
|
<ListItemCell>{country.country.country}</ListItemCell>
|
||||||
|
<ListItemCell className={classes.center}>
|
||||||
|
<ControlledCheckbox
|
||||||
|
className={classes.center}
|
||||||
|
checked={country.chargeTaxes}
|
||||||
|
name={"chargeTaxes" as keyof TaxConfigurationUpdateInput}
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
|
<SingleSelectField
|
||||||
|
className={classes.selectField}
|
||||||
|
choices={strategyChoices}
|
||||||
|
disabled={!country.chargeTaxes}
|
||||||
|
value={country.taxCalculationStrategy}
|
||||||
|
name={"taxCalculationStrategy" as keyof TaxConfigurationUpdateInput}
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
|
</ListItemCell>
|
||||||
|
<ListItemCell className={classes.center}>
|
||||||
|
<ControlledCheckbox
|
||||||
|
className={classes.center}
|
||||||
|
checked={country.displayGrossPrices}
|
||||||
|
name={"displayGrossPrices" as keyof TaxConfigurationUpdateInput}
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
|
</ListItemCell>
|
||||||
|
<ListItemCell>
|
||||||
|
<IconButton onClick={onDelete} variant="secondary">
|
||||||
|
<DeleteIcon />
|
||||||
|
</IconButton>
|
||||||
|
</ListItemCell>
|
||||||
|
</ListItem>
|
||||||
|
{divider && <Divider />}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default TaxCountryExceptionListItem;
|
|
@ -0,0 +1,2 @@
|
||||||
|
export { default } from "./TaxCountryExceptionListItem";
|
||||||
|
export * from "./TaxCountryExceptionListItem";
|
|
@ -0,0 +1,117 @@
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
Divider,
|
||||||
|
FormControlLabel,
|
||||||
|
Radio,
|
||||||
|
RadioGroup,
|
||||||
|
Typography,
|
||||||
|
} from "@material-ui/core";
|
||||||
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
|
import ControlledCheckbox from "@saleor/components/ControlledCheckbox";
|
||||||
|
import Grid from "@saleor/components/Grid";
|
||||||
|
import SingleSelectField, {
|
||||||
|
Choice,
|
||||||
|
} from "@saleor/components/SingleSelectField";
|
||||||
|
import { TaxConfigurationUpdateInput } from "@saleor/graphql";
|
||||||
|
import { FormChange } from "@saleor/hooks/useForm";
|
||||||
|
import { taxesMessages } from "@saleor/taxes/messages";
|
||||||
|
import React from "react";
|
||||||
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import { TaxConfigurationFormData } from "../TaxChannelsPage";
|
||||||
|
import { useStyles } from "./styles";
|
||||||
|
|
||||||
|
export interface TaxSettingsCardProps {
|
||||||
|
values: TaxConfigurationFormData;
|
||||||
|
strategyChoices: Choice[];
|
||||||
|
onChange: FormChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TaxSettingsCard: React.FC<TaxSettingsCardProps> = ({
|
||||||
|
values,
|
||||||
|
strategyChoices,
|
||||||
|
onChange,
|
||||||
|
}) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const classes = useStyles();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardTitle title={intl.formatMessage(taxesMessages.defaultSettings)} />
|
||||||
|
<CardContent>
|
||||||
|
<Typography className={classes.supportHeader}>
|
||||||
|
<FormattedMessage {...taxesMessages.chargeTaxesHeader} />
|
||||||
|
</Typography>
|
||||||
|
<div className={classes.taxStrategySection}>
|
||||||
|
<ControlledCheckbox
|
||||||
|
checked={values.chargeTaxes}
|
||||||
|
name={"chargeTaxes" as keyof TaxConfigurationUpdateInput}
|
||||||
|
onChange={onChange}
|
||||||
|
label={intl.formatMessage(taxesMessages.chargeTaxes)}
|
||||||
|
/>
|
||||||
|
<div className={classes.singleSelectWrapper}>
|
||||||
|
<span className={classes.hint}>
|
||||||
|
<FormattedMessage {...taxesMessages.taxStrategyHint} />{" "}
|
||||||
|
</span>
|
||||||
|
<SingleSelectField
|
||||||
|
className={classes.singleSelectField}
|
||||||
|
choices={strategyChoices}
|
||||||
|
disabled={!values.chargeTaxes}
|
||||||
|
value={values.taxCalculationStrategy}
|
||||||
|
name={
|
||||||
|
"taxCalculationStrategy" as keyof TaxConfigurationUpdateInput
|
||||||
|
}
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
<Divider />
|
||||||
|
<CardContent>
|
||||||
|
<Grid variant="uniform">
|
||||||
|
<RadioGroup
|
||||||
|
value={values.pricesEnteredWithTax}
|
||||||
|
name={"pricesEnteredWithTax" as keyof TaxConfigurationUpdateInput}
|
||||||
|
onChange={e => {
|
||||||
|
onChange({
|
||||||
|
target: {
|
||||||
|
name: e.target.name,
|
||||||
|
value: e.target.value === "true",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
className={classes.showCheckboxShadows}
|
||||||
|
>
|
||||||
|
<Typography className={classes.supportHeader}>
|
||||||
|
<FormattedMessage {...taxesMessages.enteredPrices} />
|
||||||
|
</Typography>
|
||||||
|
<FormControlLabel
|
||||||
|
value={true}
|
||||||
|
control={<Radio />}
|
||||||
|
label={intl.formatMessage(taxesMessages.pricesWithTaxLabel)}
|
||||||
|
/>
|
||||||
|
<FormControlLabel
|
||||||
|
value={false}
|
||||||
|
control={<Radio />}
|
||||||
|
label={intl.formatMessage(taxesMessages.pricesWithoutTaxLabel)}
|
||||||
|
/>
|
||||||
|
</RadioGroup>
|
||||||
|
<div className={classes.showCheckboxShadows}>
|
||||||
|
<Typography className={classes.supportHeader}>
|
||||||
|
<FormattedMessage {...taxesMessages.renderedPrices} />
|
||||||
|
</Typography>
|
||||||
|
<ControlledCheckbox
|
||||||
|
label={intl.formatMessage(taxesMessages.showGrossHeader)}
|
||||||
|
name={"displayGrossPrices" as keyof TaxConfigurationUpdateInput}
|
||||||
|
checked={values.displayGrossPrices}
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Grid>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TaxSettingsCard;
|
2
src/taxes/pages/TaxChannelsPage/TaxSettingsCard/index.ts
Normal file
2
src/taxes/pages/TaxChannelsPage/TaxSettingsCard/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export { default } from "./TaxSettingsCard";
|
||||||
|
export * from "./TaxSettingsCard";
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue