Skip to content

Commit

Permalink
Add part of dashboard (#1012)
Browse files Browse the repository at this point in the history
* - feat: add RevenueByLocationMap.vue

* - feat: add revenue reports with chart
- feat: add YearlyBreakup.vue

* - feat: add base ProjectTable.vue

* - feat: add DataSection.vue

* - feat: update Dashboard.vue

* raw: dashboard first row

* fix: move Crimea to Ukraine

* chore(dashboard): cleanup

* chore(dashboard): add cards

* chore(dashboard): refactor

---------

Co-authored-by: Maksim Nedoshev <[email protected]>
  • Loading branch information
VasylHryha and m0ksem authored Jan 23, 2024
1 parent c7ccdb3 commit 77383bd
Show file tree
Hide file tree
Showing 35 changed files with 44,379 additions and 813 deletions.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,21 @@
"@amcharts/amcharts5-geodata": "^5.1.1",
"@fortawesome/fontawesome-free": "^6.1.1",
"@gtm-support/vue-gtm": "^2.0.0",
"@vue-leaflet/vue-leaflet": "^0.10.1",
"@vuestic/tailwind": "^0.1.3",
"@vueuse/core": "^10.6.1",
"axios": "^1.6.1",
"chart.js": "^3.8.0",
"chart.js": "^4.4.1",
"epic-spinners": "^2.0.0",
"flag-icons": "^6.15.0",
"ionicons": "^4.6.3",
"leaflet": "^1.9.4",
"medium-editor": "^5.23.3",
"pinia": "^2.1.7",
"register-service-worker": "^1.7.1",
"sass": "^1.69.5",
"serve": "^14.2.1",
"vue": "^3.3.7",
"vue": "3.3.9",
"vue-chartjs": "^4.1.1",
"vue-i18n": "^9.6.2",
"vue-router": "^4.2.5",
Expand Down Expand Up @@ -69,8 +71,6 @@
"lint-staged": "^15.1.0",
"postcss": "^8.4.21",
"prettier": "^3.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"storybook": "^7.4.6",
"tailwindcss": "^3.4.0",
"typescript": "^5.2.2",
Expand Down
30 changes: 13 additions & 17 deletions src/components/va-charts/VaChart.vue
Original file line number Diff line number Diff line change
@@ -1,34 +1,30 @@
<template>
<!-- @vue-ignore -->
<Component :is="chartComponent" ref="chart" :chart-data="data" :chart-options="chartOptions" class="va-chart" />
<component :is="chartComponent" :chart-data="data" :chart-options="chartOptions" class="va-chart" />
</template>

<script lang="ts" setup>
import { computed, ref } from 'vue'
import type { TChartOptions } from 'vue-chartjs/dist/types'
<script lang="ts" setup generic="T extends 'line' | 'bar' | 'bubble' | 'doughnut' | 'pie'">
import { computed } from 'vue'
import type { TChartOptions, TChartData } from 'vue-chartjs/dist/types'
import { defaultConfig, chartTypesMap } from './vaChartConfigs'
import { TChartData } from '../../data/types'
const props = defineProps<{
data: TChartData
options?: TChartOptions<'line' | 'bar' | 'bubble' | 'doughnut' | 'pie'>
type: keyof typeof chartTypesMap
data: TChartData<T>
options?: TChartOptions<T>
type: T
}>()
const chart = ref()
const chartComponent = chartTypesMap[props.type]
const chartComponent = computed(() => chartTypesMap[props.type])
const chartOptions = computed(() => ({
...defaultConfig,
const chartOptions = computed<TChartOptions<T>>(() => ({
...(defaultConfig as any),
...props.options,
}))
</script>

<style lang="scss">
.va-chart {
width: 100%;
height: 100%;
min-width: 100%;
min-height: 100%;
display: flex;
align-items: center;
justify-content: center;
Expand All @@ -41,7 +37,7 @@ const chartOptions = computed(() => ({
canvas {
width: 100%;
height: auto;
min-height: 320px;
min-height: 20px;
}
}
</style>
45 changes: 44 additions & 1 deletion src/components/va-charts/chart-types/LineChart.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<template>
<Line :chart-data="props.chartData" :chart-options="chartOptions" />
<Line ref="chart" :chart-data="computedChartData" :chart-options="chartOptions" />
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import { Line } from 'vue-chartjs'
import type { TChartOptions } from 'vue-chartjs/dist/types'
import {
Expand All @@ -17,11 +18,53 @@ import {
Filler,
} from 'chart.js'
import { TLineChartData } from '../../../data/types'
import { computed } from 'vue'
import { useColors } from 'vuestic-ui/web-components'
ChartJS.register(Title, Tooltip, Legend, LineElement, LinearScale, PointElement, CategoryScale, Filler)
const chart = ref<typeof Line>()
const props = defineProps<{
chartData: TLineChartData
chartOptions?: TChartOptions<'line'>
}>()
const ctx = computed(() => {
if (!chart.value) {
return null
}
return chart.value.chart.ctx as CanvasRenderingContext2D
})
const { setHSLAColor, getColor } = useColors()
const colors = ['primary', 'success', 'danger', 'warning']
const computedChartData = computed(() => {
if (!ctx.value) {
return props.chartData
}
const makeGradient = (bg: string) => {
const gradient = ctx.value!.createLinearGradient(0, 0, 0, 70)
gradient.addColorStop(0, setHSLAColor(bg, { a: 0.3 }))
gradient.addColorStop(1, setHSLAColor(bg, { a: 0.05 }))
return gradient
}
const datasets = props.chartData.datasets.map((dataset, index) => {
const color = getColor(colors[index % colors.length])
return {
...dataset,
fill: true,
backgroundColor: makeGradient(color),
borderColor: color,
}
})
return { ...props.chartData, datasets }
})
</script>
55 changes: 48 additions & 7 deletions src/components/va-charts/vaChartConfigs.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { defineAsyncComponent } from 'vue'
import { defineAsyncComponent, markRaw } from 'vue'

const DEFAULT_FONT_FAMILY = "'Inter', sans-serif"

Expand Down Expand Up @@ -56,11 +56,52 @@ export const defaultConfig = {
animation: true,
}

export const doughnutConfig = {
cutout: '80%',
scales: {
x: {
display: false,
grid: {
display: false, // Disable X-axis grid lines ("net")
},
},
y: {
display: false,
grid: {
display: false, // Disable Y-axis grid lines ("net")
},
ticks: {
display: false, // Hide Y-axis values
},
},
},
plugins: {
legend: {
display: false,
},
},
datasets: {
line: {
fill: 'origin',
tension: 0.3,
borderColor: 'transparent',
},
bubble: {
borderColor: 'transparent',
},
bar: {
borderColor: 'transparent',
},
},
maintainAspectRatio: false,
animation: true,
}

export const chartTypesMap = {
pie: defineAsyncComponent(() => import('./chart-types/PieChart.vue')),
doughnut: defineAsyncComponent(() => import('./chart-types/DoughnutChart.vue')),
bubble: defineAsyncComponent(() => import('./chart-types/BubbleChart.vue')),
line: defineAsyncComponent(() => import('./chart-types/LineChart.vue')),
bar: defineAsyncComponent(() => import('./chart-types/BarChart.vue')),
'horizontal-bar': defineAsyncComponent(() => import('./chart-types/HorizontalBarChart.vue')),
pie: markRaw(defineAsyncComponent(() => import('./chart-types/PieChart.vue'))),
doughnut: markRaw(defineAsyncComponent(() => import('./chart-types/DoughnutChart.vue'))),
bubble: markRaw(defineAsyncComponent(() => import('./chart-types/BubbleChart.vue'))),
line: markRaw(defineAsyncComponent(() => import('./chart-types/LineChart.vue'))),
bar: markRaw(defineAsyncComponent(() => import('./chart-types/BarChart.vue'))),
'horizontal-bar': markRaw(defineAsyncComponent(() => import('./chart-types/HorizontalBarChart.vue'))),
}
76 changes: 76 additions & 0 deletions src/components/va-timeline-item.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<template>
<tr class="va-timeline-item">
<td class="va-timeline-item__icon-cell">
<div class="va-timeline-item__icon">
<VaIcon name="schedule" size="22px" color="backgroundBorder" />
</div>
</td>
<td class="va-timeline-item__content-cell">
<div class="va-timeline-item__content">
<slot />
</div>
</td>
<td class="va-timeline-item__date-cell">
<slot name="date">
{{ $props.date }}
</slot>
</td>
</tr>
</template>

<script setup lang="ts">
defineProps({
date: {
type: String,
default: '',
},
})
</script>

<style lang="scss" scoped>
.va-timeline-item {
display: table-row;
&__icon-cell {
vertical-align: top;
height: 1px;
padding-right: 1rem;
}
&__icon {
width: 24px;
position: relative;
display: inline-flex;
justify-content: center;
flex-direction: column;
align-items: center;
height: 100%;
&::after {
content: '';
width: 2px;
height: 100%;
background: var(--va-background-border);
}
}
&__content {
margin-bottom: 1rem;
}
&__date-cell {
vertical-align: top;
color: var(--va-secondary);
text-wrap: nowrap;
padding-left: 0.5rem;
}
&:last-child {
.va-timeline-item__icon {
&::after {
background: transparent;
}
}
}
}
</style>
12 changes: 8 additions & 4 deletions src/data/charts/doughnutChartData.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { TDoughnutChartData } from '../types'

export const profitBackground = '#ECF0F1'
export const expensesBackground = '#fff'
export const earningsBackground = '#154EC1'

export const doughnutChartData: TDoughnutChartData = {
labels: ['North America', 'South America', 'Australia'],
labels: ['Profit', 'Expenses', 'Earnings'],
datasets: [
{
label: 'Population (millions)',
backgroundColor: ['danger', 'info', 'primary'],
data: [2478, 5267, 734],
label: 'Yearly Breakdown',
backgroundColor: [earningsBackground, profitBackground, expensesBackground],
data: [400, 200, 200],
},
],
}
40 changes: 4 additions & 36 deletions src/data/charts/lineChartData.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,12 @@
import { TLineChartData } from '../types'

const months = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
]

const getSize = (minSize = 5) => Math.max(minSize, new Date().getMonth())
const size = getSize()

const generateValue = () => Math.floor(Math.random() * 100)
const generateArray = (length: number) => Array.from(Array(length), generateValue)

const generateYLabels = () => {
const flip = !!Math.floor(Math.random() * 2)
return flip ? ['Debit', 'Credit'] : ['Credit', 'Debit']
}
const yLabels = generateYLabels()

export const lineChartData: TLineChartData = {
labels: months.slice(0, size),
labels: ['January', 'February', 'March', 'April', 'May', 'June'],
datasets: [
{
label: yLabels[0],
backgroundColor: 'primary',
data: generateArray(size),
},
{
label: yLabels[1],
backgroundColor: 'secondary',
data: generateArray(size),
label: 'Monthly Earnings',
backgroundColor: 'rgba(75,192,192,0.4)',
data: [65, 59, 80, 81, 56, 55, 40], // Random values
},
],
}
33 changes: 33 additions & 0 deletions src/data/charts/revenueChartData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
export const earningsColor = '#49A8FF'
export const expensesColor = '#154EC1'

export const months: string[] = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

export type Revenues = {
month: string
earning: number
expenses: number
}

export const generateRevenues = (months: string[]): Revenues[] => {
return months.map((month: string) => {
const earning = Math.floor(Math.random() * 100000 + 10000)
return {
month,
earning,
expenses: Math.floor(earning * Math.random()),
}
})
}

export const getRevenuePerMonth = (month: string, revenues: Revenues[]): Revenues => {
const revenue = revenues.find((revenue) => revenue.month === month)
return revenue || { month, earning: 0, expenses: 0 }
}

export const formatMoney = (amount: number, currency = 'USD'): string => {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency,
}).format(amount)
}
Loading

0 comments on commit 77383bd

Please sign in to comment.