update industry page && bugfixing forecast
This commit is contained in:
parent
fdd8ecaf3e
commit
13c86dbd77
@ -1,13 +1,22 @@
|
|||||||
<script lang='ts'>
|
<script lang='ts'>
|
||||||
import { numberOfUnreadNotification } from '$lib/store';
|
import { numberOfUnreadNotification } from '$lib/store';
|
||||||
|
import { goto } from '$app/navigation';
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
|
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function handleMode(i) {
|
function handleMode(i) {
|
||||||
activeIdx = i;
|
activeIdx = i;
|
||||||
|
if(activeIdx === 0) {
|
||||||
|
goto("/industry")
|
||||||
|
} else if (activeIdx === 1) {
|
||||||
|
goto("/industry/sectors")
|
||||||
|
} else if (activeIdx === 2) {
|
||||||
|
goto("/industry/all")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
@ -24,6 +33,15 @@
|
|||||||
|
|
||||||
let activeIdx = 0;
|
let activeIdx = 0;
|
||||||
|
|
||||||
|
// Subscribe to the $page store to reactively update the activeIdx based on the URL
|
||||||
|
$: if ($page.url.pathname === '/industry') {
|
||||||
|
activeIdx = 0;
|
||||||
|
} else if ($page.url.pathname.startsWith('/industry/sectors')) {
|
||||||
|
activeIdx = 1;
|
||||||
|
} else if ($page.url.pathname.startsWith('/industry/all')) {
|
||||||
|
activeIdx = 2;
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { industryList, sectorList } from '$lib/utils';
|
|||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
let rawData = data?.getIndustryOverview;
|
let rawData = data?.getSectorIndustryOverview;
|
||||||
|
|
||||||
const sectorNavigation = [
|
const sectorNavigation = [
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
import { getCache, setCache } from "$lib/store";
|
import { getCache, setCache } from "$lib/store";
|
||||||
|
|
||||||
export const load = async ({ parent }) => {
|
export const load = async ({ parent }) => {
|
||||||
const getIndustryOverview = async () => {
|
const getSectorIndustryOverview = async () => {
|
||||||
let output;
|
let output;
|
||||||
|
|
||||||
// Get cached data for the specific tickerID
|
// Get cached data for the specific tickerID
|
||||||
const cachedData = getCache("", "getIndustryOverview");
|
const cachedData = getCache("", "getSectorIndustryOverview");
|
||||||
if (cachedData) {
|
if (cachedData) {
|
||||||
output = cachedData;
|
output = cachedData;
|
||||||
} else {
|
} else {
|
||||||
const { apiKey, apiURL } = await parent();
|
const { apiKey, apiURL } = await parent();
|
||||||
|
|
||||||
const response = await fetch(apiURL + "/industry-overview", {
|
const response = await fetch(apiURL + "/sector-industry-overview", {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@ -21,7 +21,7 @@ export const load = async ({ parent }) => {
|
|||||||
|
|
||||||
output = await response.json();
|
output = await response.json();
|
||||||
|
|
||||||
setCache("", output, "getAllReEITs");
|
setCache("", output, "getSectorIndustryOverview");
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
@ -29,6 +29,6 @@ export const load = async ({ parent }) => {
|
|||||||
|
|
||||||
// Make sure to return a promise
|
// Make sure to return a promise
|
||||||
return {
|
return {
|
||||||
getIndustryOverview: await getIndustryOverview(),
|
getSectorIndustryOverview: await getSectorIndustryOverview(),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
153
src/routes/industry/all/+page.svelte
Normal file
153
src/routes/industry/all/+page.svelte
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
<script lang='ts'>
|
||||||
|
import { screenWidth } from '$lib/store';
|
||||||
|
import { abbreviateNumber } from '$lib/utils';
|
||||||
|
import { goto } from '$app/navigation';
|
||||||
|
|
||||||
|
export let data;
|
||||||
|
let rawData = data?.getIndustryOverview;
|
||||||
|
|
||||||
|
const sectorNavigation = [
|
||||||
|
{
|
||||||
|
title: 'Financial Services',
|
||||||
|
link: '/list/financial-sector'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Finance',
|
||||||
|
link: '/list/financial-sector'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Healthcare',
|
||||||
|
link: '/list/healthcare-sector'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Technology',
|
||||||
|
link: '/list/technology-sector'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Industrials',
|
||||||
|
link: '/list/industrials-sector'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Energy',
|
||||||
|
link: '/list/energy-sector'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Utilities',
|
||||||
|
link: '/list/utilities-sector'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Consumer Cyclical',
|
||||||
|
link: '/list/consumer-cyclical-sector'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Real Estate',
|
||||||
|
link: '/list/real-estate-sector'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Basic Materials',
|
||||||
|
link: '/list/basic-materials-sector'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Communication Services',
|
||||||
|
link: '/list/communication-services-sector'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Consumer Defensive',
|
||||||
|
link: '/list/consumer-defensive-sector'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
function sectorSelector(sector) {
|
||||||
|
const selectedSector = sectorNavigation?.find(item => item?.title === sector);
|
||||||
|
|
||||||
|
if (selectedSector) {
|
||||||
|
goto(selectedSector?.link);
|
||||||
|
} else {
|
||||||
|
// Handle the case when the sector is not found
|
||||||
|
console.error(`Sector not found: ${sector}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$: charNumber = $screenWidth < 640 ? 20 : 30;
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<section class="w-full overflow-hidden m-auto px-2 sm:px-0">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Page wrapper -->
|
||||||
|
<div class="flex justify-center w-full m-auto h-full overflow-hidden">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Content area -->
|
||||||
|
<div class="w-full overflow-x-scroll">
|
||||||
|
|
||||||
|
<table class="table rounded-none sm:rounded-md w-full m-auto mt-4 ">
|
||||||
|
<thead>
|
||||||
|
<tr class="border border-slate-800">
|
||||||
|
<th class="text-white font-semibold text-[1rem]">Industry Name</th>
|
||||||
|
<th class="text-white text-end font-semibold text-[1rem]">Stocks</th>
|
||||||
|
<th class="text-white font-semibold text-end text-[1rem]">Market Cap</th>
|
||||||
|
<th class="text-white font-semibold text-[1rem] text-end">Div. Yield</th>
|
||||||
|
<th class="text-white font-semibold text-[1rem] text-end">PE Ratio</th>
|
||||||
|
<th class="text-white font-semibold text-[1rem] text-end">Profit Margin</th>
|
||||||
|
<th class="text-white font-semibold text-[1rem] text-end">1M Change</th>
|
||||||
|
<th class="text-white font-semibold text-[1rem] text-end">1Y Change</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{#each rawData as item}
|
||||||
|
<!-- row -->
|
||||||
|
<tr on:click={() => sectorSelector(item?.sector)} class="cursor-pointer sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] border-b-[#09090B]">
|
||||||
|
<td class="hover:sm:text-white text-blue-400 font-medium text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
|
||||||
|
{item?.industry?.length > charNumber ? item?.industry?.slice(0,charNumber) + "..." : item?.industry}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="text-white text-end text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
|
||||||
|
{item?.numStocks}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class="text-white text-end font-medium text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
|
||||||
|
{abbreviateNumber(item?.totalMarketCap) ?? '-'}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class="text-white text-end font-medium text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
|
||||||
|
{item?.avgDividendYield?.toFixed(2) ?? '-'}%
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class="text-white text-end font-medium text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
|
||||||
|
{item?.pe?.toFixed(2) ?? '-'}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="text-white font-medium text-sm sm:text-[1rem] whitespace-nowrap text-end border-b-[#09090B]">
|
||||||
|
{item?.profitMargin?.toFixed(2)}%
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class="{item?.avgChange1M >= 0 ? 'text-[#10DB06]' : 'text-[#FF2F1F]'} text-end font-medium text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
|
||||||
|
{item?.avgChange1M?.toFixed(2) ?? '-'}%
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class="{item?.avgChange1Y >= 0 ? 'text-[#10DB06]' : 'text-[#FF2F1F]'} text-end font-medium text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
|
||||||
|
{item?.avgChange1Y?.toFixed(2) ?? '-'}%
|
||||||
|
</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
{/each}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
34
src/routes/industry/all/+page.ts
Normal file
34
src/routes/industry/all/+page.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { getCache, setCache } from "$lib/store";
|
||||||
|
|
||||||
|
export const load = async ({ parent }) => {
|
||||||
|
const getIndustryOverview = async () => {
|
||||||
|
let output;
|
||||||
|
|
||||||
|
// Get cached data for the specific tickerID
|
||||||
|
const cachedData = getCache("", "getIndustryOverview");
|
||||||
|
if (cachedData) {
|
||||||
|
output = cachedData;
|
||||||
|
} else {
|
||||||
|
const { apiKey, apiURL } = await parent();
|
||||||
|
|
||||||
|
const response = await fetch(apiURL + "/industry-overview", {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"X-API-KEY": apiKey,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
output = await response.json();
|
||||||
|
|
||||||
|
setCache("", output, "getIndustryOverview");
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Make sure to return a promise
|
||||||
|
return {
|
||||||
|
getIndustryOverview: await getIndustryOverview(),
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -1,11 +1,10 @@
|
|||||||
<script lang='ts'>
|
<script lang='ts'>
|
||||||
import { screenWidth } from '$lib/store';
|
import { screenWidth } from '$lib/store';
|
||||||
import IndustryTable from '$lib/components/IndustryTable.svelte';
|
import { abbreviateNumber } from '$lib/utils';
|
||||||
import { industryList, sectorList } from '$lib/utils';
|
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
let rawData = data?.getIndustryOverview;
|
let rawData = data?.getSectorOverview;
|
||||||
|
|
||||||
const sectorNavigation = [
|
const sectorNavigation = [
|
||||||
{
|
{
|
||||||
@ -69,6 +68,7 @@ function sectorSelector(sector) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$: charNumber = $screenWidth < 640 ? 20 : 30;
|
$: charNumber = $screenWidth < 640 ? 20 : 30;
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
@ -76,11 +76,6 @@ $: charNumber = $screenWidth < 640 ? 20 : 30;
|
|||||||
<section class="w-full overflow-hidden m-auto px-2 sm:px-0">
|
<section class="w-full overflow-hidden m-auto px-2 sm:px-0">
|
||||||
|
|
||||||
|
|
||||||
<div class="border border-gray-800 w-full sm:flex sm:flex-row sm:items-center m-auto text-gray-100 bg-[#09090B] sm:rounded-lg h-auto p-5 mb-4">
|
|
||||||
<svg class="w-5 h-5 inline-block sm:mr-2 flex-shrink-0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><path fill="#a474f6" d="M128 24a104 104 0 1 0 104 104A104.11 104.11 0 0 0 128 24m-4 48a12 12 0 1 1-12 12a12 12 0 0 1 12-12m12 112a16 16 0 0 1-16-16v-40a8 8 0 0 1 0-16a16 16 0 0 1 16 16v40a8 8 0 0 1 0 16"/></svg>
|
|
||||||
We categorize stocks into {sectorList?.length} sectors and {industryList?.length} industries, based on the company's primary business activity.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Page wrapper -->
|
<!-- Page wrapper -->
|
||||||
@ -89,22 +84,68 @@ $: charNumber = $screenWidth < 640 ? 20 : 30;
|
|||||||
|
|
||||||
|
|
||||||
<!-- Content area -->
|
<!-- Content area -->
|
||||||
<div class="w-full">
|
<div class="w-full overflow-x-scroll">
|
||||||
{#each sectorList as sector}
|
|
||||||
<h2 on:click={() => sectorSelector(sector)} class="cursor-pointer text-white sm:hover:underline font-semibold text-lg sm:text-xl mt-5">
|
<table class="table rounded-none sm:rounded-md w-full m-auto mt-4 ">
|
||||||
Sector: {sector} <svg class="inline-block h-6 w-6 -mt-1" viewBox="0 0 20 20" fill="white" style="max-width:40px"><path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path></svg>
|
<thead>
|
||||||
</h2>
|
<tr class="border border-slate-800">
|
||||||
|
<th class="text-white font-semibold text-[1rem]">Industry Name</th>
|
||||||
|
<th class="text-white text-end font-semibold text-[1rem]">Stocks</th>
|
||||||
|
<th class="text-white font-semibold text-end text-[1rem]">Market Cap</th>
|
||||||
|
<th class="text-white font-semibold text-[1rem] text-end">Div. Yield</th>
|
||||||
|
<th class="text-white font-semibold text-[1rem] text-end">PE Ratio</th>
|
||||||
|
<th class="text-white font-semibold text-[1rem] text-end">Profit Margin</th>
|
||||||
|
<th class="text-white font-semibold text-[1rem] text-end">1M Change</th>
|
||||||
|
<th class="text-white font-semibold text-[1rem] text-end">1Y Change</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{#each rawData as item}
|
||||||
|
<!-- row -->
|
||||||
|
<tr on:click={() => sectorSelector(item?.sector)} class="cursor-pointer sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-[#27272A] border-b-[#09090B]">
|
||||||
|
<td class="hover:sm:text-white text-blue-400 font-medium text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
|
||||||
|
{item?.sector?.length > charNumber ? item?.sector?.slice(0,charNumber) + "..." : item?.sector}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="text-white text-end text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
|
||||||
|
{item?.numStocks}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class="text-white text-end font-medium text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
|
||||||
|
{abbreviateNumber(item?.totalMarketCap) ?? '-'}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class="text-white text-end font-medium text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
|
||||||
|
{item?.avgDividendYield?.toFixed(2) ?? '-'}%
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class="text-white text-end font-medium text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
|
||||||
|
{item?.pe?.toFixed(2) ?? '-'}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="text-white font-medium text-sm sm:text-[1rem] whitespace-nowrap text-end border-b-[#09090B]">
|
||||||
|
{item?.profitMargin?.toFixed(2)}%
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class="{item?.avgChange1M >= 0 ? 'text-[#10DB06]' : 'text-[#FF2F1F]'} text-end font-medium text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
|
||||||
|
{item?.avgChange1M?.toFixed(2) ?? '-'}%
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class="{item?.avgChange1Y >= 0 ? 'text-[#10DB06]' : 'text-[#FF2F1F]'} text-end font-medium text-sm sm:text-[1rem] whitespace-nowrap border-b-[#09090B]">
|
||||||
|
{item?.avgChange1Y?.toFixed(2) ?? '-'}%
|
||||||
|
</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
|
||||||
<div class="border-t border-gray-600 mt-5"/>
|
|
||||||
|
|
||||||
<IndustryTable charNumber = {charNumber} industryList = {rawData[sector]} />
|
|
||||||
<div class="border-t border-gray-600 mt-5"/>
|
|
||||||
{/each}
|
{/each}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
34
src/routes/industry/sectors/+page.ts
Normal file
34
src/routes/industry/sectors/+page.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { getCache, setCache } from "$lib/store";
|
||||||
|
|
||||||
|
export const load = async ({ parent }) => {
|
||||||
|
const getSectorOverview = async () => {
|
||||||
|
let output;
|
||||||
|
|
||||||
|
// Get cached data for the specific tickerID
|
||||||
|
const cachedData = getCache("", "getSectorOverview");
|
||||||
|
if (cachedData) {
|
||||||
|
output = cachedData;
|
||||||
|
} else {
|
||||||
|
const { apiKey, apiURL } = await parent();
|
||||||
|
|
||||||
|
const response = await fetch(apiURL + "/sector-overview", {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"X-API-KEY": apiKey,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
output = await response.json();
|
||||||
|
|
||||||
|
setCache("", output, "getSectorOverview");
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Make sure to return a promise
|
||||||
|
return {
|
||||||
|
getSectorOverview: await getSectorOverview(),
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -10,7 +10,7 @@
|
|||||||
let changeEPS = 0;
|
let changeEPS = 0;
|
||||||
function findIndex(data) {
|
function findIndex(data) {
|
||||||
const currentYear = new Date().getFullYear();
|
const currentYear = new Date().getFullYear();
|
||||||
return data?.findIndex((item) => item?.date >= currentYear && item?.revenue === null);
|
return data?.findIndex((item) => item?.date > currentYear && item?.revenue === null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data?.getAnalystEstimate?.length !== 0) {
|
if (data?.getAnalystEstimate?.length !== 0) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user