forked from cerc-io/cosmos-explorer
feat: chart theme switch
This commit is contained in:
parent
b10578e680
commit
2f93b4c10c
@ -1,50 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { Icon } from '@iconify/vue';
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
const props = defineProps<{
|
||||
themes: {
|
||||
name: string;
|
||||
icon: string;
|
||||
}[];
|
||||
}>();
|
||||
|
||||
const themeMap = { system: 'mdi-laptop', light: 'mdi-weather-sunny', dark: 'mdi-weather-night' }
|
||||
|
||||
const theme = ref(window.localStorage.getItem('theme') || 'dark');
|
||||
|
||||
const changeMode = () => {
|
||||
let value = 'dark';
|
||||
if (theme.value === 'dark') {
|
||||
value = 'light';
|
||||
}
|
||||
if (
|
||||
theme.value === 'system' &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
) {
|
||||
value = 'dark';
|
||||
}
|
||||
if (value === 'light') {
|
||||
document.documentElement.classList.add('light');
|
||||
document.documentElement.classList.remove('dark');
|
||||
} else {
|
||||
document.documentElement.classList.add('dark');
|
||||
document.documentElement.classList.remove('light');
|
||||
}
|
||||
document.documentElement.setAttribute('data-theme', value);
|
||||
window.localStorage.setItem('theme', value);
|
||||
};
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="tooltip tooltip-bottom delay-1000">
|
||||
<button class=" btn btn-ghost btn-circle btn-sm mx-1" @click="changeMode">
|
||||
<Icon :icon="props.themes[theme].icon" class="text-2xl" />
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
@ -1,17 +1,26 @@
|
||||
<script lang="ts" setup>
|
||||
import ApexCharts from 'vue3-apexcharts';
|
||||
import { computed } from 'vue';
|
||||
import { useBaseStore } from '@/stores';
|
||||
import { getDonutChartConfig } from './apexChartConfig';
|
||||
|
||||
const props = defineProps(['series', 'labels']);
|
||||
|
||||
const expenseRationChartConfig = computed(() =>
|
||||
getDonutChartConfig(window.localStorage.getItem('theme') || 'dark', props.labels)
|
||||
);
|
||||
const baseStore = useBaseStore();
|
||||
|
||||
const expenseRationChartConfig = computed(() => {
|
||||
const theme = baseStore.theme;
|
||||
getDonutChartConfig(theme, props.labels);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ApexCharts type="donut" height="410" :options="expenseRationChartConfig" :series="series" />
|
||||
<ApexCharts
|
||||
type="donut"
|
||||
height="410"
|
||||
:options="expenseRationChartConfig"
|
||||
:series="series"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -3,11 +3,14 @@ import ApexCharts from 'vue3-apexcharts';
|
||||
import { getMarketPriceChartConfig } from './apexChartConfig';
|
||||
import { useIndexModule } from '@/modules/[chain]/indexStore';
|
||||
import { computed, ref } from '@vue/reactivity';
|
||||
import { useBaseStore } from '@/stores';
|
||||
|
||||
const store = useIndexModule();
|
||||
const baseStore = useBaseStore();
|
||||
const chartConfig = computed(() => {
|
||||
const theme = baseStore.theme;
|
||||
const labels = store.marketData.prices.map((item: any) => item[0]);
|
||||
return getMarketPriceChartConfig(window.localStorage.getItem('theme') || 'dark', labels);
|
||||
return getMarketPriceChartConfig(theme, labels);
|
||||
});
|
||||
const kind = ref('price');
|
||||
const series = computed(() => {
|
||||
@ -17,7 +20,9 @@ const series = computed(() => {
|
||||
data:
|
||||
kind.value === 'price'
|
||||
? store.marketData.prices.map((item: any) => item[1])
|
||||
: store.marketData.total_volumes.map((item: any) => item[1]),
|
||||
: store.marketData.total_volumes.map(
|
||||
(item: any) => item[1]
|
||||
),
|
||||
},
|
||||
];
|
||||
});
|
||||
@ -29,14 +34,25 @@ function changeChart(type: string) {
|
||||
|
||||
<template>
|
||||
<div class="tabs tabs-boxed bg-transparent justify-end">
|
||||
<a class="tab text-xs mr-2 text-gray-400 uppercase" :class="{ 'tab-active': kind === 'price' }"
|
||||
@click="changeChart('price')">
|
||||
<a
|
||||
class="tab text-xs mr-2 text-gray-400 uppercase"
|
||||
:class="{ 'tab-active': kind === 'price' }"
|
||||
@click="changeChart('price')"
|
||||
>
|
||||
Price
|
||||
</a>
|
||||
<a class="tab text-xs text-gray-400 uppercase" :class="{ 'tab-active': kind === 'volume' }"
|
||||
@click="changeChart('volume')">
|
||||
<a
|
||||
class="tab text-xs text-gray-400 uppercase"
|
||||
:class="{ 'tab-active': kind === 'volume' }"
|
||||
@click="changeChart('volume')"
|
||||
>
|
||||
Volume
|
||||
</a>
|
||||
</div>
|
||||
<ApexCharts type="area" height="230" :options="chartConfig" :series="series" />
|
||||
<ApexCharts
|
||||
type="area"
|
||||
height="230"
|
||||
:options="chartConfig"
|
||||
:series="series"
|
||||
/>
|
||||
</template>
|
||||
|
@ -34,11 +34,16 @@ const handleLangChange = (lang: string) => {
|
||||
<div
|
||||
class="dropdown"
|
||||
:class="
|
||||
currentLang === 'ar' ? 'dropdown-right' : 'dropdown-bottom dropdown-end'
|
||||
currentLang === 'ar'
|
||||
? 'dropdown-right'
|
||||
: 'dropdown-bottom dropdown-end'
|
||||
"
|
||||
>
|
||||
<label tabindex="0" class="btn btn-ghost btn-circle btn-sm mx-1">
|
||||
<Icon icon="mdi-translate" class="text-2xl" />
|
||||
<Icon
|
||||
icon="mdi-translate"
|
||||
class="text-2xl text-gray-500 dark:text-gray-400"
|
||||
/>
|
||||
</label>
|
||||
<ul
|
||||
tabindex="0"
|
||||
|
@ -1,23 +1,24 @@
|
||||
<script setup lang="ts">
|
||||
import { Icon } from '@iconify/vue';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { onMounted, computed } from 'vue';
|
||||
import { useBaseStore } from '@/stores';
|
||||
|
||||
const themeMap: Record<string, string> = { system: 'mdi-laptop', light: 'mdi-weather-sunny', dark: 'mdi-weather-night' }
|
||||
const themeMap: Record<string, string> = {
|
||||
system: 'mdi-laptop',
|
||||
light: 'mdi-weather-sunny',
|
||||
dark: 'mdi-weather-night',
|
||||
};
|
||||
const baseStore = useBaseStore();
|
||||
const theme = computed(() => {
|
||||
return baseStore.theme;
|
||||
});
|
||||
|
||||
const theme = ref(window.localStorage.getItem('theme') || 'dark');
|
||||
|
||||
const changeMode = (val?: string) => {
|
||||
let value = 'dark';
|
||||
const currentValue = val || theme.value;
|
||||
const changeMode = (val?: 'dark' | 'light') => {
|
||||
let value: 'dark' | 'light' = 'dark';
|
||||
const currentValue: 'dark' | 'light' = val || theme.value;
|
||||
if (currentValue === 'dark') {
|
||||
value = 'light';
|
||||
}
|
||||
if (
|
||||
currentValue === 'system' &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
) {
|
||||
value = 'dark';
|
||||
}
|
||||
if (value === 'light') {
|
||||
document.documentElement.classList.add('light');
|
||||
document.documentElement.classList.remove('dark');
|
||||
@ -27,10 +28,9 @@ const changeMode = (val?: string) => {
|
||||
}
|
||||
document.documentElement.setAttribute('data-theme', value);
|
||||
window.localStorage.setItem('theme', value);
|
||||
theme.value = value;
|
||||
baseStore.theme = value;
|
||||
};
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
changeMode(theme.value === 'light' ? 'dark' : 'light');
|
||||
});
|
||||
@ -38,8 +38,11 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<div class="tooltip tooltip-bottom delay-1000">
|
||||
<button class=" btn btn-ghost btn-circle btn-sm mx-1" @click="changeMode()">
|
||||
<Icon :icon="themeMap?.[theme]" class="text-2xl" />
|
||||
<button
|
||||
class="btn btn-ghost btn-circle btn-sm mx-1"
|
||||
@click="changeMode()"
|
||||
>
|
||||
<Icon :icon="themeMap?.[theme]" class="text-2xl text-gray-500 dark:text-gray-400" />
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -12,6 +12,9 @@ export const useBaseStore = defineStore('baseStore', {
|
||||
earlest: {} as Block,
|
||||
latest: {} as Block,
|
||||
recents: [] as Block[],
|
||||
theme: (window.localStorage.getItem('theme') || 'dark') as
|
||||
| 'light'
|
||||
| 'dark',
|
||||
};
|
||||
},
|
||||
getters: {
|
||||
@ -33,10 +36,14 @@ export const useBaseStore = defineStore('baseStore', {
|
||||
return useBlockchain();
|
||||
},
|
||||
currentChainId(): string {
|
||||
return this.latest.block?.header.chain_id || ""
|
||||
return this.latest.block?.header.chain_id || '';
|
||||
},
|
||||
txsInRecents() {
|
||||
const txs = [] as { height: string; hash: string; tx: DecodedTxRaw }[];
|
||||
const txs = [] as {
|
||||
height: string;
|
||||
hash: string;
|
||||
tx: DecodedTxRaw;
|
||||
}[];
|
||||
this.recents.forEach((b) =>
|
||||
b.block?.data?.txs.forEach((tx: string) => {
|
||||
if (tx) {
|
||||
@ -89,7 +96,10 @@ export const useBaseStore = defineStore('baseStore', {
|
||||
},
|
||||
|
||||
async fetchValidatorByHeight(height?: number, offset = 0) {
|
||||
return this.blockchain.rpc.getBaseValidatorsetAt(String(height), offset);
|
||||
return this.blockchain.rpc.getBaseValidatorsetAt(
|
||||
String(height),
|
||||
offset
|
||||
);
|
||||
},
|
||||
async fetchLatestValidators(offset = 0) {
|
||||
return this.blockchain.rpc.getBaseValidatorsetLatest(offset);
|
||||
|
Loading…
Reference in New Issue
Block a user