Added color scale support to main page indicators

This commit is contained in:
Claudio Maggioni 2023-05-19 19:53:13 +02:00
parent fdd6fc3d72
commit 74928aee46

View file

@ -39,7 +39,7 @@
<strong>{{ m.title }}</strong> <strong>{{ m.title }}</strong>
<span class="text-right">{{ m.value(company) }}{{ m.symbol ?? '' }}</span> <span class="text-right">{{ m.value(company) }}{{ m.symbol ?? '' }}</span>
</div> </div>
<v-progress-linear :color="m.color" :model-value="m.percentage(company)"></v-progress-linear> <v-progress-linear :color="m.color(company)" :model-value="m.percentage(company)"></v-progress-linear>
</div> </div>
</v-card-text> </v-card-text>
@ -134,52 +134,101 @@ const setSearch = (text: string) => searchText.value = text;
watch(filteredCompanies, () => loading.value = false); watch(filteredCompanies, () => loading.value = false);
type ColorScale = { gt?: number, color: string }[];
interface Metric { interface Metric {
title: string, title: string,
color: string,
minValue: number, minValue: number,
maxValue: number, maxValue: number,
value: (c: Company) => number // in [0, 100], value: (c: Company) => number // in [0, 100],
symbol?: string, symbol?: string,
decimals?: number decimals?: number
scale: ColorScale
} }
// COLORS from Pietro:
// Valuation: < 1 ( GREEN); > 1 (RED); = 1 (ORANGE)
// Financial Health: < 1 (GREEN); > 1 (RED); = 1 (ORANGE)
// Growth: < 0 (RED); 0 < x < 8% (ORANGE); < 8 % (GREEN)
// Past performance: -100 < x < 0 (RED); = 0 (ORANGE); 0 < x < 100 (GREEN)
const COLORS = {
good: 'success',
warning: 'warning',
bad: 'error'
};
const metricsData = reactive<Metric[]>([ const metricsData = reactive<Metric[]>([
{ {
title: 'Valuation', title: 'Valuation',
color: 'secondary',
minValue: 0, minValue: 0,
maxValue: 150, maxValue: 150,
value: c => c['Valuation'] value: c => c['Valuation'],
scale: [
{ gt: 1.1, color: COLORS.bad },
{ gt: 0.9, color: COLORS.warning },
{ color: COLORS.good }
]
}, },
{ {
title: 'Financial Health', title: 'Financial Health',
color: 'secondary',
minValue: 0, minValue: 0,
maxValue: 500, maxValue: 500,
value: c => c['Financial Health'] value: c => c['Financial Health'],
scale: [
{ gt: 1.1, color: COLORS.bad },
{ gt: 0.9, color: COLORS.warning },
{ color: COLORS.good }
]
}, },
{ {
title: 'Estimated Growth', title: 'Estimated Growth',
color: 'secondary',
minValue: 0, minValue: 0,
maxValue: 200, maxValue: 200,
value: c => c['Estimated Growth'], value: c => c['Estimated Growth'],
symbol: ' %' symbol: ' %',
scale: [
{ gt: 8, color: COLORS.good },
{ gt: 0, color: COLORS.warning },
{ color: COLORS.bad }
]
}, },
{ {
title: 'Past Performance', title: 'Past Performance',
color: 'secondary', minValue: -100,
minValue: 0,
maxValue: 200, maxValue: 200,
value: c => c['Past Performance'] value: c => c['Past Performance'],
symbol: ' %',
scale: [
{ gt: 5, color: COLORS.good },
{ gt: -5, color: COLORS.warning },
{ gt: -Infinity, color: COLORS.bad }
]
} }
]); ]);
const metrics = computed<(Metric & { percentage: (c: Company) => number })[]>(() => metricsData.map(e => ({ type ExtendedMetric = Metric & {
percentage: (c: Company) => number,
color: (c: Company) => string
}
const metrics = computed<ExtendedMetric[]>(() => metricsData.map(e => ({
...e, ...e,
percentage: (c: Company) => (e.value(c) - e.minValue) * 100 / (e.maxValue - e.minValue), percentage: (c: Company) => (e.value(c) - e.minValue) * 100 / (e.maxValue - e.minValue),
value: (c: Company) => roundTo(e.value(c), e.decimals ?? 2) value: (c: Company) => roundTo(e.value(c), e.decimals ?? 2),
color: (c: Company) => {
console.log(JSON.parse(JSON.stringify(e.scale)));
const value = e.value(c);
console.log(c.ticker, value);
for (const s of e.scale) {
console.log('checking', s.gt, s.color);
if (typeof s.gt !== 'number' || value > s.gt) {
console.log(s.gt, s.color);
return s.color;
}
}
return 'blue-grey' // default value, should never be displayed
}
}))); })));
getCompanies().then(cs => { getCompanies().then(cs => {