ui fixes
This commit is contained in:
parent
d800bd9084
commit
f1e1ecc2ac
@ -7,8 +7,8 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<SEO
|
<SEO
|
||||||
title="Data Disclaimer"
|
title="Data Disclaimer | StockNear - Financial Data Sources & Accuracy"
|
||||||
description="All data shown on this website is for informational purposes only and should not be relied upon to make trading or investing decisions."
|
description="Comprehensive information about our financial data sources, accuracy standards, and usage guidelines for stock market data, analyst estimates, and financial metrics."
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<section
|
<section
|
||||||
@ -36,11 +36,14 @@
|
|||||||
<div class="w-full bg-default m-auto">
|
<div class="w-full bg-default m-auto">
|
||||||
<div>
|
<div>
|
||||||
<p class="text-white mb-5 text-[1rem] sm:text-lg">
|
<p class="text-white mb-5 text-[1rem] sm:text-lg">
|
||||||
The data on this site is for informational purposes only and
|
The financial data presented on Stocknear is provided for
|
||||||
should not be used for trading or investment decisions.
|
informational and educational purposes only. This information
|
||||||
|
should not be construed as financial advice or used as the sole
|
||||||
|
basis for trading or investment decisions.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
We strive for accuracy and quality. If you spot errors, please contact
|
We maintain rigorous standards for data accuracy and quality assurance.
|
||||||
us via
|
If you identify any discrepancies or require clarification, please
|
||||||
|
reach out to us via
|
||||||
<a
|
<a
|
||||||
href={discordURL}
|
href={discordURL}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@ -49,7 +52,7 @@
|
|||||||
>
|
>
|
||||||
Discord
|
Discord
|
||||||
</a>
|
</a>
|
||||||
or email us at
|
or contact our support team at
|
||||||
<a
|
<a
|
||||||
href="mailto:{emailAddress}"
|
href="mailto:{emailAddress}"
|
||||||
class="text-blue-400 hover:underline"
|
class="text-blue-400 hover:underline"
|
||||||
@ -59,86 +62,103 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2 class="mb-1 text-white text-2xl sm:text-3xl font-bold">
|
<h2 class="mb-1 text-white text-2xl sm:text-3xl font-bold">
|
||||||
Stock Charts
|
Market Data & Stock Charts
|
||||||
</h2>
|
</h2>
|
||||||
<p class="text-white mb-10 mt-5 text-[1rem] sm:text-lg">
|
<p class="text-white mb-10 mt-5 text-[1rem] sm:text-lg">
|
||||||
Intraday and historical stock chart data are provided by
|
Our comprehensive market data and real-time stock charts are
|
||||||
|
powered by
|
||||||
<a
|
<a
|
||||||
href="https://site.financialmodelingprep.com/pricing-plans?couponCode=stocknear"
|
href="https://site.financialmodelingprep.com/pricing-plans?couponCode=stocknear"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
class="text-blue-400 hover:underline"
|
class="text-blue-400 hover:underline"
|
||||||
>
|
>
|
||||||
FMP
|
Financial Modeling Prep (FMP)
|
||||||
</a>.
|
</a>, a leading provider of financial data services. This
|
||||||
|
includes intraday pricing, historical data, and technical
|
||||||
|
indicators.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2 class="mb-1 text-white text-2xl sm:text-3xl font-bold">
|
<h2 class="mb-1 text-white text-2xl sm:text-3xl font-bold">
|
||||||
Stocks Covered
|
Market Coverage
|
||||||
</h2>
|
</h2>
|
||||||
<p class="text-white mb-10 mt-5 text-[1rem] sm:text-lg">
|
<p class="text-white mb-10 mt-5 text-[1rem] sm:text-lg">
|
||||||
Stocknear covers all stocks and ETFs listed on major US
|
Stocknear provides comprehensive coverage of securities listed
|
||||||
exchanges (NASDAQ, NYSE, NYSE American, NYSE Arca) and many OTC
|
on major U.S. exchanges, including NASDAQ, NYSE, NYSE American,
|
||||||
stocks. We also include international companies trading on US
|
and NYSE Arca. Our database encompasses stocks, ETFs, ADRs, and
|
||||||
exchanges and aim to add global stock exchanges soon.
|
select OTC securities. We are actively expanding our coverage to
|
||||||
|
include additional global exchanges and financial instruments.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2 class="mb-1 text-white text-2xl sm:text-3xl font-bold">
|
<h2 class="mb-1 text-white text-2xl sm:text-3xl font-bold">
|
||||||
Historical Financials
|
Financial Fundamentals
|
||||||
</h2>
|
</h2>
|
||||||
<p class="text-white mb-10 mt-5 text-[1rem] sm:text-lg">
|
<p class="text-white mb-10 mt-5 text-[1rem] sm:text-lg">
|
||||||
Fundamental financial data is sourced from
|
Our fundamental financial data is sourced from
|
||||||
<a
|
<a
|
||||||
href="https://site.financialmodelingprep.com/pricing-plans?couponCode=stocknear"
|
href="https://site.financialmodelingprep.com/pricing-plans?couponCode=stocknear"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
class="text-blue-400 hover:underline"
|
class="text-blue-400 hover:underline"
|
||||||
>
|
>
|
||||||
FMP
|
Financial Modeling Prep
|
||||||
</a>, based on official SEC filings (10-K, 10-Q). Data is
|
</a>
|
||||||
updated daily, but delays may occur if companies file late. All
|
and is derived from official SEC filings (Forms 10-K, 10-Q, and 8-K).
|
||||||
displayed data is official, audited, and SEC-submitted.
|
While our systems update this information daily, there may be inherent
|
||||||
|
delays due to standard SEC filing windows and corporate reporting
|
||||||
|
schedules. All financial data presented is based on official, audited
|
||||||
|
company submissions to regulatory authorities.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2 class="mb-1 text-white text-2xl sm:text-3xl font-bold">
|
<h2 class="mb-1 text-white text-2xl sm:text-3xl font-bold">
|
||||||
Price Targets and Analyst Estimates
|
Analyst Coverage & Market Projections
|
||||||
</h2>
|
</h2>
|
||||||
<p class="text-white mb-10 mt-5 text-[1rem] sm:text-lg">
|
<p class="text-white mb-10 mt-5 text-[1rem] sm:text-lg">
|
||||||
Price targets and ratings are from Benzinga, sourced from Wall
|
Our analyst coverage integrates data from multiple authoritative
|
||||||
Street analysts. Revenue and EPS forecasts come from Benzinga
|
sources. Price targets and analyst ratings are provided by
|
||||||
and <a
|
Benzinga, representing consensus views from leading Wall Street
|
||||||
|
analysts. Revenue projections and EPS forecasts are aggregated
|
||||||
|
from both Benzinga and
|
||||||
|
<a
|
||||||
href="https://site.financialmodelingprep.com/pricing-plans?couponCode=stocknear"
|
href="https://site.financialmodelingprep.com/pricing-plans?couponCode=stocknear"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
class="text-blue-400 hover:underline"
|
class="text-blue-400 hover:underline"
|
||||||
>
|
>
|
||||||
FMP
|
Financial Modeling Prep
|
||||||
</a>. Analyst accuracy and performance metrics are also provided
|
</a>. While we strive to present the most accurate forecasts,
|
||||||
by Benzinga. Differences across sources may occur but are
|
users should note that market predictions are inherently
|
||||||
directionally consistent. Use this information cautiously as
|
uncertain and should be considered as part of a broader
|
||||||
predictions are often inaccurate.
|
investment research process.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2 class="mb-1 text-white text-2xl sm:text-3xl font-bold">
|
<h2 class="mb-1 text-white text-2xl sm:text-3xl font-bold">
|
||||||
ETF Holdings
|
ETF Analytics
|
||||||
</h2>
|
</h2>
|
||||||
<p class="text-white mb-10 mt-5 text-[1rem] sm:text-lg">
|
<p class="text-white mb-10 mt-5 text-[1rem] sm:text-lg">
|
||||||
Most ETF holdings data is provided by <a
|
Our ETF holdings data and analytics are provided through our
|
||||||
|
partnership with
|
||||||
|
<a
|
||||||
href="https://site.financialmodelingprep.com/pricing-plans?couponCode=stocknear"
|
href="https://site.financialmodelingprep.com/pricing-plans?couponCode=stocknear"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
class="text-blue-400 hover:underline"
|
class="text-blue-400 hover:underline"
|
||||||
>
|
>
|
||||||
FMP
|
Financial Modeling Prep
|
||||||
</a>.
|
</a>, ensuring accurate and timely information on fund
|
||||||
|
compositions, allocations, and performance metrics.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2 class="mb-1 text-white text-2xl sm:text-3xl font-bold">
|
<h2 class="mb-1 text-white text-2xl sm:text-3xl font-bold">
|
||||||
Options Data
|
Options Market Data
|
||||||
</h2>
|
</h2>
|
||||||
<p class="text-white mb-10 mt-5 text-[1rem] sm:text-lg">
|
<p class="text-white mb-10 mt-5 text-[1rem] sm:text-lg">
|
||||||
Options flow data is sourced from Benzinga via OPRA. Individual
|
Our options market data infrastructure combines real-time
|
||||||
ticker options data is from Intrinio, also sourced from OPRA.
|
options flow information from Benzinga and individual options
|
||||||
|
chain data from Intrinio, both sourced through the Options Price
|
||||||
|
Reporting Authority (OPRA). This provides comprehensive coverage
|
||||||
|
of options market activity and pricing across all major
|
||||||
|
exchanges.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -18,9 +18,11 @@
|
|||||||
|
|
||||||
let filterList = [];
|
let filterList = [];
|
||||||
let weekdayFiltered = [];
|
let weekdayFiltered = [];
|
||||||
let weekday; // Added declaration
|
let weekday = []; // our unordered week data
|
||||||
let syncWorker: Worker | undefined;
|
let syncWorker: Worker | undefined;
|
||||||
let pagePathName = $page?.url?.pathname;
|
let pagePathName: string = "";
|
||||||
|
// reassign pagePathName reactively
|
||||||
|
$: pagePathName = $page?.url?.pathname || "";
|
||||||
|
|
||||||
const maxWeeksChange = 6;
|
const maxWeeksChange = 6;
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
@ -31,21 +33,27 @@
|
|||||||
let sortMode = false;
|
let sortMode = false;
|
||||||
$: testList = [];
|
$: testList = [];
|
||||||
|
|
||||||
|
// Get calendar data from our load function
|
||||||
$: economicCalendar = data?.getEconomicCalendar;
|
$: economicCalendar = data?.getEconomicCalendar;
|
||||||
|
// Calculate the week days
|
||||||
$: daysOfWeek = getDaysOfWeek(currentWeek);
|
$: daysOfWeek = getDaysOfWeek(currentWeek);
|
||||||
|
// Format days for header labels
|
||||||
$: formattedWeekday = daysOfWeek.map((day) => format(day.date, "EEE, MMM d"));
|
$: formattedWeekday = daysOfWeek.map((day) => format(day.date, "EEE, MMM d"));
|
||||||
$: {
|
|
||||||
if (!sortMode) {
|
|
||||||
weekday = getWeekdayData(economicCalendar, daysOfWeek);
|
|
||||||
rawData = weekday;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reapply filters whenever weekday data changes
|
// Recalculate weekday data when the economicCalendar or days change – but only when not sorting
|
||||||
if (filterList.length > 0 && syncWorker) {
|
$: if (!sortMode) {
|
||||||
loadWorker();
|
weekday = getWeekdayData(economicCalendar, daysOfWeek);
|
||||||
}
|
rawData = weekday;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Whenever filters are applied and the worker exists, trigger filtering
|
||||||
|
$: if (filterList.length > 0 && syncWorker) {
|
||||||
|
loadWorker();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a consolidated derived value for our header and table rendering
|
||||||
|
$: displayWeekData = filterList.length === 0 ? weekday : weekdayFiltered;
|
||||||
|
|
||||||
const startBoundary = subWeeks(
|
const startBoundary = subWeeks(
|
||||||
startOfWeek(today, { weekStartsOn: 1 }),
|
startOfWeek(today, { weekStartsOn: 1 }),
|
||||||
maxWeeksChange,
|
maxWeeksChange,
|
||||||
@ -54,13 +62,13 @@
|
|||||||
startOfWeek(today, { weekStartsOn: 1 }),
|
startOfWeek(today, { weekStartsOn: 1 }),
|
||||||
maxWeeksChange,
|
maxWeeksChange,
|
||||||
);
|
);
|
||||||
|
|
||||||
$: previousMax = currentWeek <= startBoundary;
|
$: previousMax = currentWeek <= startBoundary;
|
||||||
$: nextMax = currentWeek >= endBoundary;
|
$: nextMax = currentWeek >= endBoundary;
|
||||||
|
|
||||||
let currentDate = new Date();
|
let currentDate = new Date();
|
||||||
let selectedWeekday = Math.min((currentDate.getDay() + 6) % 7, 4);
|
let selectedWeekday = Math.min((currentDate.getDay() + 6) % 7, 4);
|
||||||
|
|
||||||
|
// Returns an array of weekdays (Monday - Friday) for a given week.
|
||||||
function getDaysOfWeek(week) {
|
function getDaysOfWeek(week) {
|
||||||
const startDate = startOfWeek(week, { weekStartsOn: 1 });
|
const startDate = startOfWeek(week, { weekStartsOn: 1 });
|
||||||
return Array.from({ length: 5 }, (_, i) => ({
|
return Array.from({ length: 5 }, (_, i) => ({
|
||||||
@ -69,23 +77,27 @@
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Retrieves and sorts calendar data for each day.
|
||||||
function getWeekdayData(calendar, days) {
|
function getWeekdayData(calendar, days) {
|
||||||
if (!calendar) return [];
|
if (!calendar) return [];
|
||||||
return days.map((day) => {
|
return days.map((day) => {
|
||||||
const dayData = calendar.filter(
|
const dayData = calendar.filter(
|
||||||
(item) => item.date === format(day.date, "yyyy-MM-dd"),
|
(item) => item.date === format(day.date, "yyyy-MM-dd"),
|
||||||
);
|
);
|
||||||
return dayData?.sort(
|
return dayData.sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
new Date(`1970-01-01T${a.time}`) - new Date(`1970-01-01T${b.time}`),
|
new Date(`1970-01-01T${a.time}`).getTime() -
|
||||||
|
new Date(`1970-01-01T${b.time}`).getTime(),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle messages from our filtering web worker.
|
||||||
const handleMessage = (event) => {
|
const handleMessage = (event) => {
|
||||||
weekdayFiltered = event.data?.finalData?.output ?? [];
|
weekdayFiltered = event.data?.finalData?.output ?? [];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Tell the web worker to filter our data
|
||||||
const loadWorker = async () => {
|
const loadWorker = async () => {
|
||||||
syncWorker?.postMessage({ rawData, filterList });
|
syncWorker?.postMessage({ rawData, filterList });
|
||||||
};
|
};
|
||||||
@ -115,7 +127,6 @@
|
|||||||
state === "previous"
|
state === "previous"
|
||||||
? subWeeks(currentWeek, 1)
|
? subWeeks(currentWeek, 1)
|
||||||
: addWeeks(currentWeek, 1);
|
: addWeeks(currentWeek, 1);
|
||||||
|
|
||||||
if (newWeek >= startBoundary && newWeek <= endBoundary) {
|
if (newWeek >= startBoundary && newWeek <= endBoundary) {
|
||||||
currentWeek = newWeek;
|
currentWeek = newWeek;
|
||||||
}
|
}
|
||||||
@ -123,21 +134,21 @@
|
|||||||
|
|
||||||
function saveRules() {
|
function saveRules() {
|
||||||
try {
|
try {
|
||||||
// Save the version along with the rules
|
localStorage?.setItem(pagePathName, JSON.stringify(filterList));
|
||||||
localStorage?.setItem(pagePathName, JSON?.stringify(filterList));
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("Failed saving filterlist: ", e);
|
console.error("Failed saving filterlist:", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notice we now initialize checkedItems just once instead of using a reactive assignment.
|
||||||
|
let checkedItems: Set<any> = new Set();
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
try {
|
try {
|
||||||
const savedRules = localStorage?.getItem(pagePathName);
|
const savedRules = localStorage?.getItem(pagePathName);
|
||||||
|
|
||||||
if (savedRules) {
|
if (savedRules) {
|
||||||
filterList = JSON.parse(savedRules);
|
filterList = JSON.parse(savedRules);
|
||||||
}
|
}
|
||||||
|
|
||||||
checkedItems = new Set(filterList);
|
checkedItems = new Set(filterList);
|
||||||
|
|
||||||
if (!syncWorker) {
|
if (!syncWorker) {
|
||||||
@ -146,29 +157,23 @@
|
|||||||
syncWorker.onmessage = handleMessage;
|
syncWorker.onmessage = handleMessage;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function handleInput(event) {
|
// Update the global searchQuery (avoid shadowing) and debounce the filtering.
|
||||||
const searchQuery = event.target.value?.toLowerCase() || "";
|
function handleInput(event: InputEvent) {
|
||||||
|
searchQuery = (event.target as HTMLInputElement)?.value.toLowerCase() || "";
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
testList = [];
|
testList = [];
|
||||||
|
|
||||||
if (searchQuery.length > 0) {
|
if (searchQuery.length > 0) {
|
||||||
const rawList = listOfRelevantCountries;
|
testList = listOfRelevantCountries.filter((item) =>
|
||||||
testList =
|
item.toLowerCase().startsWith(searchQuery),
|
||||||
rawList?.filter((item) => {
|
);
|
||||||
const index = item?.toLowerCase();
|
|
||||||
return index?.startsWith(searchQuery);
|
|
||||||
}) || [];
|
|
||||||
}
|
}
|
||||||
}, 50);
|
}, 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
$: checkedItems = new Set();
|
|
||||||
|
|
||||||
async function handleChangeValue(value) {
|
async function handleChangeValue(value) {
|
||||||
if (checkedItems.has(value)) {
|
if (checkedItems.has(value)) {
|
||||||
checkedItems.delete(value);
|
checkedItems.delete(value);
|
||||||
@ -190,23 +195,20 @@
|
|||||||
function handleReset() {
|
function handleReset() {
|
||||||
filterList = [];
|
filterList = [];
|
||||||
checkedItems = new Set();
|
checkedItems = new Set();
|
||||||
|
|
||||||
economicCalendar = data?.getEconomicCalendar;
|
economicCalendar = data?.getEconomicCalendar;
|
||||||
daysOfWeek = getDaysOfWeek(currentWeek);
|
daysOfWeek = getDaysOfWeek(currentWeek);
|
||||||
formattedWeekday = daysOfWeek.map((day) => format(day.date, "EEE, MMM d"));
|
formattedWeekday = daysOfWeek.map((day) => format(day.date, "EEE, MMM d"));
|
||||||
weekday = getWeekdayData(economicCalendar, daysOfWeek);
|
weekday = getWeekdayData(economicCalendar, daysOfWeek);
|
||||||
rawData = weekday;
|
rawData = weekday;
|
||||||
|
|
||||||
currentWeek = startOfWeek(today, { weekStartsOn: 1 });
|
currentWeek = startOfWeek(today, { weekStartsOn: 1 });
|
||||||
selectedWeekday = Math.min((currentDate.getDay() + 6) % 7, 4);
|
selectedWeekday = Math.min((currentDate.getDay() + 6) % 7, 4);
|
||||||
|
|
||||||
previousMax = currentWeek <= startBoundary;
|
previousMax = currentWeek <= startBoundary;
|
||||||
nextMax = currentWeek >= endBoundary;
|
nextMax = currentWeek >= endBoundary;
|
||||||
|
|
||||||
saveRules();
|
saveRules();
|
||||||
}
|
}
|
||||||
|
|
||||||
let columns = [
|
// Static columns (do not change across renders)
|
||||||
|
const columns = [
|
||||||
{ key: "time", label: "Time", align: "left" },
|
{ key: "time", label: "Time", align: "left" },
|
||||||
{ key: "country", label: "Country", align: "left" },
|
{ key: "country", label: "Country", align: "left" },
|
||||||
{ key: "event", label: "Event", align: "left" },
|
{ key: "event", label: "Event", align: "left" },
|
||||||
@ -228,86 +230,70 @@
|
|||||||
|
|
||||||
const sortData = (key) => {
|
const sortData = (key) => {
|
||||||
sortMode = true;
|
sortMode = true;
|
||||||
for (const k in sortOrders) {
|
Object.keys(sortOrders).forEach((k) => {
|
||||||
if (k !== key) {
|
if (k !== key) sortOrders[k].order = "none";
|
||||||
sortOrders[k].order = "none";
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cycle through 'none', 'asc', 'desc' for the clicked key
|
// Cycle through "none", "asc", "desc"
|
||||||
const orderCycle = ["none", "asc", "desc"];
|
const orderCycle = ["none", "asc", "desc"];
|
||||||
const currentOrderIndex = orderCycle.indexOf(
|
const currentOrderIndex = orderCycle.indexOf(
|
||||||
sortOrders[key]?.order || "none",
|
sortOrders[key]?.order || "none",
|
||||||
);
|
);
|
||||||
sortOrders[key] = {
|
sortOrders[key] = {
|
||||||
...(sortOrders[key] || {}),
|
...sortOrders[key],
|
||||||
order: orderCycle[(currentOrderIndex + 1) % orderCycle.length],
|
order: orderCycle[(currentOrderIndex + 1) % orderCycle.length],
|
||||||
};
|
};
|
||||||
const sortOrder = sortOrders[key]?.order;
|
|
||||||
|
|
||||||
// Reset to original data when 'none' and stop further sorting
|
const sortOrder = sortOrders[key].order;
|
||||||
if (sortOrder === "none") {
|
if (sortOrder === "none") {
|
||||||
sortMode = false;
|
sortMode = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic comparison function
|
|
||||||
const compareValues = (a, b) => {
|
const compareValues = (a, b) => {
|
||||||
const { type } = sortOrders[key];
|
const { type } = sortOrders[key];
|
||||||
let valueA, valueB;
|
let valueA, valueB;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "date":
|
case "date":
|
||||||
valueA = new Date(a[key]);
|
valueA = new Date(a[key]).getTime();
|
||||||
valueB = new Date(b[key]);
|
valueB = new Date(b[key]).getTime();
|
||||||
break;
|
break;
|
||||||
case "rating":
|
|
||||||
case "string":
|
case "string":
|
||||||
// Retrieve values
|
valueA = a[key] ? a[key].toUpperCase() : "";
|
||||||
valueA = a[key];
|
valueB = b[key] ? b[key].toUpperCase() : "";
|
||||||
valueB = b[key];
|
|
||||||
|
|
||||||
// Handle null or undefined values, always placing them at the bottom
|
|
||||||
if (valueA == null && valueB == null) {
|
|
||||||
return 0; // Both are null/undefined, no need to change the order
|
|
||||||
} else if (valueA == null) {
|
|
||||||
return 1; // null goes to the bottom
|
|
||||||
} else if (valueB == null) {
|
|
||||||
return -1; // null goes to the bottom
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert the values to uppercase for case-insensitive comparison
|
|
||||||
valueA = valueA?.toUpperCase();
|
|
||||||
valueB = valueB?.toUpperCase();
|
|
||||||
|
|
||||||
// Perform the sorting based on ascending or descending order
|
|
||||||
return sortOrder === "asc"
|
return sortOrder === "asc"
|
||||||
? valueA?.localeCompare(valueB)
|
? valueA.localeCompare(valueB)
|
||||||
: valueB?.localeCompare(valueA);
|
: valueB.localeCompare(valueA);
|
||||||
case "number":
|
case "number":
|
||||||
default:
|
default:
|
||||||
valueA = parseFloat(a[key]);
|
valueA = parseFloat(a[key]);
|
||||||
valueB = parseFloat(b[key]);
|
valueB = parseFloat(b[key]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return sortOrder === "asc"
|
||||||
if (sortOrder === "asc") {
|
? valueA < valueB
|
||||||
return valueA < valueB ? -1 : valueA > valueB ? 1 : 0;
|
? -1
|
||||||
} else {
|
: valueA > valueB
|
||||||
return valueA > valueB ? -1 : valueA < valueB ? 1 : 0;
|
? 1
|
||||||
}
|
: 0
|
||||||
|
: valueA > valueB
|
||||||
|
? -1
|
||||||
|
: valueA < valueB
|
||||||
|
? 1
|
||||||
|
: 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Sort and update the originalData and stockList
|
// Create a new array copy to trigger reactivity (instead of in-place mutation)
|
||||||
weekday[selectedWeekday] = [...rawData[selectedWeekday]].sort(
|
weekday = [
|
||||||
compareValues,
|
...weekday.slice(0, selectedWeekday),
|
||||||
);
|
[...rawData[selectedWeekday]].sort(compareValues),
|
||||||
|
...weekday.slice(selectedWeekday + 1),
|
||||||
|
];
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<SEO
|
<SEO
|
||||||
title="Worldwide
|
title="Worldwide Economic Calendar"
|
||||||
Economic Calendar"
|
|
||||||
description="A list of upcoming economic events on the US stock market, with dates, times and estimation."
|
description="A list of upcoming economic events on the US stock market, with dates, times and estimation."
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@ -337,11 +323,10 @@
|
|||||||
<div class="flex justify-center w-full m-auto h-full overflow-hidden">
|
<div class="flex justify-center w-full m-auto h-full overflow-hidden">
|
||||||
<!-- Content area -->
|
<!-- Content area -->
|
||||||
<div class="relative flex flex-col flex-1 overflow-hidden">
|
<div class="relative flex flex-col flex-1 overflow-hidden">
|
||||||
<!-- Cards -->
|
<!-- Header Dates -->
|
||||||
<div
|
<div
|
||||||
class=" w-full flex flex-row justify-center m-auto items-center"
|
class="w-full flex flex-row justify-center m-auto items-center"
|
||||||
>
|
>
|
||||||
<!-- Start Columns -->
|
|
||||||
<label
|
<label
|
||||||
on:click={() => changeWeek("previous")}
|
on:click={() => changeWeek("previous")}
|
||||||
class="{previousMax
|
class="{previousMax
|
||||||
@ -352,13 +337,14 @@
|
|||||||
class="w-6 h-6 m-auto rotate-180"
|
class="w-6 h-6 m-auto rotate-180"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
><path
|
>
|
||||||
|
<path
|
||||||
fill="white"
|
fill="white"
|
||||||
d="M8.025 22L6.25 20.225L14.475 12L6.25 3.775L8.025 2l10 10l-10 10Z"
|
d="M8.025 22L6.25 20.225L14.475 12L6.25 3.775L8.025 2l10 10l-10 10Z"
|
||||||
/></svg
|
/>
|
||||||
>
|
</svg>
|
||||||
</label>
|
</label>
|
||||||
{#each filterList?.length === 0 ? weekday : weekdayFiltered as day, index}
|
{#each displayWeekData as day, index (formattedWeekday[index])}
|
||||||
<div
|
<div
|
||||||
class="w-full text-white {index === selectedWeekday
|
class="w-full text-white {index === selectedWeekday
|
||||||
? ''
|
? ''
|
||||||
@ -366,13 +352,13 @@
|
|||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
on:click={() => toggleDate(index)}
|
on:click={() => toggleDate(index)}
|
||||||
class=" m-auto w-full cursor-pointer h-16 {index ===
|
class="m-auto w-full cursor-pointer h-16 {index ===
|
||||||
selectedWeekday
|
selectedWeekday
|
||||||
? 'bg-white text-black font-semibold'
|
? 'bg-white text-black font-semibold'
|
||||||
: ''} rounded sm:rounded-none flex bg-default border border-gray-600 mb-3"
|
: ''} rounded sm:rounded-none flex bg-default border border-gray-600 mb-3"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class=" flex flex-row justify-center items-center w-full"
|
class="flex flex-row justify-center items-center w-full"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
on:click={() => clickWeekday("previous", index)}
|
on:click={() => clickWeekday("previous", index)}
|
||||||
@ -382,18 +368,19 @@
|
|||||||
class="w-8 h-8 inline-block rotate-180"
|
class="w-8 h-8 inline-block rotate-180"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
><path
|
>
|
||||||
|
<path
|
||||||
fill="black"
|
fill="black"
|
||||||
d="M8.025 22L6.25 20.225L14.475 12L6.25 3.775L8.025 2l10 10l-10 10Z"
|
d="M8.025 22L6.25 20.225L14.475 12L6.25 3.775L8.025 2l10 10l-10 10Z"
|
||||||
/></svg
|
/>
|
||||||
>
|
</svg>
|
||||||
</label>
|
</label>
|
||||||
<div
|
<div
|
||||||
class="flex flex-col items-center truncate m-auto p-1"
|
class="flex flex-col items-center truncate m-auto p-1"
|
||||||
>
|
>
|
||||||
<span class="text-md">{formattedWeekday[index]}</span>
|
<span class="text-md">{formattedWeekday[index]}</span>
|
||||||
<span class="text-[1rem] sm:text-sm m-auto pt-1 pb-1">
|
<span class="text-[1rem] sm:text-sm m-auto pt-1 pb-1"
|
||||||
{day?.length} Events</span
|
>{day?.length} Events</span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<label
|
<label
|
||||||
@ -404,11 +391,12 @@
|
|||||||
class="w-8 h-8 inline-block"
|
class="w-8 h-8 inline-block"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
><path
|
>
|
||||||
|
<path
|
||||||
fill="black"
|
fill="black"
|
||||||
d="M8.025 22L6.25 20.225L14.475 12L6.25 3.775L8.025 2l10 10l-10 10Z"
|
d="M8.025 22L6.25 20.225L14.475 12L6.25 3.775L8.025 2l10 10l-10 10Z"
|
||||||
/></svg
|
/>
|
||||||
>
|
</svg>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
@ -424,14 +412,16 @@
|
|||||||
class="w-6 h-6 m-auto"
|
class="w-6 h-6 m-auto"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
><path
|
>
|
||||||
|
<path
|
||||||
fill="white"
|
fill="white"
|
||||||
d="M8.025 22L6.25 20.225L14.475 12L6.25 3.775L8.025 2l10 10l-10 10Z"
|
d="M8.025 22L6.25 20.225L14.475 12L6.25 3.775L8.025 2l10 10l-10 10Z"
|
||||||
/></svg
|
/>
|
||||||
>
|
</svg>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Dropdown Filters -->
|
||||||
<div
|
<div
|
||||||
class="flex flex-row items-center w-full sm:w-fit m-auto sm:m-0 pt-6 pb-3"
|
class="flex flex-row items-center w-full sm:w-fit m-auto sm:m-0 pt-6 pb-3"
|
||||||
>
|
>
|
||||||
@ -467,32 +457,28 @@
|
|||||||
class="relative sticky z-40 focus:outline-none -top-1"
|
class="relative sticky z-40 focus:outline-none -top-1"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
role="menu"
|
role="menu"
|
||||||
style=""
|
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
bind:value={searchQuery}
|
bind:value={searchQuery}
|
||||||
on:input={handleInput}
|
on:input={handleInput}
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
class=" absolute fixed sticky w-full border-0 bg-default border-b border-gray-200
|
class="absolute sticky w-full border-0 bg-default border-b border-gray-200 focus:border-gray-200 focus:ring-0 text-white placeholder:text-gray-300"
|
||||||
focus:border-gray-200 focus:ring-0 text-white placeholder:text-gray-300"
|
|
||||||
type="search"
|
type="search"
|
||||||
placeholder="Search..."
|
placeholder="Search..."
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<DropdownMenu.Group>
|
<DropdownMenu.Group>
|
||||||
{#each testList.length > 0 && searchQuery?.length > 0 ? testList : searchQuery?.length > 0 && testList?.length === 0 ? [] : listOfRelevantCountries as item}
|
{#each searchQuery.length > 0 ? testList : listOfRelevantCountries as item}
|
||||||
<DropdownMenu.Item class="sm:hover:bg-primary">
|
<DropdownMenu.Item class="sm:hover:bg-primary">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<label
|
<label
|
||||||
on:click={() => {
|
on:click={() => handleChangeValue(item)}
|
||||||
handleChangeValue(item);
|
|
||||||
}}
|
|
||||||
class="cursor-pointer text-white"
|
class="cursor-pointer text-white"
|
||||||
for={item}
|
for={item}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={checkedItems?.has(item)}
|
checked={checkedItems.has(item)}
|
||||||
/>
|
/>
|
||||||
<span class="ml-2">{item}</span>
|
<span class="ml-2">{item}</span>
|
||||||
</label>
|
</label>
|
||||||
@ -507,7 +493,7 @@
|
|||||||
<DropdownMenu.Trigger asChild let:builder>
|
<DropdownMenu.Trigger asChild let:builder>
|
||||||
<Button
|
<Button
|
||||||
builders={[builder]}
|
builders={[builder]}
|
||||||
class="border-gray-600 border bg-default sm:hover:bg-primary ease-out flex flex-row justify-between items-center px-3 py-2 text-white rounded-md truncate"
|
class="border-gray-600 border bg-default sm:hover:bg-primary ease-out flex flex-row justify-between items-center px-3 py-2 text-white rounded-md truncate"
|
||||||
>
|
>
|
||||||
<span class="truncate text-white"
|
<span class="truncate text-white"
|
||||||
>Filter Importance</span
|
>Filter Importance</span
|
||||||
@ -534,26 +520,23 @@
|
|||||||
class="relative sticky z-40 focus:outline-none -top-1"
|
class="relative sticky z-40 focus:outline-none -top-1"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
role="menu"
|
role="menu"
|
||||||
style=""
|
|
||||||
></div>
|
></div>
|
||||||
<DropdownMenu.Group>
|
<DropdownMenu.Group>
|
||||||
{#each [1, 2, 3] as i}
|
{#each [1, 2, 3] as i}
|
||||||
<DropdownMenu.Item class="sm:hover:bg-primary">
|
<DropdownMenu.Item class="sm:hover:bg-primary">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<label
|
<label
|
||||||
on:click={() => {
|
on:click={() => handleChangeValue(i)}
|
||||||
handleChangeValue(i);
|
|
||||||
}}
|
|
||||||
class="flex flex-row items-center cursor-pointer text-white"
|
class="flex flex-row items-center cursor-pointer text-white"
|
||||||
for={i}
|
for={i}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={checkedItems?.has(i)}
|
checked={checkedItems.has(i)}
|
||||||
/>
|
/>
|
||||||
<div class="ml-2 flex flex-row items-center">
|
<div class="ml-2 flex flex-row items-center">
|
||||||
{#if i > 0}
|
{#if i > 0}
|
||||||
{#each Array(i).fill() as _, index}
|
{#each Array(i) as _}
|
||||||
<svg
|
<svg
|
||||||
class="w-4 h-4 text-[#FBCE3C]"
|
class="w-4 h-4 text-[#FBCE3C]"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
@ -566,19 +549,6 @@
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
{/each}
|
{/each}
|
||||||
{#each Array(3 - i).fill() as _}
|
|
||||||
<svg
|
|
||||||
class="w-4 h-4 text-gray-300 dark:text-gray-500"
|
|
||||||
aria-hidden="true"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
fill="currentColor"
|
|
||||||
viewBox="0 0 22 20"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M20.924 7.625a1.523 1.523 0 0 0-1.238-1.044l-5.051-.734-2.259-4.577a1.534 1.534 0 0 0-2.752 0L7.365 5.847l-5.051.734A1.535 1.535 0 0 0 1.463 9.2l3.656 3.563-.863 5.031a1.532 1.532 0 0 0 2.226 1.616L11 17.033l4.518 2.375a1.534 1.534 0 0 0 2.226-1.617l-.863-5.03L20.537 9.2a1.523 1.523 0 0 0 .387-1.575Z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
{/each}
|
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
@ -589,34 +559,35 @@
|
|||||||
</DropdownMenu.Content>
|
</DropdownMenu.Content>
|
||||||
</DropdownMenu.Root>
|
</DropdownMenu.Root>
|
||||||
|
|
||||||
{#if filterList?.length !== 0}
|
{#if filterList.length !== 0}
|
||||||
<Button
|
<Button
|
||||||
on:click={() => handleReset()}
|
on:click={handleReset}
|
||||||
class="w-fit border-gray-600 border bg-default sm:hover:bg-primary ease-out flex flex-row justify-start items-center px-3 py-2 text-white rounded-md truncate"
|
class="w-fit border-gray-600 border bg-default sm:hover:bg-primary ease-out flex flex-row justify-start items-center px-3 py-2 text-white rounded-md truncate"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
class="inline-block w-4 h-4 mr-2"
|
class="inline-block w-4 h-4 mr-2"
|
||||||
viewBox="0 0 21 21"
|
viewBox="0 0 21 21"
|
||||||
><g
|
>
|
||||||
|
<g
|
||||||
fill="none"
|
fill="none"
|
||||||
fill-rule="evenodd"
|
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
><path d="M3.578 6.487A8 8 0 1 1 2.5 10.5" /><path
|
>
|
||||||
d="M7.5 6.5h-4v-4"
|
<path d="M3.578 6.487A8 8 0 1 1 2.5 10.5" />
|
||||||
/></g
|
<path d="M7.5 6.5h-4v-4" />
|
||||||
></svg
|
</g>
|
||||||
>
|
</svg>
|
||||||
Reset All
|
Reset All
|
||||||
</Button>
|
</Button>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Events Table -->
|
||||||
<div class="z-0 mb-40">
|
<div class="z-0 mb-40">
|
||||||
{#each filterList?.length === 0 ? weekday : weekdayFiltered as day, index}
|
{#each displayWeekData as day, index}
|
||||||
{#if index === selectedWeekday}
|
{#if index === selectedWeekday}
|
||||||
{#if day?.length !== 0}
|
{#if day?.length !== 0}
|
||||||
<div class="flex flex-row items-center mt-5">
|
<div class="flex flex-row items-center mt-5">
|
||||||
@ -624,19 +595,15 @@
|
|||||||
{formattedWeekday[index]?.split(", ")[1]} · {day?.length}
|
{formattedWeekday[index]?.split(", ")[1]} · {day?.length}
|
||||||
Events
|
Events
|
||||||
</h2>
|
</h2>
|
||||||
{#if filterList?.length !== 0}
|
{#if filterList.length !== 0}
|
||||||
<div
|
<div
|
||||||
class="ml-auto text-[1rem] sm:text-lg flex flex-row items-center relative block rounded-md px-2 py-1 focus:outline-none"
|
class="ml-auto text-[1rem] sm:text-lg flex flex-row items-center relative block rounded-md px-2 py-1 focus:outline-none"
|
||||||
>
|
>
|
||||||
<span class="text-white">Filters</span>
|
<span class="text-white">Filters</span>
|
||||||
<span
|
<span
|
||||||
class="ml-2 rounded-full avatar w-5 h-5 text-xs font-semibold text-white text-center flex-shrink-0
|
class="ml-2 rounded-full avatar w-5 h-5 text-xs font-semibold text-white text-center flex-shrink-0 flex items-center justify-center bg-red-500"
|
||||||
flex items-center justify-center bg-red-500 {filterList?.length !==
|
|
||||||
0
|
|
||||||
? 'bg-red-500'
|
|
||||||
: 'bg-gray-600'}"
|
|
||||||
>
|
>
|
||||||
{filterList?.length}
|
{filterList.length}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
@ -651,16 +618,14 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{#each day as item}
|
{#each day as item}
|
||||||
<!-- row -->
|
|
||||||
<tr
|
<tr
|
||||||
class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-odd border border-gray-800"
|
class="sm:hover:bg-[#245073] sm:hover:bg-opacity-[0.2] odd:bg-odd border border-gray-800"
|
||||||
>
|
>
|
||||||
<td class="text-white text-sm sm:text-[1rem]">
|
<td class="text-white text-sm sm:text-[1rem]">
|
||||||
<label class="p-1.5 rounded-md">
|
<label class="p-1.5 rounded-md"
|
||||||
{item?.time}
|
>{item?.time}</label
|
||||||
</label>
|
>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td
|
<td
|
||||||
class="flex flex-row items-center text-sm sm:text-[1rem] whitespace-nowrap"
|
class="flex flex-row items-center text-sm sm:text-[1rem] whitespace-nowrap"
|
||||||
>
|
>
|
||||||
@ -670,93 +635,98 @@
|
|||||||
class="w-4 h-4 sm:w-6 sm:h-6"
|
class="w-4 h-4 sm:w-6 sm:h-6"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 512 512"
|
viewBox="0 0 512 512"
|
||||||
><mask id="circleFlagsEu0"
|
>
|
||||||
><circle
|
<mask id="circleFlagsEu0">
|
||||||
|
<circle
|
||||||
cx="256"
|
cx="256"
|
||||||
cy="256"
|
cy="256"
|
||||||
r="256"
|
r="256"
|
||||||
fill="#fff"
|
fill="#fff"
|
||||||
/></mask
|
/>
|
||||||
><g mask="url(#circleFlagsEu0)"
|
</mask>
|
||||||
><path
|
<g mask="url(#circleFlagsEu0)">
|
||||||
|
<path
|
||||||
fill="#0052b4"
|
fill="#0052b4"
|
||||||
d="M0 0h512v512H0z"
|
d="M0 0h512v512H0z"
|
||||||
/><path
|
/>
|
||||||
|
<path
|
||||||
fill="#ffda44"
|
fill="#ffda44"
|
||||||
d="m256 100.2l8.3 25.5H291l-21.7 15.7l8.3 25.6l-21.7-15.8l-21.7 15.8l8.3-25.6l-21.7-15.7h26.8zm-110.2 45.6l24 12.2l18.9-19l-4.2 26.5l23.9 12.2l-26.5 4.2l-4.2 26.5l-12.2-24l-26.5 4.3l19-19zM100.2 256l25.5-8.3V221l15.7 21.7l25.6-8.3l-15.8 21.7l15.8 21.7l-25.6-8.3l-15.7 21.7v-26.8zm45.6 110.2l12.2-24l-19-18.9l26.5 4.2l12.2-23.9l4.2 26.5l26.5 4.2l-24 12.2l4.3 26.5l-19-19zM256 411.8l-8.3-25.5H221l21.7-15.7l-8.3-25.6l21.7 15.8l21.7-15.8l-8.3 25.6l21.7 15.7h-26.8zm110.2-45.6l-24-12.2l-18.9 19l4.2-26.5l-23.9-12.2l26.5-4.2l4.2-26.5l12.2 24l26.5-4.3l-19 19zM411.8 256l-25.5 8.3V291l-15.7-21.7l-25.6 8.3l15.8-21.7l-15.8-21.7l25.6 8.3l15.7-21.7v26.8zm-45.6-110.2l-12.2 24l19 18.9l-26.5-4.2l-12.2 23.9l-4.2-26.5l-26.5-4.2l24-12.2l-4.3-26.5l19 19z"
|
d="m256 100.2l8.3 25.5H291l-21.7 15.7l8.3 25.6l-21.7-15.8l-21.7 15.8l8.3-25.6l-21.7-15.7h26.8zm-110.2 45.6l24 12.2l18.9-19l-4.2 26.5l23.9 12.2l-26.5 4.2l-4.2 26.5l-12.2-24l-26.5 4.3l19-19zM100.2 256l25.5-8.3V221l15.7 21.7l25.6-8.3l-15.8 21.7l15.8 21.7l-25.6-8.3l-15.7 21.7v-26.8zm45.6 110.2l12.2-24l-19-18.9l26.5 4.2l12.2-23.9l4.2 26.5l26.5 4.2l-24 12.2l4.3 26.5l-19-19zM256 411.8l-8.3-25.5H221l21.7-15.7l-8.3-25.6l21.7 15.8l21.7-15.8l-8.3 25.6l21.7 15.7h-26.8zm110.2-45.6l-24-12.2l-18.9 19l4.2-26.5l-23.9-12.2l26.5-4.2l4.2-26.5l12.2 24l26.5-4.3l-19 19zM411.8 256l-25.5 8.3V291l-15.7-21.7l-25.6 8.3l15.8-21.7l-15.8-21.7l25.6 8.3l15.7-21.7v26.8zm-45.6-110.2l-12.2 24l19 18.9l-26.5-4.2l-12.2 23.9l-4.2-26.5l-26.5-4.2l24-12.2l-4.3-26.5l19 19z"
|
||||||
/></g
|
/>
|
||||||
></svg
|
</g>
|
||||||
>
|
</svg>
|
||||||
{:else if item?.country === "UK"}
|
{:else if item?.country === "UK"}
|
||||||
<svg
|
<svg
|
||||||
style="clip-path: circle(50%);"
|
style="clip-path: circle(50%);"
|
||||||
class="w-4 h-4 sm:w-6 sm:h-6"
|
class="w-4 h-4 sm:w-6 sm:h-6"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 512 512"
|
viewBox="0 0 512 512"
|
||||||
><mask id="circleFlagsUk0"
|
>
|
||||||
><circle
|
<mask id="circleFlagsUk0">
|
||||||
|
<circle
|
||||||
cx="256"
|
cx="256"
|
||||||
cy="256"
|
cy="256"
|
||||||
r="256"
|
r="256"
|
||||||
fill="#fff"
|
fill="#fff"
|
||||||
/></mask
|
/>
|
||||||
><g mask="url(#circleFlagsUk0)"
|
</mask>
|
||||||
><path
|
<g mask="url(#circleFlagsUk0)">
|
||||||
|
<path
|
||||||
fill="#eee"
|
fill="#eee"
|
||||||
d="m0 0l8 22l-8 23v23l32 54l-32 54v32l32 48l-32 48v32l32 54l-32 54v68l22-8l23 8h23l54-32l54 32h32l48-32l48 32h32l54-32l54 32h68l-8-22l8-23v-23l-32-54l32-54v-32l-32-48l32-48v-32l-32-54l32-54V0l-22 8l-23-8h-23l-54 32l-54-32h-32l-48 32l-48-32h-32l-54 32L68 0z"
|
d="m0 0l8 22l-8 23v23l32 54l-32 54v32l32 48l-32 48v32l32 54l-32 54v68l22-8l23 8h23l54-32l54 32h32l48-32l48 32h32l54-32l54 32h68l-8-22l8-23v-23l-32-54l32-54v-32l-32-48l32-48v-32l-32-54l32-54V0l-22 8l-23-8h-23l-54 32l-54-32h-32l-48 32l-48-32h-32l-54 32L68 0z"
|
||||||
/><path
|
/>
|
||||||
|
<path
|
||||||
fill="#0052b4"
|
fill="#0052b4"
|
||||||
d="M336 0v108L444 0Zm176 68L404 176h108zM0 176h108L0 68ZM68 0l108 108V0Zm108 512V404L68 512ZM0 444l108-108H0Zm512-108H404l108 108Zm-68 176L336 404v108z"
|
d="M336 0v108L444 0Zm176 68L404 176h108zM0 176h108L0 68ZM68 0l108 108V0Zm108 512V404L68 512ZM0 444l108-108H0Zm512-108H404l108 108Zm-68 176L336 404v108z"
|
||||||
/><path
|
/>
|
||||||
|
<path
|
||||||
fill="#d80027"
|
fill="#d80027"
|
||||||
d="M0 0v45l131 131h45zm208 0v208H0v96h208v208h96V304h208v-96H304V0zm259 0L336 131v45L512 0zM176 336L0 512h45l131-131zm160 0l176 176v-45L381 336z"
|
d="M0 0v45l131 131h45zm208 0v208H0v96h208v208h96V304h208v-96H304V0zm259 0L336 131v45L512 0zM176 336L0 512h45l131-131zm160 0l176 176v-45L381 336z"
|
||||||
/></g
|
/>
|
||||||
></svg
|
</g>
|
||||||
>
|
</svg>
|
||||||
{:else}
|
{:else}
|
||||||
<img
|
<img
|
||||||
style="clip-path: circle(50%);"
|
style="clip-path: circle(50%);"
|
||||||
class="w-4 h-4 sm:w-6 sm:h-6"
|
class="w-4 h-4 sm:w-6 sm:h-6"
|
||||||
src={`https://hatscripts.github.io/circle-flags/flags/${item?.countryCode}.svg`}
|
src={`https://hatscripts.github.io/circle-flags/flags/${item?.countryCode}.svg`}
|
||||||
|
loading="lazy"
|
||||||
|
alt="{item?.country} flag"
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
<span class="text-white ml-2">
|
<span class="text-white ml-2"
|
||||||
{item?.country}
|
>{item?.country}</span
|
||||||
</span>
|
>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td
|
<td
|
||||||
class="text-start text-white text-sm sm:text-[1rem] whitespace-nowrap"
|
class="text-start text-white text-sm sm:text-[1rem] whitespace-nowrap"
|
||||||
>
|
>
|
||||||
{item?.event?.length > 40
|
{item?.event?.length > 40
|
||||||
? item?.event?.slice(0, 40) + "..."
|
? item?.event.slice(0, 40) + "..."
|
||||||
: item?.event}
|
: item?.event}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td
|
<td
|
||||||
class="text-white text-end text-sm sm:text-[1rem] whitespace-nowrap"
|
class="text-white text-end text-sm sm:text-[1rem] whitespace-nowrap"
|
||||||
>
|
>
|
||||||
{item?.actual !== (null || "")
|
{item?.actual !== null && item?.actual !== ""
|
||||||
? abbreviateNumber(item?.actual)
|
? abbreviateNumber(item?.actual)
|
||||||
: "-"}
|
: "-"}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td
|
<td
|
||||||
class="text-white text-end text-sm sm:text-[1rem] whitespace-nowrap"
|
class="text-white text-end text-sm sm:text-[1rem] whitespace-nowrap"
|
||||||
>
|
>
|
||||||
{item?.consensus !== (null || "")
|
{item?.consensus !== null &&
|
||||||
|
item?.consensus !== ""
|
||||||
? abbreviateNumber(item?.consensus)
|
? abbreviateNumber(item?.consensus)
|
||||||
: "-"}
|
: "-"}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td
|
<td
|
||||||
class="text-white text-end text-sm sm:text-[1rem] whitespace-nowrap"
|
class="text-white text-end text-sm sm:text-[1rem] whitespace-nowrap"
|
||||||
>
|
>
|
||||||
{item?.prior !== (null || "")
|
{item?.prior !== null && item?.prior !== ""
|
||||||
? abbreviateNumber(item?.prior)
|
? abbreviateNumber(item?.prior)
|
||||||
: "-"}
|
: "-"}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td
|
<td
|
||||||
class="text-white text-start text-sm sm:text-[1rem] whitespace-nowrap"
|
class="text-white text-start text-sm sm:text-[1rem] whitespace-nowrap"
|
||||||
>
|
>
|
||||||
@ -818,7 +788,7 @@
|
|||||||
class="w-full text-white border border-gray-600 rounded-md h-fit pb-4 mt-4 cursor-pointer bg-inherit sm:hover:bg-secondary transition ease-out duration-100"
|
class="w-full text-white border border-gray-600 rounded-md h-fit pb-4 mt-4 cursor-pointer bg-inherit sm:hover:bg-secondary transition ease-out duration-100"
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
href={"/earnings-calendar"}
|
href="/earnings-calendar"
|
||||||
class="w-auto lg:w-full p-1 flex flex-col m-auto px-2 sm:px-0"
|
class="w-auto lg:w-full p-1 flex flex-col m-auto px-2 sm:px-0"
|
||||||
>
|
>
|
||||||
<div class="w-full flex justify-between items-center p-3 mt-3">
|
<div class="w-full flex justify-between items-center p-3 mt-3">
|
||||||
@ -827,9 +797,9 @@
|
|||||||
</h2>
|
</h2>
|
||||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||||
</div>
|
</div>
|
||||||
<span class="text-white p-3 ml-3 mr-3">
|
<span class="text-white p-3 ml-3 mr-3"
|
||||||
Get the latest Earnings of companies
|
>Get the latest Earnings of companies</span
|
||||||
</span>
|
>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -837,7 +807,7 @@
|
|||||||
class="w-full text-white border border-gray-600 rounded-md h-fit pb-4 mt-4 cursor-pointer bg-inherit sm:hover:bg-secondary transition ease-out duration-100"
|
class="w-full text-white border border-gray-600 rounded-md h-fit pb-4 mt-4 cursor-pointer bg-inherit sm:hover:bg-secondary transition ease-out duration-100"
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
href={"/dividends-calendar"}
|
href="/dividends-calendar"
|
||||||
class="w-auto lg:w-full p-1 flex flex-col m-auto px-2 sm:px-0"
|
class="w-auto lg:w-full p-1 flex flex-col m-auto px-2 sm:px-0"
|
||||||
>
|
>
|
||||||
<div class="w-full flex justify-between items-center p-3 mt-3">
|
<div class="w-full flex justify-between items-center p-3 mt-3">
|
||||||
@ -846,9 +816,9 @@
|
|||||||
</h2>
|
</h2>
|
||||||
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
<ArrowLogo class="w-8 h-8 mr-3 flex-shrink-0" />
|
||||||
</div>
|
</div>
|
||||||
<span class="text-white p-3 ml-3 mr-3">
|
<span class="text-white p-3 ml-3 mr-3"
|
||||||
Get the latest dividend announcement
|
>Get the latest dividend announcement</span
|
||||||
</span>
|
>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { convertToSlug } from "$lib/utils";
|
|||||||
const pages = [
|
const pages = [
|
||||||
{ title: "/" },
|
{ title: "/" },
|
||||||
{ title: "/reddit-tracker" },
|
{ title: "/reddit-tracker" },
|
||||||
{ title: "/list/most-shorted-stocks"},
|
{ title: "/list/most-shorted-stocks" },
|
||||||
{ title: "/stocks" },
|
{ title: "/stocks" },
|
||||||
{ title: "/etf" },
|
{ title: "/etf" },
|
||||||
{ title: "/etf/etf-providers" },
|
{ title: "/etf/etf-providers" },
|
||||||
@ -29,10 +29,10 @@ const pages = [
|
|||||||
{ title: "/list/market-cap/small-cap-stocks" },
|
{ title: "/list/market-cap/small-cap-stocks" },
|
||||||
{ title: "/list/market-cap/micro-cap-stocks" },
|
{ title: "/list/market-cap/micro-cap-stocks" },
|
||||||
{ title: "/list/market-cap/nano-cap-stocks" },
|
{ title: "/list/market-cap/nano-cap-stocks" },
|
||||||
{ title: "/list/highest-open-interest" },
|
{ title: "/list/highest-open-interest" },
|
||||||
{ title: "/list/highest-open-interest-change" },
|
{ title: "/list/highest-open-interest-change" },
|
||||||
{ title: "/list/highest-option-iv-rank" },
|
{ title: "/list/highest-option-iv-rank" },
|
||||||
{ title: "/list/highest-option-premium" },
|
{ title: "/list/highest-option-premium" },
|
||||||
{ title: "/list/bitcoin-etfs" },
|
{ title: "/list/bitcoin-etfs" },
|
||||||
{ title: "/stock-screener" },
|
{ title: "/stock-screener" },
|
||||||
{ title: "/market-news" },
|
{ title: "/market-news" },
|
||||||
@ -66,7 +66,7 @@ const pages = [
|
|||||||
{ title: "/analysts" },
|
{ title: "/analysts" },
|
||||||
{ title: "/analysts/top-stocks" },
|
{ title: "/analysts/top-stocks" },
|
||||||
{ title: "/heatmap" },
|
{ title: "/heatmap" },
|
||||||
{ title: "/market-flow" },
|
{ title: "/market-flow" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const website = "https://stocknear.com";
|
const website = "https://stocknear.com";
|
||||||
@ -76,8 +76,6 @@ export async function GET({ locals }) {
|
|||||||
//get all posts;
|
//get all posts;
|
||||||
const { apiKey, apiURL, pb } = locals;
|
const { apiKey, apiURL, pb } = locals;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const rawData = await fetch(apiURL + "/full-searchbar", {
|
const rawData = await fetch(apiURL + "/full-searchbar", {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
@ -92,16 +90,15 @@ export async function GET({ locals }) {
|
|||||||
type: item?.type,
|
type: item?.type,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const articles = await pb.collection("articles").getFullList({
|
||||||
|
sort: "-created",
|
||||||
|
});
|
||||||
|
|
||||||
const articles = await pb.collection("articles").getFullList({
|
const tutorials = await pb.collection("tutorials").getFullList({
|
||||||
sort: "-created",
|
sort: "-created",
|
||||||
});
|
});
|
||||||
|
|
||||||
const tutorials = await pb.collection("tutorials").getFullList({
|
const body = sitemap(stocks, articles, pages);
|
||||||
sort: "-created",
|
|
||||||
});
|
|
||||||
|
|
||||||
const body = sitemap(stocks, articles, pages, tutorials);
|
|
||||||
const response = new Response(body);
|
const response = new Response(body);
|
||||||
response.headers.set("Cache-Control", "max-age=0, s-maxage=3600");
|
response.headers.set("Cache-Control", "max-age=0, s-maxage=3600");
|
||||||
response.headers.set("Content-Type", "application/xml");
|
response.headers.set("Content-Type", "application/xml");
|
||||||
@ -113,7 +110,6 @@ const sitemap = (
|
|||||||
stocks,
|
stocks,
|
||||||
articles,
|
articles,
|
||||||
pages,
|
pages,
|
||||||
tutorials,
|
|
||||||
) => `<?xml version="1.0" encoding="UTF-8" ?>
|
) => `<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<urlset
|
<urlset
|
||||||
xmlns="https://www.sitemaps.org/schemas/sitemap/0.9"
|
xmlns="https://www.sitemaps.org/schemas/sitemap/0.9"
|
||||||
@ -133,23 +129,23 @@ const sitemap = (
|
|||||||
)
|
)
|
||||||
.join("")}
|
.join("")}
|
||||||
${articles
|
${articles
|
||||||
.map(
|
.map(
|
||||||
(item) => `
|
(item) => `
|
||||||
<url>
|
<url>
|
||||||
<loc>${website}/blog/article/${convertToSlug(item?.title)}</loc>
|
<loc>${website}/blog/article/${convertToSlug(item?.title)}</loc>
|
||||||
</url>
|
</url>
|
||||||
`,
|
`,
|
||||||
)
|
)
|
||||||
.join("")}
|
.join("")}
|
||||||
${tutorials
|
${tutorials
|
||||||
.map(
|
.map(
|
||||||
(item) => `
|
(item) => `
|
||||||
<url>
|
<url>
|
||||||
<loc>${website}/learning-center/article/${convertToSlug(item?.title)}</loc>
|
<loc>${website}/learning-center/article/${convertToSlug(item?.title)}</loc>
|
||||||
</url>
|
</url>
|
||||||
`,
|
`,
|
||||||
)
|
)
|
||||||
.join("")}
|
.join("")}
|
||||||
${stocks
|
${stocks
|
||||||
.map((ticker) => {
|
.map((ticker) => {
|
||||||
// Determine the path based on the type of the ticker
|
// Determine the path based on the type of the ticker
|
||||||
@ -158,7 +154,7 @@ const sitemap = (
|
|||||||
? "/stocks/"
|
? "/stocks/"
|
||||||
: ticker.type === "ETF"
|
: ticker.type === "ETF"
|
||||||
? "/etf/"
|
? "/etf/"
|
||||||
: "/index/";
|
: "/crypto/";
|
||||||
return `
|
return `
|
||||||
<url>
|
<url>
|
||||||
<loc>${website}${path}${ticker.id}</loc>
|
<loc>${website}${path}${ticker.id}</loc>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user