PluginProbe
Hostinger Tools / 3.0.79
Hostinger Tools v3.0.79
3.0.79 3.0.78 3.0.77 3.0.76 3.0.75 3.0.74 3.0.73 3.0.72 3.0.71 3.0.70 3.0.69 3.0.68 3.0.67 3.0.66 1.8.1 1.8.2 1.8.3 1.9.1 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 All 110 releases
hostinger / vue-frontend / src / components / HostingerTools / SectionCard.vue

SectionCard.vue in Hostinger Tools 3.0.79, at vue-frontend/src/components/HostingerTools/SectionCard.vue

252 lines 6.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <script lang="ts" setup>
2 import Button from "@/components/Button/Button.vue";
3 import Card from "@/components/Card.vue";
4 import CopyField from "@/components/CopyField.vue";
5 import Icon from "@/components/Icon/Icon.vue";
6 import SkeletonLoader from "@/components/Loaders/SkeletonLoader.vue";
7 import Toggle from "@/components/Toggle.vue";
8 import { SectionHeaderButton, SectionItem } from "@/types";
9 import { translate } from "@/utils/helpers";
10
11 type SectionHeaderToggle = {
12 value: boolean;
13 onToggle?: (value: boolean) => void;
14 };
15
16 type Props = {
17 title: string;
18 isLoading?: boolean;
19 sectionItems: SectionItem[];
20 headerButtons?: SectionHeaderButton[];
21 headerToggle?: SectionHeaderToggle;
22 warning?: string;
23 isDisabled?: boolean;
24 };
25
26 type Emits = {
27 "save-section": [value: boolean, item: SectionItem];
28 };
29
30 defineProps<Props>();
31
32 const emit = defineEmits<Emits>();
33 </script>
34
35 <template>
36 <div class="home-section">
37 <Card v-if="isLoading">
38 <SkeletonLoader
39 class="h-mb-24"
40 width="50%"
41 :height="24"
42 rounded
43 />
44 <SkeletonLoader
45 v-for="(item, index) in sectionItems"
46 :key="`skeleton-${index}`"
47 :class="{ 'h-mb-24': index !== sectionItems.length - 1 }"
48 width="100%"
49 :height="item.copyLink ? 48 : 24"
50 rounded
51 />
52 </Card>
53 <Card v-else>
54 <template #header>
55 <div class="w-100">
56 <slot name="snackbar" />
57 <div
58 class="d-flex align-items-center justify-content-between w-100"
59 >
60 <div class="d-flex align-items-center">
61 <Toggle
62 v-if="headerToggle"
63 :model-value="headerToggle.value"
64 :bind="false"
65 :is-disabled="isDisabled"
66 class="h-mr-16"
67 @click="
68 headerToggle.onToggle &&
69 headerToggle.onToggle(!headerToggle.value)
70 "
71 />
72 <h2 class="h-m-0">
73 {{ title }}
74 </h2>
75 </div>
76 <div
77 v-if="headerButtons?.length"
78 class="d-flex align-items-center"
79 >
80 <Button
81 v-for="button in headerButtons"
82 :key="button.id"
83 size="small"
84 :to="button.to"
85 :is-disabled="isDisabled"
86 :variant="button.variant"
87 :target="button.to ? '_blank' : undefined"
88 :icon-append="
89 button.to ? 'icon-launch' : undefined
90 "
91 >
92 {{ button.text }}
93 </Button>
94 </div>
95 </div>
96 <div
97 v-if="warning"
98 class="hostinger-notice d-flex align-items-center w-100 mt-3"
99 >
100 <Icon
101 name="icon-info"
102 color="gray-dark"
103 />
104 <p class="text-body-3">
105 {{ warning }}
106 </p>
107 </div>
108 </div>
109 </template>
110 <div
111 v-for="item in sectionItems"
112 :key="item.title"
113 class="home-section__section-item"
114 :class="{
115 'home-section__section-item--disabled':
116 headerToggle && !headerToggle.value,
117 }"
118 >
119 <div class="d-flex flex-direction-column">
120 <div class="d-flex align-items-center w-100">
121 <Toggle
122 v-if="item.toggleValue !== undefined"
123 class="h-mr-16"
124 :model-value="Boolean(item.toggleValue)"
125 :bind="false"
126 :is-disabled="
127 (headerToggle && !headerToggle.value) ||
128 isDisabled
129 "
130 @click="
131 emit(
132 'save-section',
133 Boolean(!item.toggleValue),
134 item,
135 )
136 "
137 />
138 <div class="d-flex flex-column flex-grow-1">
139 <h3 class="h-m-0">
140 {{ item.title }}
141 </h3>
142 <p class="h-m-0 text-body-2">
143 {{ item.description }}
144 <template v-if="item.learnMoreLink">
145 <a
146 :href="item.learnMoreLink"
147 target="_blank"
148 rel="noopener"
149 class="text-link-2 additional-link"
150 >
151 {{
152 translate(
153 "hostinger_tools_llms_txt_learn_more",
154 )
155 }}
156 </a>
157 </template>
158 </p>
159 </div>
160 <div
161 v-if="
162 item.sideButtons?.length ||
163 item.sideButton?.text
164 "
165 class="d-flex align-items-center h-ml-16 section-buttons"
166 >
167 <Button
168 v-for="(button, index) in item.sideButtons"
169 :key="`${item.title}-${button.id || index}`"
170 size="small"
171 :variant="button.variant || 'text'"
172 :to="button.to"
173 :target="button.to ? '_blank' : undefined"
174 :icon-append="button.icon || 'icon-launch'"
175 :is-disabled="button.isDisabled || isDisabled"
176 color="primary"
177 @click="button.onClick"
178 >
179 {{ button.text }}
180 </Button>
181
182 <Button
183 v-if="
184 item.sideButton?.text &&
185 !item.sideButtons?.length
186 "
187 size="small"
188 variant="text"
189 :is-disabled="
190 isDisabled ||
191 item.sideButton?.isDisabled ||
192 item.sideButton?.isLoading
193 "
194 :is-loading="item.sideButton?.isLoading"
195 @click="item.sideButton?.onClick"
196 >
197 {{ item.sideButton?.text }}
198 </Button>
199 </div>
200 </div>
201 </div>
202 <CopyField
203 v-if="item.copyLink"
204 class="h-mt-16"
205 :link="item.copyLink"
206 />
207 </div>
208 </Card>
209 </div>
210 </template>
211
212 <style lang="scss">
213 .home-section {
214 &__section-item {
215 display: flex;
216 flex-direction: column;
217 margin-top: 16px;
218 padding-bottom: 16px;
219 border-bottom: 1px solid var(--gray-border);
220
221 &:last-child {
222 margin-bottom: 0;
223 padding-bottom: 0;
224 border-bottom: none;
225 }
226
227 &--disabled {
228 opacity: 0.5;
229 pointer-events: none;
230 }
231
232 .additional-link {
233 text-decoration: none !important;
234 }
235 }
236
237 .section-buttons {
238 gap: 8px;
239 }
240 }
241
242 .hostinger-notice {
243 background: var(--gray-light);
244 color: var(--gray-dark);
245 border: 1px solid var(--gray-border);
246 border-radius: 12px;
247 padding: 12px 16px;
248 font-size: var(--font-size-sm);
249 gap: 1em;
250 }
251 </style>
252