feat(admin,admin-ui,medusa): Add Medusa Admin plugin (#3334)

This commit is contained in:
Kasper Fabricius Kristensen
2023-03-03 10:09:16 +01:00
committed by GitHub
parent d6b1ad1ccd
commit 40de54b010
928 changed files with 85441 additions and 384 deletions

View File

@@ -0,0 +1,18 @@
const units: [string, number][] = [
["B", 1],
["Kb", 1000],
["Mb", 1000000],
["Gb", 1000000000]
]
export function bytesConverter(size: number): string | undefined {
let result: string | undefined = undefined
for (const [unit, divider] of units) {
if (size >= divider) {
result = `${(size / divider).toFixed(2)} ${unit}`
}
}
return result
}

View File

@@ -0,0 +1,2 @@
export const callAll = (...fns: Function[]) => (...args) =>
fns?.forEach(async fn => typeof fn === "function" && fn(...args))

View File

@@ -0,0 +1,12 @@
export const getColor = (index: number): string => {
const colors = [
"bg-fuschia-40",
"bg-pink-40",
"bg-orange-40",
"bg-teal-40",
"bg-cyan-40",
"bg-blue-40",
"bg-indigo-40",
]
return colors[index % colors.length]
}

View File

@@ -0,0 +1,15 @@
export const consolidateImages = (images, uploaded) => {
const result: any[] = []
let i = 0
let j = 0
for (i = 0; i < images.length; i++) {
const image = images[i].url
if (image.startsWith("blob")) {
result.push(uploaded[j])
j++
} else {
result.push(image)
}
}
return result
}

View File

@@ -0,0 +1,9 @@
export const convertEmptyStringToNull = (data) => {
const obj = { ...data }
Object.keys(data).forEach((k) => {
if (obj[k] === "") {
obj[k] = null
}
})
return obj
}

View File

@@ -0,0 +1,638 @@
export const isoAlpha2Countries = {
AF: "Afghanistan",
AX: "Aland Islands",
AL: "Albania",
DZ: "Algeria",
AS: "American Samoa",
AD: "Andorra",
AO: "Angola",
AI: "Anguilla",
AQ: "Antarctica",
AG: "Antigua And Barbuda",
AR: "Argentina",
AM: "Armenia",
AW: "Aruba",
AU: "Australia",
AT: "Austria",
AZ: "Azerbaijan",
BS: "Bahamas",
BH: "Bahrain",
BD: "Bangladesh",
BB: "Barbados",
BY: "Belarus",
BE: "Belgium",
BZ: "Belize",
BJ: "Benin",
BM: "Bermuda",
BT: "Bhutan",
BO: "Bolivia",
BA: "Bosnia And Herzegovina",
BW: "Botswana",
BV: "Bouvet Island",
BR: "Brazil",
IO: "British Indian Ocean Territory",
BN: "Brunei Darussalam",
BG: "Bulgaria",
BF: "Burkina Faso",
BI: "Burundi",
KH: "Cambodia",
CM: "Cameroon",
CA: "Canada",
CV: "Cape Verde",
KY: "Cayman Islands",
CF: "Central African Republic",
TD: "Chad",
CL: "Chile",
CN: "China",
CX: "Christmas Island",
CC: "Cocos (Keeling) Islands",
CO: "Colombia",
KM: "Comoros",
CG: "Congo",
CD: "Congo, Democratic Republic",
CK: "Cook Islands",
CR: "Costa Rica",
CI: "Cote D'Ivoire",
HR: "Croatia",
CU: "Cuba",
CY: "Cyprus",
CZ: "Czech Republic",
DK: "Denmark",
DJ: "Djibouti",
DM: "Dominica",
DO: "Dominican Republic",
EC: "Ecuador",
EG: "Egypt",
SV: "El Salvador",
GQ: "Equatorial Guinea",
ER: "Eritrea",
EE: "Estonia",
ET: "Ethiopia",
FK: "Falkland Islands (Malvinas)",
FO: "Faroe Islands",
FJ: "Fiji",
FI: "Finland",
FR: "France",
GF: "French Guiana",
PF: "French Polynesia",
TF: "French Southern Territories",
GA: "Gabon",
GM: "Gambia",
GE: "Georgia",
DE: "Germany",
GH: "Ghana",
GI: "Gibraltar",
GR: "Greece",
GL: "Greenland",
GD: "Grenada",
GP: "Guadeloupe",
GU: "Guam",
GT: "Guatemala",
GG: "Guernsey",
GN: "Guinea",
GW: "Guinea-Bissau",
GY: "Guyana",
HT: "Haiti",
HM: "Heard Island & Mcdonald Islands",
VA: "Holy See (Vatican City State)",
HN: "Honduras",
HK: "Hong Kong",
HU: "Hungary",
IS: "Iceland",
IN: "India",
ID: "Indonesia",
IR: "Iran, Islamic Republic Of",
IQ: "Iraq",
IE: "Ireland",
IM: "Isle Of Man",
IL: "Israel",
IT: "Italy",
JM: "Jamaica",
JP: "Japan",
JE: "Jersey",
JO: "Jordan",
KZ: "Kazakhstan",
KE: "Kenya",
KI: "Kiribati",
KR: "South Korea",
KW: "Kuwait",
KG: "Kyrgyzstan",
LA: "Lao People's Democratic Republic",
LV: "Latvia",
LB: "Lebanon",
LS: "Lesotho",
LR: "Liberia",
LY: "Libyan Arab Jamahiriya",
LI: "Liechtenstein",
LT: "Lithuania",
LU: "Luxembourg",
MO: "Macao",
MK: "Macedonia",
MG: "Madagascar",
MW: "Malawi",
MY: "Malaysia",
MV: "Maldives",
ML: "Mali",
MT: "Malta",
MH: "Marshall Islands",
MQ: "Martinique",
MR: "Mauritania",
MU: "Mauritius",
YT: "Mayotte",
MX: "Mexico",
FM: "Micronesia, Federated States Of",
MD: "Moldova",
MC: "Monaco",
MN: "Mongolia",
ME: "Montenegro",
MS: "Montserrat",
MA: "Morocco",
MZ: "Mozambique",
MM: "Myanmar",
NA: "Namibia",
NR: "Nauru",
NP: "Nepal",
NL: "Netherlands",
AN: "Netherlands Antilles",
NC: "New Caledonia",
NZ: "New Zealand",
NI: "Nicaragua",
NE: "Niger",
NG: "Nigeria",
NU: "Niue",
NF: "Norfolk Island",
MP: "Northern Mariana Islands",
NO: "Norway",
OM: "Oman",
PK: "Pakistan",
PW: "Palau",
PS: "Palestinian Territory, Occupied",
PA: "Panama",
PG: "Papua New Guinea",
PY: "Paraguay",
PE: "Peru",
PH: "Philippines",
PN: "Pitcairn",
PL: "Poland",
PT: "Portugal",
PR: "Puerto Rico",
QA: "Qatar",
RE: "Reunion",
RO: "Romania",
RU: "Russian Federation",
RW: "Rwanda",
BL: "Saint Barthelemy",
SH: "Saint Helena",
KN: "Saint Kitts And Nevis",
LC: "Saint Lucia",
MF: "Saint Martin",
PM: "Saint Pierre And Miquelon",
VC: "Saint Vincent And Grenadines",
WS: "Samoa",
SM: "San Marino",
ST: "Sao Tome And Principe",
SA: "Saudi Arabia",
SN: "Senegal",
RS: "Serbia",
SC: "Seychelles",
SL: "Sierra Leone",
SG: "Singapore",
SK: "Slovakia",
SI: "Slovenia",
SB: "Solomon Islands",
SO: "Somalia",
ZA: "South Africa",
GS: "South Georgia And Sandwich Isl.",
ES: "Spain",
LK: "Sri Lanka",
SD: "Sudan",
SR: "Suriname",
SJ: "Svalbard And Jan Mayen",
SZ: "Swaziland",
SE: "Sweden",
CH: "Switzerland",
SY: "Syrian Arab Republic",
TW: "Taiwan",
TJ: "Tajikistan",
TZ: "Tanzania",
TH: "Thailand",
TL: "Timor-Leste",
TG: "Togo",
TK: "Tokelau",
TO: "Tonga",
TT: "Trinidad And Tobago",
TN: "Tunisia",
TR: "Turkey",
TM: "Turkmenistan",
TC: "Turks And Caicos Islands",
TV: "Tuvalu",
UG: "Uganda",
UA: "Ukraine",
AE: "United Arab Emirates",
GB: "United Kingdom",
US: "United States",
UM: "United States Outlying Islands",
UY: "Uruguay",
UZ: "Uzbekistan",
VU: "Vanuatu",
VE: "Venezuela",
VN: "Viet Nam",
VG: "Virgin Islands, British",
VI: "Virgin Islands, U.S.",
WF: "Wallis And Futuna",
EH: "Western Sahara",
YE: "Yemen",
ZM: "Zambia",
ZW: "Zimbabwe",
}
export const countries = [
{ alpha2: "AF", name: "Afghanistan", alpha3: "AFG", numeric: "004" },
{ alpha2: "AL", name: "Albania", alpha3: "ALB", numeric: "008" },
{ alpha2: "DZ", name: "Algeria", alpha3: "DZA", numeric: "012" },
{ alpha2: "AS", name: "American Samoa", alpha3: "ASM", numeric: "016" },
{ alpha2: "AD", name: "Andorra", alpha3: "AND", numeric: "020" },
{ alpha2: "AO", name: "Angola", alpha3: "AGO", numeric: "024" },
{ alpha2: "AI", name: "Anguilla", alpha3: "AIA", numeric: "660" },
{ alpha2: "AQ", name: "Antarctica", alpha3: "ATA", numeric: "010" },
{ alpha2: "AG", name: "Antigua and Barbuda", alpha3: "ATG", numeric: "028" },
{ alpha2: "AR", name: "Argentina", alpha3: "ARG", numeric: "032" },
{ alpha2: "AM", name: "Armenia", alpha3: "ARM", numeric: "051" },
{ alpha2: "AW", name: "Aruba", alpha3: "ABW", numeric: "533" },
{ alpha2: "AU", name: "Australia", alpha3: "AUS", numeric: "036" },
{ alpha2: "AT", name: "Austria", alpha3: "AUT", numeric: "040" },
{ alpha2: "AZ", name: "Azerbaijan", alpha3: "AZE", numeric: "031" },
{ alpha2: "BS", name: "Bahamas", alpha3: "BHS", numeric: "044" },
{ alpha2: "BH", name: "Bahrain", alpha3: "BHR", numeric: "048" },
{ alpha2: "BD", name: "Bangladesh", alpha3: "BGD", numeric: "050" },
{ alpha2: "BB", name: "Barbados", alpha3: "BRB", numeric: "052" },
{ alpha2: "BY", name: "Belarus", alpha3: "BLR", numeric: "112" },
{ alpha2: "BE", name: "Belgium", alpha3: "BEL", numeric: "056" },
{ alpha2: "BZ", name: "Belize", alpha3: "BLZ", numeric: "084" },
{ alpha2: "BJ", name: "Benin", alpha3: "BEN", numeric: "204" },
{ alpha2: "BM", name: "Bermuda", alpha3: "BMU", numeric: "060" },
{ alpha2: "BT", name: "Bhutan", alpha3: "BTN", numeric: "064" },
{ alpha2: "BO", name: "Bolivia", alpha3: "BOL", numeric: "068" },
{
alpha2: "BQ",
name: "Bonaire",
alpha3: "BES",
numeric: "535",
},
{
alpha2: "BA",
name: "Bosnia and Herzegovina",
alpha3: "BIH",
numeric: "070",
},
{ alpha2: "BW", name: "Botswana", alpha3: "BWA", numeric: "072" },
{ alpha2: "BV", name: "Bouvet Island", alpha3: "BVD", numeric: "074" },
{ alpha2: "BR", name: "Brazil", alpha3: "BRA", numeric: "076" },
{
alpha2: "IO",
name: "British Indian Ocean Territory",
alpha3: "IOT",
numeric: "086",
},
{ alpha2: "BN", name: "Brunei Darussalam", alpha3: "BRN", numeric: "096" },
{ alpha2: "BG", name: "Bulgaria", alpha3: "BGR", numeric: "100" },
{ alpha2: "BF", name: "Burkina Faso", alpha3: "BFA", numeric: "854" },
{ alpha2: "BI", name: "Burundi", alpha3: "BDI", numeric: "108" },
{ alpha2: "KH", name: "Cambodia", alpha3: "KHM", numeric: "116" },
{ alpha2: "CM", name: "Cameroon", alpha3: "CMR", numeric: "120" },
{ alpha2: "CA", name: "Canada", alpha3: "CAN", numeric: "124" },
{ alpha2: "CV", name: "Cape Verde", alpha3: "CPV", numeric: "132" },
{ alpha2: "KY", name: "Cayman Islands", alpha3: "CYM", numeric: "136" },
{
alpha2: "CF",
name: "Central African Republic",
alpha3: "CAF",
numeric: "140",
},
{ alpha2: "TD", name: "Chad", alpha3: "TCD", numeric: "148" },
{ alpha2: "CL", name: "Chile", alpha3: "CHL", numeric: "152" },
{ alpha2: "CN", name: "China", alpha3: "CHN", numeric: "156" },
{ alpha2: "CX", name: "Christmas Island", alpha3: "CXR", numeric: "162" },
{
alpha2: "CC",
name: "Cocos (Keeling) Islands",
alpha3: "CCK",
numeric: "166",
},
{ alpha2: "CO", name: "Colombia", alpha3: "COL", numeric: "170" },
{ alpha2: "KM", name: "Comoros", alpha3: "COM", numeric: "174" },
{ alpha2: "CG", name: "Congo", alpha3: "COG", numeric: "178" },
{
alpha2: "CD",
name: "D.R. Congo",
alpha3: "COD",
numeric: "180",
},
{ alpha2: "CK", name: "Cook Islands", alpha3: "COK", numeric: "184" },
{ alpha2: "CR", name: "Costa Rica", alpha3: "CRI", numeric: "188" },
{ alpha2: "CI", name: "Cote D'Ivoire", alpha3: "CIV", numeric: "384" },
{ alpha2: "HR", name: "Croatia", alpha3: "HRV", numeric: "191" },
{ alpha2: "CU", name: "Cuba", alpha3: "CUB", numeric: "192" },
{ alpha2: "CW", name: "Curaçao", alpha3: "CUW", numeric: "531" },
{ alpha2: "CY", name: "Cyprus", alpha3: "CYP", numeric: "196" },
{ alpha2: "CZ", name: "Czech Republic", alpha3: "CZE", numeric: "203" },
{ alpha2: "DK", name: "Denmark", alpha3: "DNK", numeric: "208" },
{ alpha2: "DJ", name: "Djibouti", alpha3: "DJI", numeric: "262" },
{ alpha2: "DM", name: "Dominica", alpha3: "DMA", numeric: "212" },
{ alpha2: "DO", name: "Dominican Republic", alpha3: "DOM", numeric: "214" },
{ alpha2: "EC", name: "Ecuador", alpha3: "ECU", numeric: "218" },
{ alpha2: "EG", name: "Egypt", alpha3: "EGY", numeric: "818" },
{ alpha2: "SV", name: "El Salvador", alpha3: "SLV", numeric: "222" },
{ alpha2: "GQ", name: "Equatorial Guinea", alpha3: "GNQ", numeric: "226" },
{ alpha2: "ER", name: "Eritrea", alpha3: "ERI", numeric: "232" },
{ alpha2: "EE", name: "Estonia", alpha3: "EST", numeric: "233" },
{ alpha2: "ET", name: "Ethiopia", alpha3: "ETH", numeric: "231" },
{
alpha2: "FK",
name: "Falkland Islands (Malvinas)",
alpha3: "FLK",
numeric: "238",
},
{ alpha2: "FO", name: "Faroe Islands", alpha3: "FRO", numeric: "234" },
{ alpha2: "FJ", name: "Fiji", alpha3: "FJI", numeric: "242" },
{ alpha2: "FI", name: "Finland", alpha3: "FIN", numeric: "246" },
{ alpha2: "FR", name: "France", alpha3: "FRA", numeric: "250" },
{ alpha2: "GF", name: "French Guiana", alpha3: "GUF", numeric: "254" },
{ alpha2: "PF", name: "French Polynesia", alpha3: "PYF", numeric: "258" },
{
alpha2: "TF",
name: "French Southern Territories",
alpha3: "ATF",
numeric: "260",
},
{ alpha2: "GA", name: "Gabon", alpha3: "GAB", numeric: "266" },
{ alpha2: "GM", name: "Gambia", alpha3: "GMB", numeric: "270" },
{ alpha2: "GE", name: "Georgia", alpha3: "GEO", numeric: "268" },
{ alpha2: "DE", name: "Germany", alpha3: "DEU", numeric: "276" },
{ alpha2: "GH", name: "Ghana", alpha3: "GHA", numeric: "288" },
{ alpha2: "GI", name: "Gibraltar", alpha3: "GIB", numeric: "292" },
{ alpha2: "GR", name: "Greece", alpha3: "GRC", numeric: "300" },
{ alpha2: "GL", name: "Greenland", alpha3: "GRL", numeric: "304" },
{ alpha2: "GD", name: "Grenada", alpha3: "GRD", numeric: "308" },
{ alpha2: "GP", name: "Guadeloupe", alpha3: "GLP", numeric: "312" },
{ alpha2: "GU", name: "Guam", alpha3: "GUM", numeric: "316" },
{ alpha2: "GT", name: "Guatemala", alpha3: "GTM", numeric: "320" },
{ alpha2: "GG", name: "Guernsey", alpha3: "GGY", numeric: "831" },
{ alpha2: "GN", name: "Guinea", alpha3: "GIN", numeric: "324" },
{ alpha2: "GW", name: "Guinea-Bissau", alpha3: "GNB", numeric: "624" },
{ alpha2: "GY", name: "Guyana", alpha3: "GUY", numeric: "328" },
{ alpha2: "HT", name: "Haiti", alpha3: "HTI", numeric: "332" },
{ alpha2: "HN", name: "Honduras", alpha3: "HND", numeric: "340" },
{ alpha2: "HK", name: "Hong Kong", alpha3: "HKG", numeric: "344" },
{ alpha2: "HU", name: "Hungary", alpha3: "HUN", numeric: "348" },
{ alpha2: "IS", name: "Iceland", alpha3: "ISL", numeric: "352" },
{ alpha2: "IN", name: "India", alpha3: "IND", numeric: "356" },
{ alpha2: "ID", name: "Indonesia", alpha3: "IDN", numeric: "360" },
{
alpha2: "IR",
name: "Iran, Islamic Republic of",
alpha3: "IRN",
numeric: "364",
},
{ alpha2: "IQ", name: "Iraq", alpha3: "IRQ", numeric: "368" },
{ alpha2: "IE", name: "Ireland", alpha3: "IRL", numeric: "372" },
{ alpha2: "IM", name: "Isle Of Man", alpha3: "IMN", numeric: "833" },
{ alpha2: "IL", name: "Israel", alpha3: "ISR", numeric: "376" },
{ alpha2: "IT", name: "Italy", alpha3: "ITA", numeric: "380" },
{ alpha2: "JM", name: "Jamaica", alpha3: "JAM", numeric: "388" },
{ alpha2: "JP", name: "Japan", alpha3: "JPN", numeric: "392" },
{ alpha2: "JE", name: "Jersey", alpha3: "JEY", numeric: "832" },
{ alpha2: "JO", name: "Jordan", alpha3: "JOR", numeric: "400" },
{ alpha2: "KZ", name: "Kazakhstan", alpha3: "KAZ", numeric: "398" },
{ alpha2: "KE", name: "Kenya", alpha3: "KEN", numeric: "404" },
{ alpha2: "KI", name: "Kiribati", alpha3: "KIR", numeric: "296" },
{ alpha2: "KR", name: "South Korea", alpha3: "KOR", numeric: "410" },
{ alpha2: "XK", name: "Kosovo", alpha3: "XKX", numeric: "900" },
{ alpha2: "KW", name: "Kuwait", alpha3: "KWT", numeric: "414" },
{ alpha2: "KG", name: "Kyrgyzstan", alpha3: "KGZ", numeric: "417" },
{ alpha2: "LV", name: "Latvia", alpha3: "LVA", numeric: "428" },
{ alpha2: "LB", name: "Lebanon", alpha3: "LBN", numeric: "422" },
{ alpha2: "LS", name: "Lesotho", alpha3: "LSO", numeric: "426" },
{ alpha2: "LR", name: "Liberia", alpha3: "LBR", numeric: "430" },
{ alpha2: "LI", name: "Liechtenstein", alpha3: "LIE", numeric: "438" },
{ alpha2: "LT", name: "Lithuania", alpha3: "LTU", numeric: "440" },
{ alpha2: "LU", name: "Luxembourg", alpha3: "LUX", numeric: "442" },
{ alpha2: "MO", name: "Macao", alpha3: "MAC", numeric: "446" },
{
alpha2: "MK",
name: "Macedonia",
alpha3: "MKD",
numeric: "807",
},
{ alpha2: "MG", name: "Madagascar", alpha3: "MDG", numeric: "450" },
{ alpha2: "MW", name: "Malawi", alpha3: "MWI", numeric: "454" },
{ alpha2: "MY", name: "Malaysia", alpha3: "MYS", numeric: "458" },
{ alpha2: "MV", name: "Maldives", alpha3: "MDV", numeric: "462" },
{ alpha2: "ML", name: "Mali", alpha3: "MLI", numeric: "466" },
{ alpha2: "MT", name: "Malta", alpha3: "MLT", numeric: "470" },
{ alpha2: "MH", name: "Marshall Islands", alpha3: "MHL", numeric: "584" },
{ alpha2: "MQ", name: "Martinique", alpha3: "MTQ", numeric: "474" },
{ alpha2: "MR", name: "Mauritania", alpha3: "MRT", numeric: "478" },
{ alpha2: "MU", name: "Mauritius", alpha3: "MUS", numeric: "480" },
{ alpha2: "YT", name: "Mayotte", alpha3: "MYT", numeric: "175" },
{ alpha2: "MX", name: "Mexico", alpha3: "MEX", numeric: "484" },
{
alpha2: "FM",
name: "Micronesia, Federated States of",
alpha3: "FSM",
numeric: "583",
},
{ alpha2: "MD", name: "Moldova, Republic of", alpha3: "MDA", numeric: "498" },
{ alpha2: "MC", name: "Monaco", alpha3: "MCO", numeric: "492" },
{ alpha2: "MN", name: "Mongolia", alpha3: "MNG", numeric: "496" },
{ alpha2: "ME", name: "Montenegro", alpha3: "MNE", numeric: "499" },
{ alpha2: "MS", name: "Montserrat", alpha3: "MSR", numeric: "500" },
{ alpha2: "MA", name: "Morocco", alpha3: "MAR", numeric: "504" },
{ alpha2: "MZ", name: "Mozambique", alpha3: "MOZ", numeric: "508" },
{ alpha2: "MM", name: "Myanmar", alpha3: "MMR", numeric: "104" },
{ alpha2: "NA", name: "Namibia", alpha3: "NAM", numeric: "516" },
{ alpha2: "NR", name: "Nauru", alpha3: "NRU", numeric: "520" },
{ alpha2: "NP", name: "Nepal", alpha3: "NPL", numeric: "524" },
{ alpha2: "NL", name: "Netherlands", alpha3: "NLD", numeric: "528" },
{ alpha2: "NC", name: "New Caledonia", alpha3: "NCL", numeric: "540" },
{ alpha2: "NZ", name: "New Zealand", alpha3: "NZL", numeric: "554" },
{ alpha2: "NI", name: "Nicaragua", alpha3: "NIC", numeric: "558" },
{ alpha2: "NE", name: "Niger", alpha3: "NER", numeric: "562" },
{ alpha2: "NG", name: "Nigeria", alpha3: "NGA", numeric: "566" },
{ alpha2: "NU", name: "Niue", alpha3: "NIU", numeric: "570" },
{ alpha2: "NF", name: "Norfolk Island", alpha3: "NFK", numeric: "574" },
{
alpha2: "MP",
name: "Northern Mariana Islands",
alpha3: "MNP",
numeric: "580",
},
{ alpha2: "NO", name: "Norway", alpha3: "NOR", numeric: "578" },
{ alpha2: "OM", name: "Oman", alpha3: "OMN", numeric: "512" },
{ alpha2: "PK", name: "Pakistan", alpha3: "PAK", numeric: "586" },
{ alpha2: "PW", name: "Palau", alpha3: "PLW", numeric: "585" },
{
alpha2: "PS",
name: "Palestinian Territory, Occupied",
alpha3: "PSE",
numeric: "275",
},
{ alpha2: "PA", name: "Panama", alpha3: "PAN", numeric: "591" },
{ alpha2: "PG", name: "Papua New Guinea", alpha3: "PNG", numeric: "598" },
{ alpha2: "PY", name: "Paraguay", alpha3: "PRY", numeric: "600" },
{ alpha2: "PE", name: "Peru", alpha3: "PER", numeric: "604" },
{ alpha2: "PH", name: "Philippines", alpha3: "PHL", numeric: "608" },
{ alpha2: "PN", name: "Pitcairn", alpha3: "PCN", numeric: "612" },
{ alpha2: "PL", name: "Poland", alpha3: "POL", numeric: "616" },
{ alpha2: "PT", name: "Portugal", alpha3: "PRT", numeric: "620" },
{ alpha2: "PR", name: "Puerto Rico", alpha3: "PRI", numeric: "630" },
{ alpha2: "QA", name: "Qatar", alpha3: "QAT", numeric: "634" },
{ alpha2: "RE", name: "Reunion", alpha3: "REU", numeric: "638" },
{ alpha2: "RO", name: "Romania", alpha3: "ROU", numeric: "642" },
{ alpha2: "RO", name: "Romania", alpha3: "ROM", numeric: "642" },
{ alpha2: "RU", name: "Russian Federation", alpha3: "RUS", numeric: "643" },
{ alpha2: "RW", name: "Rwanda", alpha3: "RWA", numeric: "646" },
{ alpha2: "BL", name: "Saint Barthélemy", alpha3: "BLM", numeric: "652" },
{ alpha2: "SH", name: "Saint Helena", alpha3: "SHN", numeric: "654" },
{
alpha2: "KN",
name: "Saint Kitts and Nevis",
alpha3: "KNA",
numeric: "659",
},
{ alpha2: "LC", name: "Saint Lucia", alpha3: "LCA", numeric: "662" },
{
alpha2: "MF",
name: "Saint Martin (French part)",
alpha3: "MAF",
numeric: "663",
},
{
alpha2: "PM",
name: "Saint Pierre and Miquelon",
alpha3: "SPM",
numeric: "666",
},
{
alpha2: "VC",
name: "Saint Vincent and the Grenadines",
alpha3: "VCT",
numeric: "670",
},
{ alpha2: "WS", name: "Samoa", alpha3: "WSM", numeric: "882" },
{ alpha2: "SM", name: "San Marino", alpha3: "SMR", numeric: "674" },
{
alpha2: "ST",
name: "Sao Tome and Principe",
alpha3: "STP",
numeric: "678",
},
{ alpha2: "SA", name: "Saudi Arabia", alpha3: "SAU", numeric: "682" },
{ alpha2: "SN", name: "Senegal", alpha3: "SEN", numeric: "686" },
{ alpha2: "RS", name: "Serbia", alpha3: "SRB", numeric: "688" },
{ alpha2: "SC", name: "Seychelles", alpha3: "SYC", numeric: "690" },
{ alpha2: "SL", name: "Sierra Leone", alpha3: "SLE", numeric: "694" },
{ alpha2: "SG", name: "Singapore", alpha3: "SGP", numeric: "702" },
{ alpha2: "SX", name: "Sint Maarten", alpha3: "SXM", numeric: "534" },
{ alpha2: "SK", name: "Slovakia", alpha3: "SVK", numeric: "703" },
{ alpha2: "SI", name: "Slovenia", alpha3: "SVN", numeric: "705" },
{ alpha2: "SB", name: "Solomon Islands", alpha3: "SLB", numeric: "090" },
{ alpha2: "SO", name: "Somalia", alpha3: "SOM", numeric: "706" },
{ alpha2: "ZA", name: "South Africa", alpha3: "ZAF", numeric: "710" },
{ alpha2: "SS", name: "South Sudan", alpha3: "SSD", numeric: "728" },
{ alpha2: "ES", name: "Spain", alpha3: "ESP", numeric: "724" },
{ alpha2: "LK", name: "Sri Lanka", alpha3: "LKA", numeric: "144" },
{ alpha2: "SD", name: "Sudan", alpha3: "SDN", numeric: "729" },
{ alpha2: "SR", name: "Suriname", alpha3: "SUR", numeric: "740" },
{
alpha2: "SJ",
name: "Svalbard and Jan Mayen",
alpha3: "SJM",
numeric: "744",
},
{ alpha2: "SZ", name: "Swaziland", alpha3: "SWZ", numeric: "748" },
{ alpha2: "SE", name: "Sweden", alpha3: "SWE", numeric: "752" },
{ alpha2: "CH", name: "Switzerland", alpha3: "CHE", numeric: "756" },
{ alpha2: "SY", name: "Syrian Arab Republic", alpha3: "SYR", numeric: "760" },
{
alpha2: "TW",
name: "Taiwan, Province of China",
alpha3: "TWN",
numeric: "158",
},
{ alpha2: "TJ", name: "Tajikistan", alpha3: "TJK", numeric: "762" },
{
alpha2: "TZ",
name: "Tanzania, United Republic of",
alpha3: "TZA",
numeric: "834",
},
{ alpha2: "TH", name: "Thailand", alpha3: "THA", numeric: "764" },
{ alpha2: "TL", name: "Timor Leste", alpha3: "TLS", numeric: "626" },
{ alpha2: "TG", name: "Togo", alpha3: "TGO", numeric: "768" },
{ alpha2: "TK", name: "Tokelau", alpha3: "TKL", numeric: "772" },
{ alpha2: "TO", name: "Tonga", alpha3: "TON", numeric: "776" },
{ alpha2: "TT", name: "Trinidad and Tobago", alpha3: "TTO", numeric: "780" },
{ alpha2: "TN", name: "Tunisia", alpha3: "TUN", numeric: "788" },
{ alpha2: "TR", name: "Turkey", alpha3: "TUR", numeric: "792" },
{ alpha2: "TM", name: "Turkmenistan", alpha3: "TKM", numeric: "795" },
{
alpha2: "TC",
name: "Turks and Caicos Islands",
alpha3: "TCA",
numeric: "796",
},
{ alpha2: "TV", name: "Tuvalu", alpha3: "TUV", numeric: "798" },
{ alpha2: "UG", name: "Uganda", alpha3: "UGA", numeric: "800" },
{ alpha2: "UA", name: "Ukraine", alpha3: "UKR", numeric: "804" },
{ alpha2: "AE", name: "United Arab Emirates", alpha3: "ARE", numeric: "784" },
{ alpha2: "GB", name: "United Kingdom", alpha3: "GBR", numeric: "826" },
{ alpha2: "US", name: "United States", alpha3: "USA", numeric: "840" },
{
alpha2: "UM",
name: "United States Minor Outlying Islands",
alpha3: "UMI",
numeric: "581",
},
{ alpha2: "UY", name: "Uruguay", alpha3: "URY", numeric: "858" },
{ alpha2: "UZ", name: "Uzbekistan", alpha3: "UZB", numeric: "860" },
{ alpha2: "VU", name: "Vanuatu", alpha3: "VUT", numeric: "548" },
{ alpha2: "VE", name: "Venezuela", alpha3: "VEN", numeric: "862" },
{ alpha2: "VN", name: "Viet Nam", alpha3: "VNM", numeric: "704" },
{
alpha2: "VG",
name: "Virgin Islands, British",
alpha3: "VGB",
numeric: "092",
},
{ alpha2: "VI", name: "Virgin Islands, U.S.", alpha3: "VIR", numeric: "850" },
{ alpha2: "WF", name: "Wallis and Futuna", alpha3: "WLF", numeric: "876" },
{ alpha2: "EH", name: "Western Sahara", alpha3: "ESH", numeric: "732" },
{ alpha2: "YE", name: "Yemen", alpha3: "YEM", numeric: "887" },
{ alpha2: "ZM", name: "Zambia", alpha3: "ZMB", numeric: "894" },
{ alpha2: "ZW", name: "Zimbabwe", alpha3: "ZWE", numeric: "716" },
{ alpha2: "AX", name: "Åland Islands", alpha3: "ALA", numeric: "248" },
]
export function countryLookup(isoCountryCode) {
if (!isoCountryCode) {
return
}
const normalizedIsoCountryCode = isoCountryCode.toUpperCase()
if (isoAlpha2Countries[normalizedIsoCountryCode]) {
return isoAlpha2Countries[normalizedIsoCountryCode]
} else {
// try iso alpha 3
const isoRecord = countries.find(
(record) => record.alpha3 === normalizedIsoCountryCode
)
if (isoRecord) {
return isoRecord.name
}
throw new Error("Invalid country code")
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,5 @@
export const weekFromNow = () => {
const now = new Date()
const weekFromNow = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000)
return weekFromNow
}

View File

@@ -0,0 +1,40 @@
export function decideBadgeColor(batchLabel) {
switch (batchLabel) {
case "captured":
case "completed":
case "shipped":
case "published":
case "registered":
case "difference_refunded":
case "received":
return {
bgColor: "#4BB543",
color: "white",
}
case "partially_refunded":
case "refunded":
case "fulfilled":
case "partially_fulfilled":
case "partially_shipped":
case "partially_returned":
case "draft":
case "returned":
return {
bgColor: "#ffd733",
color: "black",
}
case "cancelled":
case "requires_action":
case "rejected":
case "failed":
return {
bgColor: "#ff4133",
color: "white",
}
default:
return {
bgColor: "#e3e8ee",
color: "#4f566b",
}
}
}

View File

@@ -0,0 +1,11 @@
export const setsEqual = (as: Set<string>, bs: Set<string>) => {
if (as.size !== bs.size) {
return false
}
for (const a of as) {
if (!bs.has(a)) {
return false
}
}
return true
}

View File

@@ -0,0 +1,10 @@
export const getErrorMessage = (error: any) => {
let msg = error?.response?.data?.message
if (msg[0].message) {
msg = msg[0].message
}
if (!msg) {
msg = "Something went wrong, Please try again."
}
return msg
}

View File

@@ -0,0 +1,69 @@
import { Cart, Order } from "@medusajs/medusa"
/**
* Utility for extracting the customer name from a cart or order.
*/
const extractCustomerName = (obj?: Cart | Order) => {
if (!obj) {
return "N/A"
}
if (obj.customer) {
const firstName = obj.customer.first_name
const lastName = obj.customer.last_name
if (firstName && lastName) {
return `${firstName} ${lastName}`
}
if (firstName) {
return firstName
}
if (lastName) {
return lastName
}
}
if (obj.shipping_address) {
const firstName = obj.shipping_address.first_name
const lastName = obj.shipping_address.last_name
if (firstName && lastName) {
return `${firstName} ${lastName}`
}
if (firstName) {
return firstName
}
if (lastName) {
return lastName
}
}
if (obj.billing_address) {
const firstName = obj.billing_address.first_name
const lastName = obj.billing_address.last_name
if (firstName && lastName) {
return `${firstName} ${lastName}`
}
if (firstName) {
return firstName
}
if (lastName) {
return lastName
}
}
if (obj.email) {
return obj.email
}
return "N/A"
}
export default extractCustomerName

View File

@@ -0,0 +1,26 @@
export function extractRegionOptions(
regions: any[] | undefined
): { label: string; value: string; currency: string }[] {
if (!regions) {
return []
}
return regions.map((region) => ({
label: region.name,
value: region.id,
currency: region.currency_code,
}))
}
export function extractProductOptions(
products: any[] | undefined
): { label: string; value: string }[] {
if (!products) {
return []
}
return products.map((product) => ({
label: product.title,
value: product.id,
}))
}

View File

@@ -0,0 +1,40 @@
export const DateFilterIsInTheLast = "is in the last"
export const DateFilters = {
InTheLast: "is in the last",
OlderThan: "is older than",
Between: "is between",
After: "is after",
Before: "is before",
EqualTo: "is equal to",
}
export const FulfilmentFilters = {
NotFulfilled: "not_fulfilled",
Fulfilled: "fulfilled",
PartiallyFulfilled: "partially_fulfilled",
Returned: "returned",
PartiallyReturned: "partially_returned",
Shipped: "shipped",
PartiallyShipped: "partially_shipped",
Canceled: "canceled",
RequiresAction: "requires_action",
}
export const PaymentFilters = {
Awaiting: "awaiting",
Captured: "captured",
Refunded: "refunded",
NotPaid: "not_paid",
PartiallyRefunded: "partially_refunded",
Canceled: "canceled",
RequiresAction: "requires_action",
}
export const StatusFilters = {
Pending: "pending",
Completed: "completed",
Canceled: "canceled",
Archived: "archived",
RequiresAction: "requires_action",
}

View File

@@ -0,0 +1,3 @@
export function focusByName(name: string) {
document?.getElementsByName(name)?.[0]?.focus()
}

View File

@@ -0,0 +1,22 @@
import { DeepMap } from "react-hook-form"
export const stringOrNull = (value: string) => {
return value === "" ? null : value
}
export const numberOrNull = (value: string) => {
const tmp = parseInt(value, 10)
return isNaN(tmp) ? null : tmp
}
export const checkForDirtyState = (
dirtyFields: DeepMap<Record<string, any>, true>,
otherValues: Record<string, boolean>
) => {
const otherDirtyState = otherValues
? Object.values(otherValues).some((v) => v)
: false
return !!Object.keys(dirtyFields).length || otherDirtyState
}

View File

@@ -0,0 +1,67 @@
import { ValidationRule } from "react-hook-form"
import { normalizeAmount } from "./prices"
/**
* Utility functions for validating form inputs.
*/
const FormValidator = {
whiteSpaceRule: (name: string) =>
({
value: /^[^\s]+(?:$|.*[^\s]+$)/,
message: `${name} cannot have leading or trailing spaces, or be an empty string.`,
} as ValidationRule<RegExp>),
nonNegativeNumberRule: (name: string) => ({
value: 0,
message: `${name} cannot be negative.`,
}),
minOneCharRule: (name: string) => ({
value: 1,
message: `${name} must be at least 1 character.`,
}),
min: (name: string, min: number) => ({
value: min,
message: `${name} must be greater than or equal to ${min}.`,
}),
max: (name: string, max: number) => ({
value: max,
message: `${name} must be less than or equal to ${max}.`,
}),
required: (name: string) => ({
value: true,
message: `${name} is required.`,
}),
minLength: (name: string, min: number) => ({
value: min,
message: `${name} must be at least ${min} characters.`,
}),
maxInteger: (name: string, currency?: string) => {
return {
value: MAX_INTEGER,
message: `${name} must be less than or equal to ${getNormalizedAmount(
currency
)}.`,
}
},
validateMaxInteger: (name: string, amount: number, currency?: string) => {
return (
amount <= MAX_INTEGER ||
`${name} must be less than or equal to ${getNormalizedAmount(currency)}.`
)
},
}
/**
* The maximum integer value that can be stored in the database.
*/
const MAX_INTEGER = 2147483647
/**
* Gets the normalized amount for the given currency, and if not provided then returns the MAX_INTEGER.
*/
const getNormalizedAmount = (currency?: string) => {
const amount = currency ? normalizeAmount(currency, MAX_INTEGER) : MAX_INTEGER
return amount.toLocaleString()
}
export default FormValidator

View File

@@ -0,0 +1,19 @@
import { countryLookup } from "./countries"
/**
* Formats a shipping or billing address using the postal code, city, province, and country name
* @param shippingOrBillingAddress
* @returns {string} Returns a formatted string of the address
*/
const formatAddress = (shippingOrBillingAddress) => {
const postalCode = shippingOrBillingAddress.postal_code || ""
const city = shippingOrBillingAddress.city || ""
const province = shippingOrBillingAddress.province || ""
const countryCode = shippingOrBillingAddress.country_code || ""
const countryName = countryLookup(countryCode)
const spaceIfProvince = province ? " " : ""
return `${postalCode} ${city}${spaceIfProvince}${province}, ${countryName}`
}
export { formatAddress }

View File

@@ -0,0 +1,26 @@
import { Option } from "../types/shared"
export default function (provider: string): Option {
switch (provider) {
case "primecargo":
return {
label: "Prime Cargo",
value: "primecargo",
}
case "manual":
return {
label: "Manual",
value: "manual",
}
case "webshipper":
return {
label: "Webshipper",
value: "webshipper",
}
default:
return {
label: provider,
value: provider,
}
}
}

View File

@@ -0,0 +1,12 @@
import randomize from "randomatic"
export const generatePromotionCode = () => {
const code = [
randomize("A0", 4),
randomize("A0", 4),
randomize("A0", 4),
randomize("A0", 4),
].join("-")
return code
}

View File

@@ -0,0 +1,26 @@
export const getCombinations = (options) => {
if (options.length === 0) {
return []
}
if (options.length === 1) {
const values = options.shift().values
if (values.length > 0) {
return values.map((v) => [v])
}
return [""]
}
const combinations = []
const theseValues = options.shift().values
const lowerCombinations = getCombinations(options)
for (const v of theseValues) {
for (const second of lowerCombinations) {
combinations.push([v, second].flat())
}
}
return combinations
}

View File

@@ -0,0 +1,9 @@
export const getErrorStatus = (error: Error): { status: number, message: string} | undefined => {
const formattedError = JSON.parse(JSON.stringify(error))
if ("status" in formattedError && "message" in formattedError) {
return { status: formattedError.status, message: formattedError.message }
}
return undefined
}

View File

@@ -0,0 +1,38 @@
import RelativeTimeFormatUnit = Intl.RelativeTimeFormatUnit
const units: [RelativeTimeFormatUnit, string, number][] = [
["day", "d", 86400000],
["hour", "h", 3600000],
["minute", "m", 60000],
];
const getRelativeTime = (dates: { from: Date | string; to: Date | string }) => {
const elapsed = new Date(dates.to).getTime() - new Date(dates.from).getTime()
for (const [unit, displayedUnit, amount] of units) {
if (Math.abs(elapsed) >= amount || unit === "minute") {
const isLessThan1Min = Math.abs(elapsed) <= amount && unit === "minute"
const suffix = elapsed <= 0 ? "ago" : ""
const prefix = elapsed > 0 ? "in" : ""
const indicator = Math.abs(elapsed) < 1 ? "<" : ""
const timeToShow = Math.max(
1,
Math.abs(Math.round(elapsed / amount))
)
return {
raw: elapsed,
rtf: `
${indicator}${prefix ? prefix + " " : ""}
${(isLessThan1Min ? "< " : "")}
${timeToShow}${displayedUnit}
${suffix}
`
};
}
}
return { raw: 0, rtf: "" }
};
export default getRelativeTime

View File

@@ -0,0 +1,65 @@
import React from "react"
import {
DeepMap,
FieldError,
FieldValues,
SubmitErrorHandler,
} from "react-hook-form"
import { toast as Controller } from "react-hot-toast"
import FormErrorToaster from "../components/molecules/form-error-toaster"
export const handleFormError: SubmitErrorHandler<FieldValues> = (errors) => {
const { title, list, refs } = getFormErrors(errors)
if (refs?.[0] && refs[0].focus) {
refs[0].focus()
}
Controller.custom(
(t) => <FormErrorToaster toast={t} message={list} title={title} />,
{
position: "top-right",
duration: 3000,
ariaProps: {
role: "alert",
"aria-live": "polite",
},
}
)
}
function getFormErrors(errors: DeepMap<FieldValues, FieldError>) {
const messages: string[] = Object.values(errors).reduce(
(acc, { message }) => {
if (message) {
acc.push(message)
}
return acc
},
[]
)
const refs = Object.values(errors).reduce((acc, { ref }) => {
if (ref) {
acc.push(ref)
}
return acc
}, [])
const list = (
<ul className="list-disc list-inside">
{messages.map((m) => (
<li>{m}</li>
))}
</ul>
)
const title =
messages.length > 1
? `There were ${messages.length} errors with your submission`
: "There was an error with your submission"
return { title, list, refs }
}

View File

@@ -0,0 +1,33 @@
import Medusa from "../services/api";
import { FormImage } from "../types/shared";
const splitImages = (
images: FormImage[]
): { uploadImages: FormImage[]; existingImages: FormImage[] } => {
const uploadImages: FormImage[] = []
const existingImages: FormImage[] = []
images.forEach((image) => {
if (image.nativeFile) {
uploadImages.push(image)
} else {
existingImages.push(image)
}
})
return { uploadImages, existingImages }
}
export const prepareImages = async (images: FormImage[]) => {
const { uploadImages, existingImages } = splitImages(images)
let uploadedImgs: FormImage[] = []
if (uploadImages.length > 0) {
const files = uploadImages.map((i) => i.nativeFile)
uploadedImgs = await Medusa.uploads
.create(files)
.then(({ data }) => data.uploads)
}
return [...existingImages, ...uploadedImgs]
}

View File

@@ -0,0 +1,37 @@
import { ClaimOrder, LineItem, Order, Swap } from "@medusajs/medusa"
export const isLineItemCanceled = (
item: Omit<LineItem, "beforeInsert">,
order: Omit<Order, "beforeInsert">
) => {
const { swap_id, claim_order_id } = item
const travFind = (col: (Swap | ClaimOrder)[], id: string) =>
col.filter((f) => f.id == id && f.canceled_at).length > 0
if (swap_id) {
return travFind(order.swaps, swap_id)
}
if (claim_order_id) {
return travFind(order.claims, claim_order_id)
}
return false
}
export const isLineItemReturned = (item: Omit<LineItem, "beforeInsert">) => {
const { shipped_quantity, returned_quantity } = item
if (!returned_quantity) {
return false
}
if (shipped_quantity && returned_quantity === shipped_quantity) {
return true
}
}
export const isLineItemNotReturnable = (
item: Omit<LineItem, "beforeInsert">,
order: Order
) => {
return isLineItemCanceled(item, order) || isLineItemReturned(item)
}

View File

@@ -0,0 +1,14 @@
/**
* Utility function that checks if every object property is nullish.
*/
const isNullishObject = (obj?: Object | null) => {
if (!obj) {
return true
}
return Object.values(obj).every(
(value) => value === null || value === undefined || value === ""
)
}
export default isNullishObject

View File

@@ -0,0 +1,23 @@
import { Address } from "@medusajs/medusa"
import { AddressPayload } from "../components/templates/address-form"
import { isoAlpha2Countries } from "./countries"
const mapAddressToForm = (address: Address): AddressPayload => {
return {
first_name: address.first_name || "",
last_name: address.last_name || "",
company: address.company,
address_1: address.address_1 || "",
address_2: address.address_2,
city: address.city || "",
province: address.province,
postal_code: address.postal_code || "",
country_code: {
label: isoAlpha2Countries[address.country_code?.toUpperCase()] || "",
value: address.country_code || "",
},
phone: address.phone,
}
}
export default mapAddressToForm

View File

@@ -0,0 +1,83 @@
import { get } from "lodash"
import { FieldPath, FieldValues, UseFormReturn } from "react-hook-form"
import { Get } from "type-fest"
export type NestedForm<TValues extends FieldValues> = UseFormReturn<{ __nested__: TValues }> & {
path(this: void): `__nested__`
path<TPath extends FieldPath<TValues>>(
this: void,
p?: TPath
): `__nested__.${TPath}`
get<TObj>(this: void, obj: TObj): Get<TObj, `__nested__`>
get<TPath extends FieldPath<TValues>, TObj>(
this: void,
obj: TObj,
p?: TPath
): Get<TObj, `__nested__.${TPath}`>
}
/**
* Utility function to create a nested form. This is useful when you want to use a reusable form component within a form.
* This is especially useful when you want to use a reusable form component within a form multiple times. For example, an form
* that contains both a billing and a shipping address.
* @example
* const MyForm = () => {
* const form = useForm<{ email: string, shipping_address: AddressPayload, billing_address: AddressPayload }>()
*
* return (
* <div>
* <Input {...form.register("email")} label="email" />
* <AddressForm form={nestedForm(form, "shipping_address")} />
* <AddressForm form={nestedForm(form, "billing_address")} />
* </div>
* )
* }
*
* type AddressFormProps = {
* form: NestedForm<AddressPayload>
* }
*
* const AddressForm = ({ form }: AddressFormProps) => {
* const { register, path } = form
*
* return (
* <div>
* <Input {...register(path("city"))} label="City" /> // path("city") resolves as "shipping_address.city" or "billing_address.city" depending on the second argument passed to nestedForm
* <Input {...register(path("postal_code"))} label="Postal Code" />
* </div>
* )
* }
*/
export function nestedForm<TValues extends FieldValues>(
form: UseFormReturn<TValues> | NestedForm<TValues>
): NestedForm<TValues>
export function nestedForm<TValues extends FieldValues, TPath extends FieldPath<TValues>>(
form: UseFormReturn<TValues> | NestedForm<TValues>,
path: TPath
): NestedForm<Get<TValues, TPath>>
export function nestedForm(
form: UseFormReturn<any> | NestedForm<any>,
path?: string | number
): NestedForm<any> {
return {
...form,
path(field?: string | number) {
const fullPath = path && field ? `${path}.${field}` : path ? path : field
if ("path" in form) {
return form.path(path as any)
}
return (fullPath || "") as any
},
get(obj: any, field?: string | number) {
const fullPath = path && field ? `${path}.${field}` : path ? path : field
if ("get" in form) {
return form.get(path)
}
return fullPath ? get(obj, fullPath) : obj
},
}
}

View File

@@ -0,0 +1,73 @@
import { Option } from "../types/shared"
const providerDescriptors: { [providerKey: string]: Option } = {
stripe: {
label: "Stripe",
value: "stripe",
},
"stripe-ideal": {
label: "Stripe Ideal",
value: "stripe-ideal",
},
"stripe-giropay": {
label: "Stripe Giropay",
value: "stripe-giropay",
},
"stripe-bancontact": {
label: "Stripe Bancontact",
value: "stripe-bancontact",
},
"stripe-przelewy24": {
label: "Stripe Przelewy24",
value: "stripe-przelewy24",
},
"stripe-blik": {
label: "Stripe Blik",
value: "stripe-blik",
},
"mobilepay-adyen": {
label: "MobilePay via Adyen",
value: "mobilepay-adyen",
},
"scheme-adyen": {
label: "Cards via Adyen",
value: "scheme-adyen",
},
"klarna-adyen": {
label: "Klarna via Adyen",
value: "klarna-adyen",
},
klarna: {
label: "Klarna",
value: "klarna",
},
"paywithgoogle-adyen": {
label: "GooglePay via Adyen",
value: "paywithgoogle-adyen",
},
"applepay-adyen": {
label: "ApplePay via Adyen",
value: "applepay-adyen",
},
"paypal-adyen": {
label: "PayPal via Adyen",
value: "paypal-adyen",
},
"ideal-adyen": {
label: "iDEAL via Adyen",
value: "ideal-adyen",
},
manual: {
label: "Manual",
value: "manual",
},
}
export default function (provider: string): Option {
return (
providerDescriptors[provider] ?? {
label: provider,
value: provider,
}
)
}

View File

@@ -0,0 +1,153 @@
import { LineItemTaxLine, MoneyAmount, Order, Region } from "@medusajs/medusa"
import { PricedVariant } from "@medusajs/medusa/dist/types/pricing"
import { currencies } from "./currencies"
export function normalizeAmount(currency: string, amount: number): number {
const divisor = getDecimalDigits(currency)
return Math.floor(amount) / divisor
}
export function displayAmount(currency: string, amount: number) {
const normalizedAmount = normalizeAmount(currency, amount)
return normalizedAmount.toFixed(
currencies[currency.toUpperCase()].decimal_digits
)
}
export const extractUnitPrice = (
item: PricedVariant,
region: Region,
withTax = true
) => {
let itemPrice = item.original_price
let includesTax = item.original_price_includes_tax
let taxRate = item.original_tax
if (itemPrice === undefined) {
const regionPrice = item.prices.find(
(p) => p.currency_code === region.currency_code
)
if (!regionPrice) {
return 0
}
itemPrice = regionPrice.amount
includesTax = region.includes_tax
taxRate = includesTax
? (itemPrice * region.tax_rate) / (1 + region.tax_rate)
: itemPrice * region.tax_rate
}
if (itemPrice) {
if (includesTax) {
if (withTax) {
return itemPrice
} else {
return itemPrice - (taxRate ?? 0)
}
} else {
if (withTax) {
return itemPrice + (taxRate ?? 0)
} else {
return itemPrice
}
}
}
return 0
}
export const displayUnitPrice = (item, region) => {
const currCode = region.currency_code.toUpperCase()
const price = extractUnitPrice(item, region)
return `${displayAmount(currCode, price)} ${currCode}`
}
export const extractOptionPrice = (price, region) => {
let amount = price
amount = (amount * (1 + region.tax_rate / 100)) / 100
return `${amount} ${region.currency_code.toUpperCase()}`
}
/**
* Checks the list of currencies and returns the divider/multiplier
* that should be used to calculate the persited and display amount.
* @param currency
* @return {number}
*/
export function getDecimalDigits(currency: string) {
const divisionDigits = currencies[currency.toUpperCase()].decimal_digits
return Math.pow(10, divisionDigits)
}
export function persistedPrice(currency: string, amount: number): number {
const multiplier = getDecimalDigits(currency)
return amount * multiplier
}
export const stringDisplayPrice = ({ amount, currencyCode }) => {
if (typeof amount === "undefined" || !currencyCode) {
return `N/A`
}
const display = displayAmount(currencyCode, amount)
return `${display} ${currencyCode.toUpperCase()}`
}
export const getNativeSymbol = (currencyCode: string) => {
return currencies[currencyCode.toUpperCase()].symbol_native
}
type FormatMoneyProps = {
amount: number
currency: string
digits?: number
tax?: number | LineItemTaxLine[]
}
export function formatAmountWithSymbol({
amount,
currency,
digits,
tax = 0,
}: FormatMoneyProps) {
let locale = "en-US"
// We need this to display 'Kr' instead of 'DKK'
if (currency.toLowerCase() === "dkk") {
locale = "da-DK"
}
digits = digits ?? currencies[currency.toUpperCase()].decimal_digits
const normalizedAmount = normalizeAmount(currency, amount)
const taxRate =
tax instanceof Array ? tax.reduce((acc, curr) => acc + curr.rate, 0) : tax
return new Intl.NumberFormat(locale, {
style: "currency",
currency,
minimumFractionDigits: digits,
}).format(normalizedAmount * (1 + taxRate / 100))
}
export const extractNormalizedAmount = (
amounts: Omit<MoneyAmount, "beforeInsert">[],
order: Omit<Order, "beforeInsert">
) => {
let amount = amounts.find((ma) => ma.region_id === order.region_id)
if (!amount) {
amount = amounts.find((ma) => ma.currency_code === order.currency_code)
}
if (amount) {
return normalizeAmount(order.currency_code, amount.amount)
}
return 0
}

View File

@@ -0,0 +1,13 @@
export const getProductStatusVariant = (title) => {
switch (title) {
case "proposed":
return "warning"
case "published":
return "success"
case "rejected":
return "danger"
case "draft":
default:
return "default"
}
}

View File

@@ -0,0 +1,2 @@
export const removeNullish = (obj: Record<string, unknown>) =>
Object.entries(obj).reduce((a, [k, v]) => (v ? ((a[k] = v), a) : a), {})

View File

@@ -0,0 +1,15 @@
import { SalesChannel } from "@medusajs/medusa"
export const defaultChannelsSorter = (defaultSalesChanenlId: string) => (
sc1: SalesChannel,
sc2: SalesChannel
) => {
if (sc1.id === defaultSalesChanenlId) {
return -1
}
if (sc2.id === defaultSalesChanenlId) {
return 1
}
return sc1.name.localeCompare(sc2.name)
}

View File

@@ -0,0 +1,58 @@
import moment from "moment"
export const dateToUnixTimestamp = (date) => {
if (date instanceof Date) {
return (date.getTime() / 1000).toFixed(0)
}
return null
}
export const atMidnight = (date) => {
const result = moment(date)
if (!moment.isMoment(result)) {
console.log("date is not instance of Moment: ", date)
return null
}
result.hour(0)
result.minute(0)
result.second(0)
result.millisecond(0)
return result
}
export const addHours = (date, hours) => {
return moment(date)?.add(hours, "hours")
}
/**
* The format is: [gt]=number|option
* e.g: [gt]=2|days
* @param {*} value
*/
export const relativeDateFormatToTimestamp = (value) => {
const [count, option] = value.split("|")
// relative days are always subtract
let date = moment()
date.subtract(parseInt(count), option)
date = atMidnight(date)
const result = `${date.format("X")}`
return result
}
// Takes in a value from the date picker e.g. 42|days or a timestamp
export const formatDateFilter = (filter) => {
return Object.entries(filter).reduce((acc, [key, value]) => {
if (value.includes("|")) {
acc[key] = relativeDateFormatToTimestamp(value)
} else {
acc[key] = value
}
return acc
}, {})
}

View File

@@ -0,0 +1,15 @@
const computeShippingTotal = (shipping_methods) => {
if (!shipping_methods) {
return 0
}
return shipping_methods.reduce((acc, method) => acc + method.price, 0)
}
const computeSubtotal = (items) => {
if (!items) {
return 0
}
return items.reduce((acc, item) => acc + item.unit_price * item.quantity, 0)
}
export { computeShippingTotal, computeSubtotal }

View File

@@ -0,0 +1,11 @@
export const trimValues = <T extends object>(obj: T) => {
Object.keys(obj).forEach((key) => {
if (typeof obj[key] === "string") {
obj[key] = obj[key].trim()
} else if (obj[key] && obj[key].constructor.name === "Object") {
trimValues(obj[key])
}
})
return obj
}

View File

@@ -0,0 +1,7 @@
export const validateEmail = (email: string) => {
return email
.toLowerCase()
.match(
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
)
}

View File

@@ -0,0 +1,4 @@
const xorObjFields = (obj: Record<string, any>, keyA: string, keyB: string) =>
obj[keyA] ? { [keyA]: obj[keyA] } : { [keyB]: obj[keyB] }
export default xorObjFields