update chart

This commit is contained in:
MuslemRahimi 2025-03-05 21:42:38 +01:00
parent 4d49db2bd4
commit 957dd1dfca

View File

@ -12,24 +12,11 @@
} from "$lib/utils"; } from "$lib/utils";
import highcharts from "$lib/highcharts.ts"; import highcharts from "$lib/highcharts.ts";
import { Chart } from "svelte-echarts";
import { init, use } from "echarts/core";
import { LineChart, BarChart, GaugeChart } from "echarts/charts";
import { GridComponent, TooltipComponent } from "echarts/components";
import { CanvasRenderer } from "echarts/renderers";
import { goto } from "$app/navigation"; import { goto } from "$app/navigation";
import SEO from "$lib/components/SEO.svelte"; import SEO from "$lib/components/SEO.svelte";
export let data; export let data;
use([
LineChart,
GaugeChart,
BarChart,
GridComponent,
TooltipComponent,
CanvasRenderer,
]);
let index = 0; let index = 0;
let changeRevenue = 0; let changeRevenue = 0;
@ -103,7 +90,7 @@
categories = ["Strong Buy", "Buy", "Hold", "Sell", "Strong Sell"]; categories = ["Strong Buy", "Buy", "Hold", "Sell", "Strong Sell"];
} }
optionsData = getPlotOptions() || null; optionsBarChart = getPlotOptions() || null;
optionsPieChart = getPieChart() || null; optionsPieChart = getPieChart() || null;
config = getPriceForecastChart() || null; config = getPriceForecastChart() || null;
} }
@ -151,88 +138,113 @@
} }
}; };
function getPlotOptions() { function getBarChart() {
if (!rawAnalystList || rawAnalystList.length === 0) { if (!rawAnalystList || rawAnalystList.length === 0) {
return null; return null;
} }
// Define categories in the exact order you specified const categories = ["Strong Buy", "Buy", "Hold", "Sell", "Strong Sell"];
const categories = ["Strong Sell", "Sell", "Hold", "Buy", "Strong Buy"]; const colors = ["#008A00", "#31B800", "#F5B700", "#D9220E", "#9E190A"];
const colors = ["#9E190A", "#D9220E", "#f5b700", "#31B800", "#008A00"];
// Create a consistent mapping for data // Step 1: Store original values
const formattedData = rawAnalystList?.map((item) => const formattedData = rawAnalystList.map((item) =>
categories.map((cat) => item[cat] || 0), categories.map((cat) => item[cat] || 0),
); );
// Normalize data to percentages // Step 2: Create normalized data for visualization
const normalizedData = formattedData.map((row) => { const normalizedData = formattedData.map((row) => {
const total = row.reduce((sum, val) => sum + val, 0); const total = row.reduce((sum, val) => sum + val, 0);
return row.map((val) => (total > 0 ? (val / total) * 100 : 0)); return row.map((val) => (total > 0 ? (val / total) * 100 : 0));
}); });
// Calculate total percentage for each category across all dates // Step 3: Include original values in data points
const totalData = [];
for (let i = 0; i < categories.length; ++i) {
let sum = 0;
for (let j = 0; j < normalizedData.length; ++j) {
sum += normalizedData[j][i];
}
totalData.push(sum / normalizedData.length);
}
// Define series based on categories with color mapping
const series = categories.map((name, idx) => ({ const series = categories.map((name, idx) => ({
name, name: name,
type: "bar", data: normalizedData?.map((row, dataIndex) => ({
stack: "total", y: formattedData[dataIndex][idx], // Normalized percentage for chart
barWidth: "60%", originalValue: formattedData[dataIndex][idx], // Original value for tooltip
data: normalizedData.map((row) => row[idx]), })),
itemStyle: { color: colors[idx],
color: colors[idx], borderColor: colors[idx],
}, borderRadius: "1px",
})); }));
// Define chart option const xCategories = rawAnalystList.map((item) => {
const option = { const dateParts = item?.date?.split("-");
grid: { const year = dateParts[0];
left: "2%", const monthIndex = parseInt(dateParts[1], 10) - 1;
right: "2%", return `${monthNames[monthIndex]} ${year}`;
bottom: "10%", });
top: "5%",
containLabel: true,
},
// Define and return the Highcharts options object
const options = {
chart: {
type: "column",
backgroundColor: "#09090B",
plotBackgroundColor: "#09090B",
animation: false,
height: 360, // Add fixed height
marginTop: 40, // Reduce top margin
marginBottom: 60, // Increase bottom margin for x-axis labels
},
legend: {
enabled: false,
},
title: {
text: null,
},
xAxis: { xAxis: {
type: "category", categories: xCategories,
data: rawAnalystList.map((item) => item.date), labels: {
axisLabel: { style: {
color: "#fff", color: "#fff",
formatter: function (value) {
const dateParts = value.split("-");
const year = dateParts[0].substring(0);
const monthIndex = parseInt(dateParts[1]) - 1;
return `${monthNames[monthIndex]} ${year}`;
}, },
}, },
}, },
yAxis: { tooltip: {
type: "value", shared: true,
max: 100, useHTML: true,
backgroundColor: "rgba(0, 0, 0, 0.8)",
axisLabel: { borderColor: "rgba(255, 255, 255, 0.2)",
show: false, // Hide y-axis labels borderWidth: 1,
style: {
color: "#fff",
fontSize: "16px",
padding: "10px",
}, },
splitLine: { borderRadius: 4,
show: false, headerFormat:
'<span class="font-semibold text-[1rem]">{point.key}</span><br/>',
pointFormat:
'<span style="color:{point.color}">\u25CF</span> ' +
"<span class='text-sm'>{series.name}: <b>{point.originalValue}</b><br/></span>",
},
yAxis: {
gridLineWidth: 1,
gridLineColor: "#111827",
labels: {
style: { color: "white" },
},
title: { text: null },
},
plotOptions: {
column: {
stacking: "normal", // stacks the columns so that each column adds up to 100%
pointWidth: 40, // adjust this value as needed to mimic your desired "barWidth"
pointPadding: 0.1, // More spacing between bars
groupPadding: 0.1, // More spacing between groups
},
series: {
animation: false,
}, },
}, },
series, credits: {
animation: false, enabled: false,
silent: true, },
series: series,
}; };
return option; return options;
} }
function getPieChart() { function getPieChart() {
@ -680,7 +692,7 @@
return options; return options;
} }
let optionsData = getPlotOptions() || null; let optionsBarChart = getBarChart() || null;
let optionsPieChart = getPieChart() || null; let optionsPieChart = getPieChart() || null;
let config = getPriceForecastChart() || null; let config = getPriceForecastChart() || null;
@ -921,11 +933,12 @@
</div> </div>
</div> </div>
<div class="grow pt-2 md:pt-4 lg:pl-4 lg:pt-0"> <div class="grow pt-2 md:pt-4 lg:pl-4 lg:pt-0">
<div class="app h-[250px] xs:h-[275px]"> {#if optionsBarChart !== null}
{#if optionsData !== null} <div
<Chart {init} options={optionsData} class="chart" /> class="border border-gray-800 rounded"
{/if} use:highcharts={optionsBarChart}
</div> ></div>
{/if}
<div <div
class="hide-scroll mb-1 mt-2 overflow-x-auto px-1.5 text-center md:mb-0 md:px-0 lg:mt-2" class="hide-scroll mb-1 mt-2 overflow-x-auto px-1.5 text-center md:mb-0 md:px-0 lg:mt-2"
> >