fixed charts
This commit is contained in:
parent
d3cd94feb0
commit
ded132c461
5 changed files with 241 additions and 156 deletions
|
@ -1,6 +1,4 @@
|
||||||
<template>
|
<template>
|
||||||
<v-row>
|
|
||||||
<v-col cols="12">
|
|
||||||
<v-card>
|
<v-card>
|
||||||
<v-card-item>
|
<v-card-item>
|
||||||
<v-card-title>Balance sheet</v-card-title>
|
<v-card-title>Balance sheet</v-card-title>
|
||||||
|
@ -10,31 +8,20 @@
|
||||||
<ag-charts-vue class="chart" v-else :options="options" />
|
<ag-charts-vue class="chart" v-else :options="options" />
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { BalanceSheet, EmployeeCount, getBalanceSheet } from '@/api';
|
import { BalanceSheet, getBalanceSheet } from '@/api';
|
||||||
import { defineLoader } from '@/api/loader';
|
import { defineLoader } from '@/api/loader';
|
||||||
import { AgAxisLabelFormatterParams, time } from 'ag-charts-community';
|
import { AgAxisLabelFormatterParams } from 'ag-charts-community';
|
||||||
import { DateTime } from 'luxon';
|
|
||||||
import { roundTo } from 'round-to';
|
|
||||||
import { onMounted, computed } from 'vue';
|
import { onMounted, computed } from 'vue';
|
||||||
import { AgChartsVue } from 'ag-charts-vue3';
|
import { AgChartsVue } from 'ag-charts-vue3';
|
||||||
|
|
||||||
const renderer = (params: any) => ({
|
|
||||||
title: params.title,
|
|
||||||
content: DateTime.fromMillis(params.xValue).year + ': ' + roundTo(params.yValue, 0),
|
|
||||||
});
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
tickers: string[],
|
tickers: string[],
|
||||||
colors: string[]
|
colors: string[]
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const getTickerColor = (ticker: string) => props.colors[props.tickers.indexOf(ticker)];
|
|
||||||
|
|
||||||
const balanceSheet = defineLoader<BalanceSheet[]>(() => getBalanceSheet(props.tickers));
|
const balanceSheet = defineLoader<BalanceSheet[]>(() => getBalanceSheet(props.tickers));
|
||||||
|
|
||||||
const options = computed(() => {
|
const options = computed(() => {
|
||||||
|
@ -105,6 +92,11 @@ const options = computed(() => {
|
||||||
{
|
{
|
||||||
type: 'category',
|
type: 'category',
|
||||||
position: 'bottom',
|
position: 'bottom',
|
||||||
|
gridStyle: [{
|
||||||
|
lineDash: [Infinity]
|
||||||
|
}, {
|
||||||
|
lineDash: [Infinity]
|
||||||
|
}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'number',
|
type: 'number',
|
||||||
|
@ -116,6 +108,11 @@ const options = computed(() => {
|
||||||
.replace('k', 'K')
|
.replace('k', 'K')
|
||||||
.replace('G', 'B') ?? ''
|
.replace('G', 'B') ?? ''
|
||||||
},
|
},
|
||||||
|
gridStyle: [{
|
||||||
|
lineDash: [Infinity]
|
||||||
|
}, {
|
||||||
|
lineDash: [Infinity]
|
||||||
|
}]
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
legend: {
|
legend: {
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
<template>
|
<template>
|
||||||
<v-row>
|
|
||||||
<v-col cols="12">
|
|
||||||
<v-card>
|
<v-card>
|
||||||
<v-card-item>
|
<v-card-item>
|
||||||
<v-card-title>Employees over time</v-card-title>
|
<v-card-title>Employees over time</v-card-title>
|
||||||
|
@ -10,8 +8,6 @@
|
||||||
<ag-charts-vue class="chart" v-else :options="options" />
|
<ag-charts-vue class="chart" v-else :options="options" />
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -28,7 +24,6 @@ const renderer = (params: any) => ({
|
||||||
content: DateTime.fromMillis(params.xValue).year + ': ' + roundTo(params.yValue, 0),
|
content: DateTime.fromMillis(params.xValue).year + ': ' + roundTo(params.yValue, 0),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
tickers: string[],
|
tickers: string[],
|
||||||
colors: string[]
|
colors: string[]
|
||||||
|
@ -71,11 +66,21 @@ const options = computed(() => {
|
||||||
autoRotate: true,
|
autoRotate: true,
|
||||||
autoRotateAngle: 335,
|
autoRotateAngle: 335,
|
||||||
format: '%Y'
|
format: '%Y'
|
||||||
}
|
},
|
||||||
|
gridStyle: [{
|
||||||
|
lineDash: [Infinity]
|
||||||
|
}, {
|
||||||
|
lineDash: [Infinity]
|
||||||
|
}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'number',
|
type: 'number',
|
||||||
position: 'left',
|
position: 'left',
|
||||||
|
gridStyle: [{
|
||||||
|
lineDash: [Infinity]
|
||||||
|
}, {
|
||||||
|
lineDash: [Infinity]
|
||||||
|
}]
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
legend: {
|
legend: {
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
<template>
|
<template>
|
||||||
<v-row>
|
|
||||||
<v-col cols="12">
|
|
||||||
<v-card>
|
<v-card>
|
||||||
<v-card-item>
|
<v-card-item>
|
||||||
<v-card-title>Earnings per Share (EPS)</v-card-title>
|
<v-card-title>Earnings per Share (EPS)</v-card-title>
|
||||||
|
@ -10,8 +8,6 @@
|
||||||
<ag-charts-vue class="chart" v-else :options="options" />
|
<ag-charts-vue class="chart" v-else :options="options" />
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -65,11 +61,21 @@ const options = computed(() => {
|
||||||
formatter: (params: any) => {
|
formatter: (params: any) => {
|
||||||
return DateTime.fromMillis(parseInt(params.value)).toFormat('yyyy-MM');
|
return DateTime.fromMillis(parseInt(params.value)).toFormat('yyyy-MM');
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
gridStyle: [{
|
||||||
|
lineDash: [Infinity]
|
||||||
|
}, {
|
||||||
|
lineDash: [Infinity]
|
||||||
|
}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'number',
|
type: 'number',
|
||||||
position: 'left',
|
position: 'left',
|
||||||
|
gridStyle: [{
|
||||||
|
lineDash: [Infinity]
|
||||||
|
}, {
|
||||||
|
lineDash: [Infinity]
|
||||||
|
}]
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
legend: {
|
legend: {
|
||||||
|
|
176
stockingly-frontend/src/components/StockPrice.vue
Normal file
176
stockingly-frontend/src/components/StockPrice.vue
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
<template>
|
||||||
|
<v-card>
|
||||||
|
<v-card-item>
|
||||||
|
<v-card-title>Stock price over time</v-card-title>
|
||||||
|
</v-card-item>
|
||||||
|
<v-card-text>
|
||||||
|
<div class="toolbar mb-3">
|
||||||
|
<v-btn-toggle class="toggles" v-model="timeToggle" color="secondary" mandatory>
|
||||||
|
<v-btn value="1M">1M</v-btn>
|
||||||
|
<v-btn value="3M">3M</v-btn>
|
||||||
|
<v-btn value="6M">6M</v-btn>
|
||||||
|
<v-btn value="1Y">1Y</v-btn>
|
||||||
|
<v-btn value="5Y">5Y</v-btn>
|
||||||
|
<v-btn value="MAX">Max</v-btn>
|
||||||
|
</v-btn-toggle>
|
||||||
|
<strong class="label">Current price:</strong>
|
||||||
|
<div class="chips">
|
||||||
|
<v-chip class="ma-1" v-for="ticker in tickers" :key="ticker" :color="getTickerColor(ticker)" size="large" variant="outlined">
|
||||||
|
{{ ticker }}: ${{ maxPrice[ticker] }}
|
||||||
|
</v-chip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<v-skeleton-loader class="chart-loader" v-if="stockPrice.loading" />
|
||||||
|
<ag-charts-vue class="chart" v-else :options="options" />
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.toolbar {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar .toggles {
|
||||||
|
flex: 1 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar .chips, .toolbar .label {
|
||||||
|
flex: 0 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { AgChartsVue } from 'ag-charts-vue3';
|
||||||
|
import { PriceHistory, getPriceHistory } from '@/api';
|
||||||
|
import { defineLoader } from '@/api/loader';
|
||||||
|
import { time, AgAxisLabelFormatterParams } from 'ag-charts-community';
|
||||||
|
import { TimeInterval } from 'ag-charts-community/dist/cjs/es5/util/time/interval';
|
||||||
|
import { DurationLike, DateTime } from 'luxon';
|
||||||
|
import { roundTo } from 'round-to';
|
||||||
|
import { computed, ref, onMounted } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
tickers: string[],
|
||||||
|
colors: string[]
|
||||||
|
}>();
|
||||||
|
|
||||||
|
type TimeOptions = '1M' | '3M' | '6M' | '1Y' | '5Y' | 'MAX';
|
||||||
|
|
||||||
|
const timeToggle = ref<TimeOptions>('1M');
|
||||||
|
|
||||||
|
const stockPrice = defineLoader<PriceHistory[]>(() => getPriceHistory(props.tickers));
|
||||||
|
|
||||||
|
const optToDuration: Record<TimeOptions, [DurationLike | undefined, TimeInterval, string]> = {
|
||||||
|
'1M': [{ months: 1 }, time.day, '%d'],
|
||||||
|
'3M': [{ months: 3 }, time.friday, '%m-%d'],
|
||||||
|
'6M': [{ months: 6 }, time.friday.every(2), '%m-%d'],
|
||||||
|
'1Y': [{ years: 1 }, time.month, '%Y-%m'],
|
||||||
|
'5Y': [{ years: 5 }, time.month.every(3, {
|
||||||
|
snapTo: DateTime.utc(2000, 1, 1).toJSDate() // snap to solar year quarters
|
||||||
|
}), '%Y-%m'],
|
||||||
|
'MAX': [undefined, time.year.every(2), '%Y']
|
||||||
|
};
|
||||||
|
|
||||||
|
const getTickerColor = (ticker: string) => props.colors[props.tickers.indexOf(ticker)];
|
||||||
|
|
||||||
|
const maxPrice = computed(() => {
|
||||||
|
const maxVal = Object.fromEntries(props.tickers.map(t => [t, NaN]));
|
||||||
|
let maxDate = -Infinity;
|
||||||
|
|
||||||
|
if (stockPrice.loading) return maxVal;
|
||||||
|
|
||||||
|
for (const d of stockPrice.data ?? []) {
|
||||||
|
if (Date.parse(d.date) > maxDate) {
|
||||||
|
maxDate = Date.parse(d.date);
|
||||||
|
for (const ticker in maxVal) {
|
||||||
|
maxVal[ticker] = d[ticker] as number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const ticker in maxVal) {
|
||||||
|
maxVal[ticker] = roundTo(maxVal[ticker], 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return maxVal;
|
||||||
|
})
|
||||||
|
|
||||||
|
const options = computed(() => {
|
||||||
|
if (stockPrice.loading) return null;
|
||||||
|
|
||||||
|
const maxDate = DateTime.now();
|
||||||
|
const opts = optToDuration[timeToggle.value];
|
||||||
|
const minDate = opts[0] ? maxDate.minus(opts[0]) : undefined;
|
||||||
|
|
||||||
|
const renderer = (params: any) => ({
|
||||||
|
title: params.title,
|
||||||
|
content: DateTime.fromMillis(params.xValue).toISODate() + ': ' + roundTo(params.yValue, 2),
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
theme: 'ag-material',
|
||||||
|
data: stockPrice.data?.map(e => ({ ...e, date: Date.parse(e.date) })),
|
||||||
|
series: props.tickers.map((t: string) => ({
|
||||||
|
xKey: 'date',
|
||||||
|
yKey: t,
|
||||||
|
yName: t,
|
||||||
|
stroke: getTickerColor(t),
|
||||||
|
tooltip: { renderer: renderer },
|
||||||
|
marker: {
|
||||||
|
fill: getTickerColor(t),
|
||||||
|
stroke: getTickerColor(t)
|
||||||
|
}
|
||||||
|
})),
|
||||||
|
axes: [
|
||||||
|
{
|
||||||
|
type: 'time',
|
||||||
|
position: 'bottom',
|
||||||
|
min: minDate?.toJSDate(),
|
||||||
|
max: maxDate.toJSDate(),
|
||||||
|
tick: {
|
||||||
|
interval: opts[1]
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
autoRotate: true,
|
||||||
|
autoRotateAngle: 335,
|
||||||
|
format: opts[2]
|
||||||
|
},
|
||||||
|
gridStyle: [{
|
||||||
|
lineDash: [Infinity]
|
||||||
|
}, {
|
||||||
|
lineDash: [Infinity]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'number',
|
||||||
|
position: 'left',
|
||||||
|
label: {
|
||||||
|
format: '$~s',
|
||||||
|
formatter: (params: AgAxisLabelFormatterParams) =>
|
||||||
|
params?.formatter?.(params.value)
|
||||||
|
.replace('k', 'K')
|
||||||
|
.replace('G', 'B') ?? '' + '$'
|
||||||
|
},
|
||||||
|
gridStyle: [{
|
||||||
|
lineDash: [Infinity]
|
||||||
|
}, {
|
||||||
|
lineDash: [Infinity]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
legend: {
|
||||||
|
position: 'bottom',
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
stockPrice.load();
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -25,26 +25,8 @@
|
||||||
</v-row>
|
</v-row>
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col cols="12">
|
<v-col cols="12">
|
||||||
<v-card>
|
<stock-price :colors="colors" :tickers="tickers" />
|
||||||
<v-card-item>
|
|
||||||
<v-card-title>Stock price over time</v-card-title>
|
|
||||||
</v-card-item>
|
|
||||||
<v-card-text>
|
|
||||||
<v-btn-toggle class="mb-3" v-model="timeToggle" color="secondary" mandatory>
|
|
||||||
<v-btn value="1M">1M</v-btn>
|
|
||||||
<v-btn value="3M">3M</v-btn>
|
|
||||||
<v-btn value="6M">6M</v-btn>
|
|
||||||
<v-btn value="1Y">1Y</v-btn>
|
|
||||||
<v-btn value="5Y">5Y</v-btn>
|
|
||||||
<v-btn value="MAX">Max</v-btn>
|
|
||||||
</v-btn-toggle>
|
|
||||||
<v-skeleton-loader class="chart-loader" v-if="stockPrice.loading" />
|
|
||||||
<ag-charts-vue class="chart" v-else :options="options" />
|
|
||||||
</v-card-text>
|
|
||||||
</v-card>
|
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
|
||||||
<v-row>
|
|
||||||
<v-col cols="12">
|
<v-col cols="12">
|
||||||
<employees-chart :colors="colors" :tickers="tickers" />
|
<employees-chart :colors="colors" :tickers="tickers" />
|
||||||
</v-col>
|
</v-col>
|
||||||
|
@ -75,112 +57,31 @@
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { AgAxisLabelFormatterParams, time } from 'ag-charts-community';
|
import { ref, onMounted } from 'vue';
|
||||||
import { AgChartsVue } from 'ag-charts-vue3';
|
|
||||||
import { ref, onMounted, computed, } from 'vue';
|
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import { Company, PriceHistory, getCompanies, getPriceHistory } from '@/api';
|
import { Company, getCompanies } from '@/api';
|
||||||
import { DateTime, DurationLike } from 'luxon';
|
|
||||||
import { TimeInterval } from 'ag-charts-community/dist/cjs/es5/util/time/interval';
|
|
||||||
import { roundTo } from 'round-to';
|
|
||||||
import { defineLoader } from '@/api/loader';
|
import { defineLoader } from '@/api/loader';
|
||||||
import CompanyCard from '@/components/CompanyCard.vue';
|
import CompanyCard from '@/components/CompanyCard.vue';
|
||||||
import EmployeesChart from '@/components/EmployeesChart.vue';
|
import EmployeesChart from '@/components/EmployeesChart.vue';
|
||||||
import BalanceSheet from '@/components/BalanceSheet.vue';
|
import BalanceSheet from '@/components/BalanceSheet.vue';
|
||||||
import EpsChart from '@/components/EpsChart.vue';
|
import EpsChart from '@/components/EpsChart.vue';
|
||||||
|
import StockPrice from '@/components/StockPrice.vue';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const goHome = () => router.push('/');
|
const goHome = () => router.push('/');
|
||||||
|
|
||||||
type TimeOptions = '1M' | '3M' | '6M' | '1Y' | '5Y' | 'MAX';
|
|
||||||
|
|
||||||
const timeToggle = ref<TimeOptions>('1M');
|
|
||||||
const companies = defineLoader<Company[]>(() => getCompanies(tickers.value));
|
const companies = defineLoader<Company[]>(() => getCompanies(tickers.value));
|
||||||
const stockPrice = defineLoader<PriceHistory[]>(() => getPriceHistory(tickers.value));
|
|
||||||
|
|
||||||
const optToDuration: Record<TimeOptions, [DurationLike | undefined, TimeInterval, string]> = {
|
|
||||||
'1M': [{ months: 1 }, time.day, '%d'],
|
|
||||||
'3M': [{ months: 3 }, time.friday, '%m-%d'],
|
|
||||||
'6M': [{ months: 6 }, time.friday.every(2), '%m-%d'],
|
|
||||||
'1Y': [{ years: 1 }, time.month, '%Y-%m'],
|
|
||||||
'5Y': [{ years: 5 }, time.month.every(3, {
|
|
||||||
snapTo: DateTime.utc(2000, 1, 1).toJSDate() // snap to solar year quarters
|
|
||||||
}), '%Y-%m'],
|
|
||||||
'MAX': [undefined, time.year.every(2), '%Y']
|
|
||||||
};
|
|
||||||
|
|
||||||
const tickers = ref<string[]>([]);
|
const tickers = ref<string[]>([]);
|
||||||
|
|
||||||
const colors = ['#9C27B0', '#D32F2F', '#3F51B5'];
|
const colors = ['#9C27B0', '#D32F2F', '#3F51B5'];
|
||||||
|
|
||||||
const getTickerColor = (ticker: string) => colors[tickers.value.indexOf(ticker)];
|
const getTickerColor = (ticker: string) => colors[tickers.value.indexOf(ticker)];
|
||||||
|
|
||||||
const options = computed(() => {
|
|
||||||
if (stockPrice.loading) return null;
|
|
||||||
|
|
||||||
const maxDate = DateTime.now();
|
|
||||||
const opts = optToDuration[timeToggle.value];
|
|
||||||
const minDate = opts[0] ? maxDate.minus(opts[0]) : undefined;
|
|
||||||
|
|
||||||
const renderer = (params: any) => ({
|
|
||||||
title: params.title,
|
|
||||||
content: DateTime.fromMillis(params.xValue).toISODate() + ': ' + roundTo(params.yValue, 2),
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
theme: 'ag-material',
|
|
||||||
data: stockPrice.data?.map(e => ({ ...e, date: Date.parse(e.date) })),
|
|
||||||
series: tickers.value.map((t: string) => ({
|
|
||||||
xKey: 'date',
|
|
||||||
yKey: t,
|
|
||||||
yName: t,
|
|
||||||
stroke: getTickerColor(t),
|
|
||||||
tooltip: { renderer: renderer },
|
|
||||||
marker: {
|
|
||||||
fill: getTickerColor(t),
|
|
||||||
stroke: getTickerColor(t)
|
|
||||||
}
|
|
||||||
})),
|
|
||||||
axes: [
|
|
||||||
{
|
|
||||||
type: 'time',
|
|
||||||
position: 'bottom',
|
|
||||||
min: minDate?.toJSDate(),
|
|
||||||
max: maxDate.toJSDate(),
|
|
||||||
tick: {
|
|
||||||
interval: opts[1]
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
autoRotate: true,
|
|
||||||
autoRotateAngle: 335,
|
|
||||||
format: opts[2]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'number',
|
|
||||||
position: 'left',
|
|
||||||
label: {
|
|
||||||
format: '$~s',
|
|
||||||
formatter: (params: AgAxisLabelFormatterParams) =>
|
|
||||||
params?.formatter?.(params.value)
|
|
||||||
.replace('k', 'K')
|
|
||||||
.replace('G', 'B') ?? '' + '$'
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
legend: {
|
|
||||||
position: 'bottom',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
tickers.value = route.params.tickers.toString().split(',');
|
tickers.value = route.params.tickers.toString().split(',');
|
||||||
|
|
||||||
// load chart data
|
// load chart data
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
stockPrice.load();
|
|
||||||
companies.load();
|
companies.load();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
Reference in a new issue