diff --git a/frontend/src/app.d.ts b/frontend/src/app.d.ts index 56235ab..20ff1f9 100644 --- a/frontend/src/app.d.ts +++ b/frontend/src/app.d.ts @@ -109,10 +109,14 @@ declare global { } } } + // prototype functions are declared in ./lib/utils interface String { removeUnderscores(): string capitalize(): string } + interface Number { + toDecimalPoint(decimal: number): Number + } } export {} diff --git a/frontend/src/lib/utils.ts b/frontend/src/lib/utils.ts index 159b301..7377262 100644 --- a/frontend/src/lib/utils.ts +++ b/frontend/src/lib/utils.ts @@ -70,6 +70,7 @@ export const flyAndScale = ( } } +// type declaration are in ../app.d.ts // this works because its imported in the root layout by other components String.prototype.removeUnderscores = function () { return this.replace(/_/g, ' ') @@ -78,3 +79,11 @@ String.prototype.removeUnderscores = function () { String.prototype.capitalize = function () { return this.charAt(0).toUpperCase() + this.slice(1) } + +Number.prototype.toDecimalPoint = function (decimal: number) { + const decimalInInt = Math.round(decimal) + + const value = 10 ** decimalInInt + + return Math.round(this.valueOf() * value) / value +} diff --git a/frontend/src/routes/(app)/dashboard/links/[id]/+page.svelte b/frontend/src/routes/(app)/dashboard/links/[id]/+page.svelte index c5b0b3d..762fc2e 100644 --- a/frontend/src/routes/(app)/dashboard/links/[id]/+page.svelte +++ b/frontend/src/routes/(app)/dashboard/links/[id]/+page.svelte @@ -141,15 +141,25 @@ {#each data.visitorByCountry as visitorByCountry} -
+
{visitorByCountry.country}
-
{visitorByCountry.count}
+
+ {visitorByCountry.count} + + ({( + (visitorByCountry.count / + data.visitorAllTime[0].count) * + 100 + ).toDecimalPoint(2)} %) + +
{#each data.visitorByCity as visitorByCity} -
+
{visitorByCity.city}
-
{visitorByCity.count}
+
+ {visitorByCity.count} + + ({( + (visitorByCity.count / + data.visitorAllTime[0].count) * + 100 + ).toDecimalPoint(2)} %) + +
-
- {#each data.visitorByDeviceVendor as visitorByDeviceVendor} -
-
-
- -
- {visitorByDeviceVendor.vendor ?? '(None)'} -
+ {#each data.visitorByDeviceVendor as visitorByDeviceVendor} +
+
+
+ +
+ {visitorByDeviceVendor.vendor || '(None)'}
-
{visitorByDeviceVendor.count}
- +
+ {visitorByDeviceVendor.count} + + ({( + (visitorByDeviceVendor.count / + data.visitorAllTime[0].count) * + 100 + ).toDecimalPoint(2)} %) + +
- {/each} -
+ +
+ {/each} -
- {#each data.visitorByDeviceType as visitorByDeviceType} -
-
-
- {#if visitorByDeviceType.type === 'mobile'} - - {:else if visitorByDeviceType.type === 'tablet'} - - {:else} - - {/if} -
- {visitorByDeviceType.type ?? '(None)'} -
+ {#each data.visitorByDeviceType as visitorByDeviceType} +
+
+
+ {#if visitorByDeviceType.type === 'mobile'} + + {:else if visitorByDeviceType.type === 'tablet'} + + {:else} + + {/if} +
+ {visitorByDeviceType.type ?? '(None)'}
-
{visitorByDeviceType.count}
- +
+ {visitorByDeviceType.count} + + ({( + (visitorByDeviceType.count / + data.visitorAllTime[0].count) * + 100 + ).toDecimalPoint(2)} %) + +
- {/each} -
+ +
+ {/each} @@ -260,44 +296,60 @@ -
- {#each data.visitorByOS as visitorByOS} -
-
-
- -
{visitorByOS.os ?? '(None)'}
-
-
{visitorByOS.count}
+ {#each data.visitorByOS as visitorByOS} +
+
+
+ +
{visitorByOS.os ?? '(None)'}
+
+
+ {visitorByOS.count} + + ({( + (visitorByOS.count / + data.visitorAllTime[0].count) * + 100 + ).toDecimalPoint(2)} %) +
-
- {/each} -
+ +
+ {/each} -
- {#each data.visitorByBrowser as visitorByBrowser} -
-
-
- -
- {visitorByBrowser.browser ?? '(None)'} -
+ {#each data.visitorByBrowser as visitorByBrowser} +
+
+
+ +
+ {visitorByBrowser.browser ?? '(None)'}
-
{visitorByBrowser.count}
- +
+ {visitorByBrowser.count} + + ({( + (visitorByBrowser.count / + data.visitorAllTime[0].count) * + 100 + ).toDecimalPoint(2)} %) + +
- {/each} -
+ +
+ {/each}