UNPKG

portal-www

Version:

Nova Portal Website. Based on Next starter by Ueno

625 lines (547 loc) 15.7 kB
import { ThemeColorType } from '@nova-hf/ui'; import { addMonths, differenceInCalendarDays, format, formatDistanceStrict, subMonths, } from 'date-fns'; import is from 'date-fns/locale/is'; import { get, isEmpty, set } from 'lodash'; import { IAmount, IRateplan, IUser } from 'typings'; import { CartItem, PurchaseInfoInput, Rateplan } from 'typings/graphql'; const locales = { 'is-IS': is, }; interface IOpts { showZero?: boolean; showDecimals?: boolean; monthly?: boolean; unit?: string; } export function formatPrice( price: number, opts: IOpts = { showZero: true, showDecimals: false, monthly: false }, ) { if (!price || price === 0) { return get(opts, 'showZero') ? `0 kr.${ get(opts, 'monthly') ? ` ${get(opts, 'unit') ? `/ ${get(opts, 'unit')}` : '/ mán'}` : '' }` : '—'; } const isMinus = price < 0; const decimal = opts.showDecimals ? 2 : 0; return `${isMinus ? '-' : ''}${price .toFixed(decimal) .replace('.', ',') .replace('-', '') .replace(/./g, (c, i, a) => (i && c !== ',' && (a.length - i) % 3 === 0 ? `.${c}` : c))} kr.${ get(opts, 'monthly') ? ` ${get(opts, 'unit') ? `/ ${get(opts, 'unit')}` : '/ mán'}` : '' }`; } export function formatCardExpiryDate(date: string) { // in temoorary use while we figure out how wee will deliver expiry date if (date.length === 4 && /^-?\d+$/.test(date)) { return `${date.slice(0, 2)}/${date.slice(2, 4)}`; } else return date; } export function isCompany(ssn: string) { const firstDigit = parseInt(ssn[0], 10); return !isNaN(firstDigit) && firstDigit > 3; } export function isStringPhoneNumber(testString: string) { const phoneRegex = /^(\d{3})?[-.●]?(\d{3})?[-.●]?(\d{4})$/; return phoneRegex.test(testString); } export function formatNumber(number: number) { const isMinus = number < 0; return `${isMinus ? '-' : ''}${number .toFixed(0) .replace('.', ',') .replace('-', '') .replace(/./g, (c, i, a) => (i && c !== ',' && (a.length - i) % 3 === 0 ? `.${c}` : c))}`; } export function formatPhone(phone: string) { if (!phone) { return '—'; } return phone.replace('-', '').replace(/^(.{3})(.*)$/, '$1 $2'); } export function formatTel(number: string) { if (!number || isNaN(parseInt(number, 10)) || number.length !== 7) { return number; } return `${number.slice(0, 3)} ${number.slice(3)}`; } /** * Date-fns format localized to is-IS * @param date * @param formatString */ export function formatDate(date: Date, formatString: string) { const dateItem = date instanceof Date ? date : new Date(date); return format(dateItem, formatString, { locale: locales['is-IS'], }); } export function formatAmount(num: number) { return num .toString() .replace('.', ',') .replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1.'); } export function capitalize(str: string) { return str.length > 0 ? str.charAt(0).toUpperCase() + str.slice(1) : str; } export function mockGenerator(id: string) { if (id == '23cf25c9-119a-4000-9062-3d8f334035b0') { return { name: 'Björgvin', service: 'AlltSaman', pack: 'Meira', color: 'orange', price: '19.900 kr.', icon: 'alltSaman', }; } if (id == '967af583-924a-4291-ab53-8241857d734c') { return { name: 'Unnur', service: 'Ljósleiðari', pack: '500 GB', color: 'purple', price: '11.790 kr.', icon: 'internet', }; } if (id == 'bd36c2a5-8c47-4580-9bea-8c4bdc89e93a') { return { name: 'Andrea', service: 'Frelsi', pack: '10 GB', color: 'pink', price: '2.490 kr.', icon: 'mobileStar', }; } if (id == 'dc1343ce-0e25-4c1f-9178-c354f332893f') { return { name: 'Ástþór', service: 'Áskrift', pack: '100 GB', color: 'ocean', price: '3.990 kr.', icon: 'mobilePlus', }; } if (id == '9c39ba3b-2d49-471a-c2d0-08dab34e9570') { return { name: 'Sigurjón', service: 'Áskrift', pack: '150 GB', color: 'ocean', price: '6.990 kr.', icon: 'mobilePlus', }; } if (id == 'cd6fc737-daa3-44ca-c2d1-08dab34e9570') { return { name: 'Hilma', service: 'MínusÁtján', pack: '2 GB', color: 'pink', price: '0 kr.', icon: 'bestDeal', }; } if (id == 'b29d78bf-37fd-4ce4-c2d2-08dab34e9570') { return { name: 'Hrafnhildur', service: 'Sjálfsvörn', pack: 'Íbúð', color: 'green', price: '3.990 kr.', icon: 'lock', }; } else { return { name: 'Gunnþór', service: 'Áskrift', pack: '100 GB', color: 'ocean', price: '3.990 kr.', icon: 'mobilePlus', }; } } export function pages(totalCount: number, perPage: number) { return Math.ceil(totalCount / perPage); } export const getMonth = (date: number | Date) => { return format(date, 'MMMM', { locale: locales['is-IS'], }); }; export function getMonths(date: number | Date, count: number) { const dateInPast = subMonths(date, count); return Array(count + 1) .fill(0) .map((_, i) => { const newdate = addMonths(dateInPast, i); return { month: format(newdate, 'MMMM', { locale: locales['is-IS'], }), date: newdate, }; }); } export function formatMillisRemaining(t: number) { const cd = 24 * 60 * 60 * 1000; const ch = 60 * 60 * 1000; const cmon = cd * 30; const mon = Math.floor(t / cmon); let d = Math.floor(t / cd); let h = Math.floor((t - d * cd) / ch); let m = Math.round((t - d * cd - h * ch) / 60000); if (m === 60) { h += 1; m = 0; } if (h === 24) { d += 1; h = 0; } if (d > 31) { if (mon === 1) { return `${mon} mánuður`; } return `${mon} mánuðir`; } if (d > 0) { if (d === 1) { return `${d} dagur`; } return `${d} dagar`; } return `${d}d ${h}k ${m}m`; } export function objectToQuery(obj: { [key: string]: string }) { return Object.keys(obj) .map((key) => { return `${encodeURIComponent(key)}=${encodeURIComponent(obj[key])}`; }) .join('&'); } export function formElementsToObject(elements: HTMLCollectionOf<HTMLInputElement>) { const obj = {}; Object.entries(elements).forEach(([_, field]) => { const attr: string = get(field, ['dataset', 'key']); if (attr !== undefined) { if (field.type === 'checkbox') { set(obj, attr.split('.'), field.checked); } else if (field.type !== 'submit') { set(obj, attr.split('.'), field.value); } } }); return obj; } export function queryToObject(query: string) { if (query.length < 1) { return {}; } const search = query.substring(1); return JSON.parse( `{"${decodeURI(search).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"')}"}`, ); } export function hasLocalStorage() { const test = 'test'; try { localStorage.setItem(test, test); localStorage.removeItem(test); return true; } catch (e) { return false; } } export function diffInDays(dateFrom: Date, dateTo: Date) { return differenceInCalendarDays(dateFrom, dateTo); } export function profileColor(rateplan: IRateplan | Rateplan) { if (rateplan.isVip) { return 'viola'; } switch (rateplan.typeId) { case 'fiber': return 'yellow'; case 'internet': return 'green'; case 'mobile': return rateplan.isPrepaid ? 'pink' : 'ocean'; case 'service_bundle': return 'orange'; case 'vip_service_bundle': return 'dark'; case 'forwarding': return 'purple'; case 'unregistered': return 'pink'; case 'tv_content_channel': return 'pink'; default: return 'ocean'; } } export function connectionColor(type: string) { switch (type) { case 'Mobile': return 'pink'; case 'Internet': return 'yellow'; case 'CallForwarding': return 'purple'; case 'BackupConnection': return 'ocean'; default: return 'ocean'; } } /** * @param name String * @returns String */ export function formatFirstName(name: string) { if (name) { if (name.includes('TANKAR\\')) { return name.split('\\')[1]; } return name.split(' ')[0]; } return ''; } export function formatName(user: IUser) { return formatFirstName(user.name); } export function distanceToDate(futureDate: Date, nowDate: Date) { return formatDistanceStrict(futureDate, nowDate, { locale: locales['is-IS'], }); } export function convertData(remaining: IAmount, included: IAmount) { const base = { B: 0, KB: 1, MB: 2, GB: 3, }; const r = base[remaining.unit]; const incl = base[included.unit]; const diff = Math.abs(incl - r); if (diff === 0) { return [remaining, included]; } if (r < incl) { const remainingResult = remaining.amount / (1024 * diff); return [{ amount: remainingResult, unit: included.unit }, included]; } const includedResult = included.amount / (1024 * diff); return [remaining, { amount: includedResult, unit: remaining.unit }]; } export function remainingPercentage(remaining: IAmount, included: IAmount) { const base = { B: 0, KB: 1, MB: 2, GB: 3, }; if (isEmpty(remaining) || isEmpty(included)) return 0; const r = base[remaining.unit]; const incl = base[included.unit]; const diff = Math.abs(incl - r); if (diff === 0) { return (remaining.amount / included.amount) * 100; } if (r < incl) { return (remaining.amount / (included.amount * (1024 * diff))) * 100; } return ((remaining.amount * (1024 * diff)) / included.amount) * 100; } export function scrollToElement(element: string, shouldScrollFromTop?: boolean) { const scrollTop = window.pageYOffset || window.scrollY; const domElement = typeof element === 'string' ? document.querySelector(element) : element; if (!domElement || (!shouldScrollFromTop && domElement.getBoundingClientRect().top > 0)) { return; } const num = domElement.getBoundingClientRect().top + scrollTop; return window.scrollTo({ top: num, left: 0, behavior: 'smooth', }); } export function signupScroll(element: string, instant?: boolean) { const domElement = typeof element === 'string' ? document.querySelector(element) : element; if (!domElement) { return; } const rect = domElement.getBoundingClientRect(); const scrollTop = window.scrollY || document.documentElement.scrollTop; // Adjust scroll position relative to current scroll position const num = rect.top + scrollTop - (window.innerHeight / 2 - rect.height / 2); return window.scrollTo({ top: num, left: 0, behavior: instant ? 'instant' : 'smooth', }); } export function getOpportunityColor(category: string) { switch (category) { case 'vip': return 'purple'; case 'service_bundle': return 'orange'; case 'vip_service_bundle': return 'dark'; case 'watch': return 'ocean'; case 'fiber': return 'yellow'; case 'internet': return 'green'; case 'mobile_prepaid': return 'pink'; case 'mobile_postpaid': return 'ocean'; case 'unregistered': return 'pink'; default: return 'ocean'; } } export function stripTypenames(properties: any) { if (Array.isArray(properties)) { return properties.map(stripTypenames); } else if (!isEmpty(properties) && typeof properties === 'object') { const newProperties = {}; for (const property in properties) { if (property !== '__typename') { newProperties[property] = stripTypenames(properties[property]); } } return newProperties; } return properties; } export const formatNationalId = (nationalId: string): string => `${nationalId.slice(0, 6)} ${nationalId.slice(6)}`; export const isNationalIdValid = (nationalId: string): boolean => { const pattern = /^\d{10}$/; return pattern.test(nationalId); }; export function emailValidate(email: string) { return /^(([^<>()[\]\\.,;:\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,}))$/.test( email, ); //eslint-disable-line } export function serializeObject(obj: { [key: string]: string }) { const str: Array<string> = []; Object.keys(obj).forEach((key) => { if (typeof obj[key] !== 'undefined') { str.push(`${encodeURIComponent(key)}=${encodeURIComponent(obj[key])}`); } }); return str.length > 0 ? `?${str.join('&')}` : ''; } export function maritalStatusMap(status?: string) { switch (status) { case 'Unmarried': return 'Ógift(ur)'; case 'IcelanderAbroadMarriedToAForeigner': return 'Íslendingur með lögheimili erlendis í hjúskap með útlendingi sem ekki er á skrá'; case 'LegallySeparated': return 'Skilin(n) að borði og sæng'; case 'IcelanderMarriedToAForeigner': return 'Íslendingur í hjúskap með útlendingi'; case 'MarriedOrRegisteredCohabitation': return 'Gift(ur) eða staðfest sambúð'; case 'Undisclosed': return 'Hjón ekki í samvistum'; case 'MarriedNotCohabitating': return 'Hjúskaðarstaða óupplýst'; case 'DivorcedByLaw': return 'Skilin(n) að lögum'; case 'Widow': return 'Ekkja eða ekkill'; default: return 'Óþekkt'; } } export const textColorByBackgroundColor = (backgroundColor: ThemeColorType): ThemeColorType => { switch (backgroundColor) { case 'grey400': case 'grey300': case 'grey200': case 'grey100': case 'ocean': case 'white': case 'yellow': return 'black100'; default: return 'white'; } }; export const isSignupMobileReference = ( referenceItem: CartItem | undefined, ): referenceItem is CartItem & { purchaseInfo: { contract: { __typename: 'SignupContract' }; service: { __typename: 'MobileServiceRequest' }; }; } => { return ( referenceItem?.purchaseInfo?.contract?.__typename === 'SignupContract' && referenceItem?.purchaseInfo?.service?.__typename === 'MobileServiceRequest' ); }; export const hasValidPurchaseInfo = ( serviceItem: { purchaseInfo?: unknown } | undefined, ): serviceItem is { purchaseInfo: PurchaseInfoInput } => { return serviceItem?.purchaseInfo !== undefined; }; export const hasMobileServiceRequest = ( serviceItem: CartItem | undefined, ): serviceItem is CartItem & { purchaseInfo: { service: { __typename: 'MobileServiceRequest'; user: unknown; }; }; } => { return ( serviceItem !== undefined && serviceItem.purchaseInfo !== undefined && serviceItem.purchaseInfo !== null && serviceItem.purchaseInfo.service !== undefined && serviceItem.purchaseInfo.service !== null && serviceItem.purchaseInfo.service.__typename === 'MobileServiceRequest' && serviceItem.purchaseInfo.service.user !== undefined ); }; export const isEighteenOrOlder = (nationalId: string): boolean => { if (!/^\d{10}$/.test(nationalId)) return false; const day = parseInt(nationalId.slice(0, 2), 10); const month = parseInt(nationalId.slice(2, 4), 10); const year = parseInt(nationalId.slice(4, 6), 10); const century = parseInt(nationalId[9], 10) === 9 ? 1900 : 2000; const birthYear = century + year; const birthDate = new Date(birthYear, month - 1, day); const today = new Date(); const age = today.getFullYear() - birthDate.getFullYear(); const m = today.getMonth() - birthDate.getMonth(); const d = today.getDate() - birthDate.getDate(); return age > 18 || (age === 18 && (m > 0 || (m === 0 && d >= 0))); };