FinancialCard.vue 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. <template>
  2. <q-card
  3. class="financial-card"
  4. :class="{
  5. 'financial-card--selected': selected,
  6. 'financial-card--clickable': clickable,
  7. }"
  8. @click="clickable && emit('click')"
  9. >
  10. <div class="row justify-between items-start no-wrap">
  11. <span class="text-subtitle1 text-dark card-title">{{ title }}</span>
  12. <q-icon :name="icon" size="22px" color="dark" />
  13. </div>
  14. <div class="bottom-area">
  15. <div class="text-h5 text-primary value-text">{{ formattedValue }}</div>
  16. <template v-if="hasFooter">
  17. <q-separator class="q-mt-sm q-mb-xs" />
  18. <div class="row items-center justify-between no-wrap">
  19. <div class="column" style="gap: 2px">
  20. <span v-if="percentage !== null" class="text-caption text-foreground">
  21. {{ hideValues ? "••" : percentage }}% vs o mês anterior
  22. </span>
  23. <span v-if="integer !== null" class="text-caption text-foreground">
  24. {{ hideValues ? "•" : integer }} {{ integerLabel }}
  25. </span>
  26. </div>
  27. <span v-if="description" class="text-caption text-foreground">
  28. {{ description }}
  29. </span>
  30. </div>
  31. </template>
  32. </div>
  33. </q-card>
  34. </template>
  35. <script setup>
  36. import { computed } from "vue";
  37. const props = defineProps({
  38. title: { type: String, required: true },
  39. icon: { type: String, default: "mdi-cash-multiple" },
  40. financialValue: { type: Number, default: 0 },
  41. legend: { type: String, default: "" },
  42. percentage: { type: Number, default: null },
  43. integer: { type: Number, default: null },
  44. integerLabel: { type: String, default: "pagamentos restantes" },
  45. description: { type: String, default: "" },
  46. hideValues: { type: Boolean, default: false },
  47. clickable: { type: Boolean, default: false },
  48. selected: { type: Boolean, default: false },
  49. });
  50. const emit = defineEmits(["click"]);
  51. const formattedValue = computed(() =>
  52. props.hideValues
  53. ? "R$ ••••"
  54. : new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL" }).format(
  55. props.financialValue,
  56. ),
  57. );
  58. const hasFooter = computed(
  59. () => props.percentage !== null || props.integer !== null || !!props.description,
  60. );
  61. </script>
  62. <style scoped lang="scss">
  63. @import "src/css/quasar.variables.scss";
  64. .financial-card--clickable {
  65. cursor: pointer;
  66. &:hover {
  67. box-shadow: 0 0 0 1.5px $primary !important;
  68. }
  69. }
  70. .financial-card--selected {
  71. box-shadow: 0 0 0 2px $primary !important;
  72. }
  73. .financial-card {
  74. flex: 1 1 0;
  75. min-width: 220px;
  76. border-radius: 12px;
  77. box-shadow: 0 0 0 1px #c0c0c0c0 !important;
  78. padding: 16px 20px;
  79. display: flex;
  80. flex-direction: column;
  81. justify-content: space-between;
  82. gap: 12px;
  83. }
  84. .card-title {
  85. line-height: 1.3;
  86. }
  87. .bottom-area {
  88. display: flex;
  89. flex-direction: column;
  90. }
  91. .value-text {
  92. font-weight: 600;
  93. line-height: 1.2;
  94. }
  95. </style>