1import { getConfigValue, REG_DATE_KEY } from '../configs.js'; 2import { 3 getSignInToken, performCommerceRestMutation, performCommerceRestQuery, 4 performMonolithGraphQLQuery, performRestMutation, 5} from '../commerce.js'; 6 7const changePasswordQuery = ` 8 mutation changeCustomerPassword($currentPassword: String!, $newPassword: String!) { 9 commerce_changeCustomerPassword ( 10 currentPassword: $currentPassword 11 newPassword: $newPassword 12 ) { 13 id 14 email 15 } 16 } 17`; 18const requestPasswordResetMutation = ` 19 mutation requestPasswordResetEmail($email: String!) { 20 commerce_requestPasswordResetEmail( 21 email: $email 22 ) 23 }`; 24 25const resetPasswordMutation = ` 26 mutation resetPassword($email: String!, $token: String!, $newPassword: String!) { 27 commerce_resetPassword( 28 email: $email 29 resetPasswordToken: $token 30 newPassword: $newPassword 31 ) 32 } 33`; 34class Store { 35 constructor() { 36 this.type = 'guest'; 37 this.customer = null; 38 this.customerLastOrder = null; 39 } 40 41 static DEFAULT_CUSTOMER = { 42 firstname: '', 43 lastname: '', 44 email: '', 45 }; 46 47 static load() { 48 const token = getSignInToken(); 49 50 if (token) { 51 this.type = 'customer'; 52 } 53 } 54 55 getCustomer() { 56 if (!this.isGuest && !this.customer) { 57 return Store.DEFAULT_CUSTOMER; 58 } 59 60 return this.customer; 61 } 62 63 setCustomer(customer) { 64 this.customer = customer; 65 this.type = 'customer'; 66 if (customer?.created_at) { 67 localStorage.setItem(REG_DATE_KEY, customer.created_at); 68 } 69 } 70 71 getCustomerLastOrder() { 72 return this.customerLastOrder; 73 } 74 75 setCustomerLastOrder(lastOrderData) { 76 this.customerLastOrder = lastOrderData; 77 } 78 79 isGuest() { 80 return this.type === 'guest'; 81 } 82} 83 84export const store = new Store(); 85 86async function createUrl(endpoint) { 87 const baseUrl = await getConfigValue('commerce-rest-endpoint'); 88 89 const storeViewCode = await getConfigValue('commerce-store-view-code'); 90 91 const url = `${baseUrl}/${storeViewCode}/V1/${endpoint}`; 92 93 return url; 94} 95 96export async function getCustomerLastOrder(useCache = true) { 97 const token = getSignInToken(); 98 99 if (!token) { 100 return null; 101 } 102 103 // load from store 104 if (useCache && store.customerLastOrder) { 105 // console.log('from cache', store.customerLastOrder); 106 return store.customerLastOrder; 107 } 108 109 const url = await createUrl('customer-order/me/getLastOrder'); 110 111 const { 112 data, success, message, status, 113 } = await performCommerceRestQuery(url, true); 114 115 if (!success) { 116 console.error('Error fetching customer data', status, message); 117 return null; 118 } 119 120 // if no data, set empty object 121 if (data === false) { 122 store.setCustomerLastOrder({}); 123 } else { 124 store.setCustomerLastOrder(data); 125 } 126 127 return data; 128} 129 130export async function getCustomer(useCache = true) { 131 const token = getSignInToken(); 132 133 if (!token) { 134 return null; 135 } 136 137 // load from store 138 if (useCache && store.customer) { 139 // console.log('from cache', store.customer); 140 return store.customer; 141 } 142 143 const url = await createUrl('customers/me'); 144 145 const { 146 data, success, message, status, 147 } = await performCommerceRestQuery(url, true); 148 149 if (!success) { 150 console.error('Error fetching customer data', status, message); 151 // Dispatch event in case API returns 401. 152 if (status === 401) { 153 window.dispatchEvent(new CustomEvent('logoutUserWithUnauthorizedToken', { 154 detail: { isAuthorized: 'false' }, 155 })); 156 } 157 158 return null; 159 } 160 161 store.setCustomer(data); 162 163 return data; 164} 165 166export async function updateCustomer(customer, phoneNumber, phoneVerified) { 167 if (!getSignInToken()) { 168 return null; 169 } 170 171 const firstname = customer.name.split(' ')[0]; 172 const lastname = customer.name.split(' ').slice(1).join(' '); 173 const dob = customer.dateofBirth; 174 const variables = { 175 customer: { 176 firstname, 177 lastname, 178 email: store.customer.email, 179 dob, 180 extension_attributes: { 181 }, 182 custom_attributes: [ 183 ], 184 }, 185 }; 186 187 if (phoneNumber && phoneVerified) { 188 variables.customer.custom_attributes.push({ 189 attribute_code: 'phone_number',
190 value: phoneNumber, 191 }); 192 variables.customer.extension_attributes.is_verified = 'Y'; 193 } else { 194 variables.customer.custom_attributes.push({ 195 attribute_code: 'phone_number', 196 value: '', 197 }); 198 delete variables.customer.extension_attributes.is_verified; 199 } 200 201 if (customer.gender !== '') { 202 variables.customer.extension_attributes.customer_gender = customer.gender; 203 } else { 204 variables.customer.extension_attributes.customer_gender = ''; 205 } 206 207 const url = await createUrl('customers/me'); 208 209 const response = await performRestMutation(url, variables, true, 'PUT'); 210 211 const { success, data } = response; 212 213 if (!success) { 214 console.error('Error making customer updates', data.message); 215 return { success: false, message: 'Error customer updates', data }; 216 } 217 218 return { success, data }; 219} 220 221export async function updateCustomer2(customer) { 222 if (!getSignInToken()) { 223 return null; 224 } 225 226 const url = await createUrl('customers/me'); 227 228 const variables = { customer }; 229 230 const response = await performRestMutation(url, variables, true, 'PUT'); 231 232 const { success, data } = response; 233 234 if (!success) { 235 console.error('Error updating communication preference', data.message); 236 return { success, data }; 237 } 238 239 return { success, data }; 240} 241 242export async function changePassword(currentPassword, newPassword) { 243 document.querySelector('.change-password-container button').classList.add('loader', 'disabled'); 244 if (!getSignInToken()) { 245 return null; 246 } 247 const variables = { currentPassword, newPassword }; 248 249 const response = await performMonolithGraphQLQuery(changePasswordQuery, variables, false, true); 250 251 const { data, errors } = response; 252 253 if (errors) { 254 console.error('Error making password change', errors); 255 return { success: false, message: 'Error during password change', errors }; 256 } 257 258 return { success: true, data }; 259} 260 261export async function forgotPassword(email) { 262 const body = { email }; 263 264 const response = await performMonolithGraphQLQuery(requestPasswordResetMutation, body, false); 265 266 const { data, errors } = response; 267 268 if (errors) { 269 console.error('Error forgot password', errors); 270 return { success: false, message: 'Error during forgot password', errors }; 271 } 272 273 return { success: true, data }; 274} 275 276export async function resetPassword(email, token, newPassword) { 277 const body = { email, token, newPassword }; 278 279 const response = await performMonolithGraphQLQuery(resetPasswordMutation, body, false); 280 281 const { data, errors } = response; 282 283 if (errors) { 284 console.error('Error reset password', errors); 285 return { success: false, message: 'Error during reset password', errors }; 286 } 287 288 return { success: true, data }; 289} 290 291export async function getSavedCards() { 292 const url = await createUrl('checkoutcomupapi/getTokenList'); 293 294 const response = await performCommerceRestQuery(url, true); 295 296 const { 297 data, success, message, status, 298 } = response; 299 300 if (!success) { 301 console.error('Error fetching saved cards', status, message); 302 return null; 303 } 304 305 return data; 306} 307 308export async function deleteSavedCard(publicHash) { 309 const customer = await getCustomer(true); 310 311 if (!customer) { 312 return { 313 success: false, message: 'No customer', status: 400, 314 }; 315 } 316 317 const url = await createUrl(`checkoutcomupapi/deleteTokenByPublicHash/${publicHash}`); 318 319 const response = await performCommerceRestMutation(url, {}, true, 'DELETE'); 320 321 const { 322 data, success, message, status, 323 } = response; 324 325 if (!success) { 326 console.error('Error deleting saved card', data, status, message); 327 return null; 328 } 329 330 return response; 331}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.