negodesign 0.0.34 → 0.0.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/core/card/product/01/CardProduct01.svelte +130 -0
- package/dist/components/core/card/product/01/CardProduct01.svelte.d.ts +4 -0
- package/dist/components/core/card/product/02/CardProduct02.svelte +118 -0
- package/dist/components/core/card/product/02/CardProduct02.svelte.d.ts +4 -0
- package/dist/components/core/card/product/CardProduct.svelte +22 -0
- package/dist/components/core/card/product/CardProduct.svelte.d.ts +11 -0
- package/dist/components/core/card/product/data.d.ts +3 -0
- package/dist/components/core/card/product/data.js +89 -0
- package/dist/components/core/card/profile/01/CardProfile01.svelte +3 -5
- package/dist/components/core/card/profile/02/CardProfile02.svelte +8 -17
- package/dist/components/core/card/promotion/CardPromotion.svelte +1 -1
- package/dist/components/core/card/promotion/CardPromotionPrice.svelte.d.ts +8 -0
- package/dist/components/core/card/shared/CardPhoneOrWhatsapp.svelte +14 -7
- package/dist/components/core/card/shared/CardTags.svelte +49 -24
- package/dist/components/core/card/shared/CardTitlePrice.svelte +24 -0
- package/dist/components/core/card/shared/CardTitlePrice.svelte.d.ts +15 -0
- package/dist/components/core/card/shared/TruncatableText.svelte +1 -1
- package/dist/components/core/card/types.d.ts +48 -0
- package/dist/components/core/carousel/grid/product/types.d.ts +22 -0
- package/dist/components/core/carousel/grid/product/types.js +1 -0
- package/dist/components/core/carousel/grid/product/ui/CarouselGridProduct.svelte +61 -0
- package/dist/components/core/carousel/grid/product/ui/CarouselGridProduct.svelte.d.ts +4 -0
- package/dist/components/core/carousel/grid/promotion/types.d.ts +23 -0
- package/dist/components/core/carousel/grid/promotion/types.js +1 -0
- package/dist/components/core/carousel/grid/promotion/ui/CarouselGridPromotion.svelte +50 -0
- package/dist/components/core/carousel/grid/promotion/ui/CarouselGridPromotion.svelte.d.ts +4 -0
- package/dist/components/core/carousel/product/types.d.ts +21 -0
- package/dist/components/core/carousel/product/types.js +1 -0
- package/dist/components/core/carousel/product/ui/CarouselProduct.svelte +47 -0
- package/dist/components/core/carousel/product/ui/CarouselProduct.svelte.d.ts +4 -0
- package/dist/components/pages/company-profile/CompanyProfile.svelte +140 -0
- package/dist/components/pages/company-profile/CompanyProfile.svelte.d.ts +4 -0
- package/dist/components/pages/company-profile/data.d.ts +2 -0
- package/dist/components/pages/company-profile/data.js +68 -0
- package/dist/components/pages/company-profile/shared/ProfileAboutCompany.svelte +79 -0
- package/dist/components/pages/company-profile/shared/ProfileAboutCompany.svelte.d.ts +9 -0
- package/dist/components/pages/company-profile/shared/ProfileBanner.svelte +194 -0
- package/dist/components/pages/company-profile/shared/ProfileBanner.svelte.d.ts +14 -0
- package/dist/components/pages/company-profile/shared/ProfileGallery.svelte +198 -0
- package/dist/components/pages/company-profile/shared/ProfileGallery.svelte.d.ts +9 -0
- package/dist/components/pages/company-profile/shared/ProfileMenuBadge.svelte +56 -0
- package/dist/components/pages/company-profile/shared/ProfileMenuBadge.svelte.d.ts +11 -0
- package/dist/components/pages/company-profile/shared/ProfileSidebar.svelte +57 -0
- package/dist/components/pages/company-profile/shared/ProfileSidebar.svelte.d.ts +11 -0
- package/dist/components/pages/company-profile/types.d.ts +117 -0
- package/dist/components/pages/company-profile/types.js +1 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/data.d.ts +3 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/data.js +179 -0
- package/dist/components/pages/privacy-policy-or-terms-of-use/shared/DocSectionView.svelte +2 -1
- package/dist/components/pages/privacy-policy-or-terms-of-use/shared/DocSectionView.svelte.d.ts +1 -0
- package/dist/components/pages/product-details/01/ProductDetails01.svelte +19 -7
- package/dist/components/pages/product-details/02/ProductDetails02.svelte +42 -37
- package/dist/components/pages/product-details/03/ProductDetails03.svelte +33 -29
- package/dist/components/pages/product-details/ProductDetails.svelte +11 -7
- package/dist/components/pages/product-details/shared/ProductDetailFeatures.svelte +11 -5
- package/dist/components/pages/product-details/shared/ProductDetailFeatures.svelte.d.ts +2 -1
- package/dist/components/pages/product-details/shared/ProductDetailFilesVertical.svelte +52 -20
- package/dist/components/pages/product-details/shared/ProductDetailFilesVertical.svelte.d.ts +1 -1
- package/dist/components/pages/product-details/shared/ProductDetailImage.svelte +51 -20
- package/dist/components/pages/product-details/shared/ProductDetailImage.svelte.d.ts +1 -1
- package/dist/components/pages/product-details/shared/ProductDetailPrice.svelte +1 -1
- package/dist/components/pages/product-details/types.d.ts +9 -2
- package/dist/components/pages/profile-user/types.d.ts +7 -0
- package/dist/globals.css +244 -8
- package/dist/i18n/langs/en.d.ts +10 -0
- package/dist/i18n/langs/en.js +10 -0
- package/dist/i18n/langs/pt.d.ts +10 -0
- package/dist/i18n/langs/pt.js +10 -0
- package/dist/i18n/translations.d.ts +20 -0
- package/package.json +1 -1
- package/dist/components/core/card/shared/CardStartPrice.svelte.d.ts +0 -8
- package/dist/components/pages/product-details/04/ProductDetails04.svelte +0 -65
- package/dist/components/pages/product-details/04/ProductDetails04.svelte.d.ts +0 -11
- /package/dist/components/core/card/{shared/CardStartPrice.svelte → promotion/CardPromotionPrice.svelte} +0 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Button from "../../../../ui/button/button.svelte";
|
|
3
|
+
import Skeleton from "../../../../ui/skeleton/skeleton.svelte";
|
|
4
|
+
import { t } from "../../../../../i18n";
|
|
5
|
+
import ImgPlaceHolderGallery from "../../../../../assets/placeholder-image.png";
|
|
6
|
+
import ImgPlaceholderCompany from "../../../../../assets/placeholder-company.png";
|
|
7
|
+
import type { CardProductProps } from "../../types";
|
|
8
|
+
import CardFavorite from "../../shared/CardFavorite.svelte";
|
|
9
|
+
import CardCart from "../../shared/CardCart.svelte";
|
|
10
|
+
import CardDescription from "../../shared/CardDescription.svelte";
|
|
11
|
+
import CardTags from "../../shared/CardTags.svelte";
|
|
12
|
+
import CardTitlePrice from "../../shared/CardTitlePrice.svelte";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Card component with a title and content.
|
|
16
|
+
* @component
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
let {
|
|
20
|
+
id,
|
|
21
|
+
tags,
|
|
22
|
+
logo,
|
|
23
|
+
title,
|
|
24
|
+
imageUrl,
|
|
25
|
+
rating = 0,
|
|
26
|
+
isFavorite = false,
|
|
27
|
+
isCart = false,
|
|
28
|
+
isLoading = false,
|
|
29
|
+
content,
|
|
30
|
+
price,
|
|
31
|
+
buttonBuyText,
|
|
32
|
+
buttonBuyClass,
|
|
33
|
+
isDescriptionIcon,
|
|
34
|
+
isDescriptionLabel,
|
|
35
|
+
onClickBuy,
|
|
36
|
+
onClickShop,
|
|
37
|
+
onClickFavorite,
|
|
38
|
+
}: CardProductProps = $props();
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<article class="relative rounded-lg border">
|
|
42
|
+
<aside class="relative w-full p-2">
|
|
43
|
+
<div class="absolute top-2 left-2 z-2 gap-1 p-2">
|
|
44
|
+
{#if isLoading}
|
|
45
|
+
<Skeleton class="h-5 w-20 rounded-full bg-black/20" />
|
|
46
|
+
{:else if logo}
|
|
47
|
+
<img
|
|
48
|
+
src={logo}
|
|
49
|
+
width={30}
|
|
50
|
+
height={30}
|
|
51
|
+
alt={title}
|
|
52
|
+
onerror={(e) =>
|
|
53
|
+
((e.target as HTMLImageElement).src = ImgPlaceholderCompany)}
|
|
54
|
+
class="rounded-lg"
|
|
55
|
+
/>
|
|
56
|
+
{:else}
|
|
57
|
+
<img
|
|
58
|
+
src={ImgPlaceholderCompany}
|
|
59
|
+
width={30}
|
|
60
|
+
height={30}
|
|
61
|
+
alt={title}
|
|
62
|
+
class="rounded-lg"
|
|
63
|
+
/>
|
|
64
|
+
{/if}
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<div class="absolute top-2 right-2 z-2 flex items-center gap-1 p-2">
|
|
68
|
+
<CardFavorite
|
|
69
|
+
{id}
|
|
70
|
+
{isFavorite}
|
|
71
|
+
{isLoading}
|
|
72
|
+
onFavoriteClick={onClickFavorite}
|
|
73
|
+
/>
|
|
74
|
+
<CardCart {id} {isCart} {isLoading} onCartClick={onClickShop} />
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
{#if isLoading}
|
|
78
|
+
<Skeleton
|
|
79
|
+
class="rounded-lg h-30 w-full object-cover object-center bg-black/15"
|
|
80
|
+
/>
|
|
81
|
+
{:else if imageUrl}
|
|
82
|
+
<img
|
|
83
|
+
src={imageUrl}
|
|
84
|
+
alt={imageUrl}
|
|
85
|
+
class="rounded-lg h-36 md:h-44 w-full object-cover object-center"
|
|
86
|
+
onerror={(e) =>
|
|
87
|
+
((e.target as HTMLImageElement).src = ImgPlaceHolderGallery)}
|
|
88
|
+
/>
|
|
89
|
+
{/if}
|
|
90
|
+
<div class="absolute inset-0 bg-black/5 rounded-sm h-full w-full"></div>
|
|
91
|
+
</aside>
|
|
92
|
+
|
|
93
|
+
<aside
|
|
94
|
+
class="bottom-1 inset-x-0 flex flex-col items-center justify-center gap-0.5 m-auto max-w-11/12 p-1 rounded-md"
|
|
95
|
+
>
|
|
96
|
+
<div class="flex justify-between w-full items-center mb-1">
|
|
97
|
+
{#if title}
|
|
98
|
+
{#if isLoading}
|
|
99
|
+
<Skeleton class="h-4 w-30 rounded-lg" />
|
|
100
|
+
{:else}
|
|
101
|
+
<div class="font-semibold line-clamp-1 flex-nowrap">
|
|
102
|
+
{title}
|
|
103
|
+
</div>
|
|
104
|
+
{/if}
|
|
105
|
+
{/if}
|
|
106
|
+
<CardTitlePrice {title} {isLoading} {price} />
|
|
107
|
+
</div>
|
|
108
|
+
|
|
109
|
+
{#if tags && tags.length > 0}
|
|
110
|
+
<div class="w-full my-1">
|
|
111
|
+
<CardTags {tags} />
|
|
112
|
+
</div>
|
|
113
|
+
{/if}
|
|
114
|
+
|
|
115
|
+
<div>
|
|
116
|
+
<CardDescription {content} {isDescriptionIcon} {isDescriptionLabel} />
|
|
117
|
+
</div>
|
|
118
|
+
|
|
119
|
+
{#if isLoading}
|
|
120
|
+
<Skeleton class="h-9 w-full rounded-md" />
|
|
121
|
+
{:else}
|
|
122
|
+
<Button
|
|
123
|
+
onclick={() => onClickBuy!(id)}
|
|
124
|
+
class="w-full mb-2 bg-gradient text-white rounded-full {buttonBuyClass}"
|
|
125
|
+
>
|
|
126
|
+
{buttonBuyText || $t("label.buy")}
|
|
127
|
+
</Button>
|
|
128
|
+
{/if}
|
|
129
|
+
</aside>
|
|
130
|
+
</article>
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Button from "../../../../ui/button/button.svelte";
|
|
3
|
+
import Skeleton from "../../../../ui/skeleton/skeleton.svelte";
|
|
4
|
+
import { t } from "../../../../../i18n";
|
|
5
|
+
import ImgPlaceHolderGallery from "../../../../../assets/placeholder-image.png";
|
|
6
|
+
import ImgPlaceholderCompany from "../../../../../assets/placeholder-company.png";
|
|
7
|
+
import type { CardProductProps } from "../../types";
|
|
8
|
+
import CardFavorite from "../../shared/CardFavorite.svelte";
|
|
9
|
+
import CardCart from "../../shared/CardCart.svelte";
|
|
10
|
+
import CardDescription from "../../shared/CardDescription.svelte";
|
|
11
|
+
import CardTags from "../../shared/CardTags.svelte";
|
|
12
|
+
import CardTitlePrice from "../../shared/CardTitlePrice.svelte";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Card component with a title and content.
|
|
16
|
+
* @component
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
let {
|
|
20
|
+
id,
|
|
21
|
+
tags,
|
|
22
|
+
logo,
|
|
23
|
+
title,
|
|
24
|
+
imageUrl,
|
|
25
|
+
isFavorite = false,
|
|
26
|
+
isCart = false,
|
|
27
|
+
isLoading = false,
|
|
28
|
+
content,
|
|
29
|
+
price,
|
|
30
|
+
buttonBuyText,
|
|
31
|
+
buttonBuyClass,
|
|
32
|
+
isDescriptionIcon,
|
|
33
|
+
isDescriptionLabel,
|
|
34
|
+
onClickBuy,
|
|
35
|
+
onClickShop,
|
|
36
|
+
onClickFavorite,
|
|
37
|
+
}: CardProductProps = $props();
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<article class="relative rounded-lg border">
|
|
41
|
+
<aside class="relative w-full">
|
|
42
|
+
<div class="absolute top-1 left-1 z-2 gap-1 p-2">
|
|
43
|
+
{#if isLoading}
|
|
44
|
+
<Skeleton class="h-5 w-20 rounded-full bg-black/20" />
|
|
45
|
+
{:else if logo}
|
|
46
|
+
<img
|
|
47
|
+
src={logo}
|
|
48
|
+
width={30}
|
|
49
|
+
height={30}
|
|
50
|
+
alt={title}
|
|
51
|
+
onerror={(e) =>
|
|
52
|
+
((e.target as HTMLImageElement).src = ImgPlaceholderCompany)}
|
|
53
|
+
class="rounded-lg"
|
|
54
|
+
/>
|
|
55
|
+
{:else}
|
|
56
|
+
<img
|
|
57
|
+
src={ImgPlaceholderCompany}
|
|
58
|
+
width={30}
|
|
59
|
+
height={30}
|
|
60
|
+
alt={title}
|
|
61
|
+
class="rounded-lg"
|
|
62
|
+
/>
|
|
63
|
+
{/if}
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<div class="absolute top-1 right-1 z-2 flex items-center gap-1 p-2">
|
|
67
|
+
<CardFavorite
|
|
68
|
+
{id}
|
|
69
|
+
{isFavorite}
|
|
70
|
+
{isLoading}
|
|
71
|
+
onFavoriteClick={onClickFavorite}
|
|
72
|
+
/>
|
|
73
|
+
<CardCart {id} {isCart} {isLoading} onCartClick={onClickShop} />
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
{#if isLoading}
|
|
77
|
+
<Skeleton
|
|
78
|
+
class="rounded-lg h-30 w-full object-cover object-center bg-black/15"
|
|
79
|
+
/>
|
|
80
|
+
{:else if imageUrl}
|
|
81
|
+
<img
|
|
82
|
+
src={imageUrl}
|
|
83
|
+
alt={imageUrl}
|
|
84
|
+
class="rounded-tr-lg rounded-tl-lg h-36 md:h-44 w-full object-cover object-center"
|
|
85
|
+
onerror={(e) =>
|
|
86
|
+
((e.target as HTMLImageElement).src = ImgPlaceHolderGallery)}
|
|
87
|
+
/>
|
|
88
|
+
{/if}
|
|
89
|
+
<div class="absolute inset-0 bg-black/5 rounded-sm h-full w-full"></div>
|
|
90
|
+
</aside>
|
|
91
|
+
|
|
92
|
+
<aside
|
|
93
|
+
class="bottom-1 inset-x-0 flex flex-col items-center justify-center gap-0.5 m-auto max-w-11/12 p-1 rounded-md"
|
|
94
|
+
>
|
|
95
|
+
<CardTitlePrice {title} {isLoading} {price} />
|
|
96
|
+
|
|
97
|
+
<div>
|
|
98
|
+
<CardDescription {content} {isDescriptionIcon} {isDescriptionLabel} />
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
{#if tags && tags.length > 0}
|
|
102
|
+
<div class="w-full mb-2">
|
|
103
|
+
<CardTags {tags} />
|
|
104
|
+
</div>
|
|
105
|
+
{/if}
|
|
106
|
+
|
|
107
|
+
{#if isLoading}
|
|
108
|
+
<Skeleton class="h-9 w-full rounded-md" />
|
|
109
|
+
{:else}
|
|
110
|
+
<Button
|
|
111
|
+
onclick={() => onClickBuy!(id)}
|
|
112
|
+
class="w-full bottom-0 bg-gradient {buttonBuyClass}"
|
|
113
|
+
>
|
|
114
|
+
{buttonBuyText || $t("label.buy")}
|
|
115
|
+
</Button>
|
|
116
|
+
{/if}
|
|
117
|
+
</aside>
|
|
118
|
+
</article>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Card component with a title and content.
|
|
4
|
+
* @component
|
|
5
|
+
*/
|
|
6
|
+
import type { CardProductProps } from "../types";
|
|
7
|
+
import CardProduct01 from "./01/CardProduct01.svelte";
|
|
8
|
+
import CardProduct02 from "./02/CardProduct02.svelte";
|
|
9
|
+
|
|
10
|
+
let {
|
|
11
|
+
variant,
|
|
12
|
+
...restProps
|
|
13
|
+
}: CardProductProps & {
|
|
14
|
+
variant?: 1 | 2;
|
|
15
|
+
} = $props();
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
{#if variant === 2}
|
|
19
|
+
<CardProduct02 {...restProps} />
|
|
20
|
+
{:else}
|
|
21
|
+
<CardProduct01 {...restProps} />
|
|
22
|
+
{/if}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Card component with a title and content.
|
|
3
|
+
* @component
|
|
4
|
+
*/
|
|
5
|
+
import type { CardProductProps } from "../types";
|
|
6
|
+
type $$ComponentProps = CardProductProps & {
|
|
7
|
+
variant?: 1 | 2;
|
|
8
|
+
};
|
|
9
|
+
declare const CardProduct: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
10
|
+
type CardProduct = ReturnType<typeof CardProduct>;
|
|
11
|
+
export default CardProduct;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { GlobalIcon, MapPin, NecklaceIcon } from "@hugeicons/core-free-icons";
|
|
2
|
+
const items = [
|
|
3
|
+
{
|
|
4
|
+
id: 1,
|
|
5
|
+
imageUrl: "https://images.unsplash.com/photo-1507525428034-b723cf961d3e?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
|
6
|
+
title: "Hotel Baía Azul",
|
|
7
|
+
content: "Acomodação premium de frente para o mar com quartos luxuosos, restaurante internacional, piscina aquecida e serviço de transfer exclusivo para hóspedes.",
|
|
8
|
+
isFavorite: true,
|
|
9
|
+
price: "45.000 Kz",
|
|
10
|
+
buttonBuyText: "Comprar",
|
|
11
|
+
onClickBuy: (id) => alert(`Comprar produto ${id}`),
|
|
12
|
+
onClickShop: (id) => alert(`Adicionar ao carrinho ${id}`),
|
|
13
|
+
isCart: true,
|
|
14
|
+
tags: [
|
|
15
|
+
{ icon: GlobalIcon, text: "Luanda" },
|
|
16
|
+
{ icon: MapPin, text: "Ilha do Cabo" },
|
|
17
|
+
{ icon: NecklaceIcon, text: "Frente ao Mar" },
|
|
18
|
+
],
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
id: 2,
|
|
22
|
+
imageUrl: "https://images.unsplash.com/photo-1566073771259-6a8506099945?q=80&w=1170&auto=format&fit=crop",
|
|
23
|
+
title: "Miramar Suites",
|
|
24
|
+
content: "Suítes executivas com vista panorâmica da baía, internet de alta velocidade, pequeno-almoço buffet incluído e centro de conferências moderno.",
|
|
25
|
+
isFavorite: false,
|
|
26
|
+
price: "38.500 Kz",
|
|
27
|
+
buttonBuyText: "Comprar",
|
|
28
|
+
onClickBuy: (id) => alert(`Comprar produto ${id}`),
|
|
29
|
+
onClickShop: (id) => alert(`Adicionar ao carrinho ${id}`),
|
|
30
|
+
isCart: true,
|
|
31
|
+
tags: [
|
|
32
|
+
{ icon: GlobalIcon, text: "Luanda" },
|
|
33
|
+
{ icon: MapPin, text: "Miramar" },
|
|
34
|
+
{ icon: NecklaceIcon, text: "Executivo" },
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: 3,
|
|
39
|
+
imageUrl: "https://images.unsplash.com/photo-1582719478250-c89cae4dc85b?q=80&w=1170&auto=format&fit=crop",
|
|
40
|
+
title: "Palm Resort & Spa",
|
|
41
|
+
content: "Resort paradisíaco rodeado por palmeiras com spa completo, campos de ténis, atividades infantis e acesso privativo à praia.",
|
|
42
|
+
isFavorite: true,
|
|
43
|
+
price: "52.000 Kz",
|
|
44
|
+
buttonBuyText: "Comprar",
|
|
45
|
+
onClickBuy: (id) => alert(`Comprar produto ${id}`),
|
|
46
|
+
onClickShop: (id) => alert(`Adicionar ao carrinho ${id}`),
|
|
47
|
+
isCart: true,
|
|
48
|
+
tags: [
|
|
49
|
+
{ icon: GlobalIcon, text: "Benguela" },
|
|
50
|
+
{ icon: MapPin, text: "Baía Farta" },
|
|
51
|
+
{ icon: NecklaceIcon, text: "Spa & Lazer" },
|
|
52
|
+
],
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: 4,
|
|
56
|
+
imageUrl: "https://images.unsplash.com/photo-1542314831-068cd1dbfeeb?q=80&w=1170&auto=format&fit=crop",
|
|
57
|
+
title: "Hotel Central Park",
|
|
58
|
+
content: "Localização privilegiada no coração financeiro da cidade, perfeito para viagens de negócios e turismo cultural.",
|
|
59
|
+
isFavorite: false,
|
|
60
|
+
price: "29.900 Kz",
|
|
61
|
+
buttonBuyText: "Comprar",
|
|
62
|
+
onClickBuy: (id) => alert(`Comprar produto ${id}`),
|
|
63
|
+
onClickShop: (id) => alert(`Adicionar ao carrinho ${id}`),
|
|
64
|
+
isCart: true,
|
|
65
|
+
tags: [
|
|
66
|
+
{ icon: GlobalIcon, text: "Huambo" },
|
|
67
|
+
{ icon: MapPin, text: "Centro" },
|
|
68
|
+
{ icon: NecklaceIcon, text: "Urbano" },
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
id: 5,
|
|
73
|
+
imageUrl: "https://images.unsplash.com/photo-1571896349842-33c89424de2d?q=80&w=1170&auto=format&fit=crop",
|
|
74
|
+
title: "Villa Serena Boutique",
|
|
75
|
+
content: "Charme e tranquilidade num ambiente intimista com arquitetura rústica, piscina infinita e gastronomia regional selecionada.",
|
|
76
|
+
isFavorite: true,
|
|
77
|
+
price: "60.000 Kz",
|
|
78
|
+
buttonBuyText: "Comprar",
|
|
79
|
+
onClickBuy: (id) => alert(`Comprar produto ${id}`),
|
|
80
|
+
onClickShop: (id) => alert(`Adicionar ao carrinho ${id}`),
|
|
81
|
+
isCart: true,
|
|
82
|
+
tags: [
|
|
83
|
+
{ icon: GlobalIcon, text: "Namibe" },
|
|
84
|
+
{ icon: MapPin, text: "Praia Amélia" },
|
|
85
|
+
{ icon: NecklaceIcon, text: "Boutique" },
|
|
86
|
+
],
|
|
87
|
+
},
|
|
88
|
+
];
|
|
89
|
+
export default items;
|
|
@@ -18,8 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
let {
|
|
20
20
|
id,
|
|
21
|
-
tags,
|
|
22
|
-
logo,
|
|
21
|
+
tags = [],
|
|
23
22
|
title,
|
|
24
23
|
content,
|
|
25
24
|
startNumber,
|
|
@@ -45,7 +44,7 @@
|
|
|
45
44
|
class="border border-gray-300 dark:border-gray-700 bg-gray-100 dark:bg-transparent rounded-lg relative"
|
|
46
45
|
>
|
|
47
46
|
<div class="p-5">
|
|
48
|
-
<div class="flex justify-between items-center w-full">
|
|
47
|
+
<div class="flex justify-between items-center w-full border-b-2">
|
|
49
48
|
<div class="w-full flex flex-col justify-center items-center relative">
|
|
50
49
|
<div>
|
|
51
50
|
{#if isLoading}
|
|
@@ -94,12 +93,11 @@
|
|
|
94
93
|
{isLoading}
|
|
95
94
|
{isDescriptionIcon}
|
|
96
95
|
{isDescriptionLabel}
|
|
97
|
-
lines={tags?.length == 0 ? 3 : 2}
|
|
98
96
|
/>
|
|
99
97
|
</div>
|
|
100
98
|
|
|
101
99
|
<CardTags
|
|
102
|
-
className="
|
|
100
|
+
className="mb-2"
|
|
103
101
|
tags={tags ?? []}
|
|
104
102
|
{isTagBorderBottom}
|
|
105
103
|
{isLoading}
|
|
@@ -18,8 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
let {
|
|
20
20
|
id,
|
|
21
|
-
tags,
|
|
22
|
-
logo,
|
|
21
|
+
tags = [],
|
|
23
22
|
title,
|
|
24
23
|
content,
|
|
25
24
|
className,
|
|
@@ -92,24 +91,16 @@
|
|
|
92
91
|
{isLoading}
|
|
93
92
|
{isDescriptionLabel}
|
|
94
93
|
{isDescriptionIcon}
|
|
94
|
+
lines={tags.length == 0 ? 3 : 2}
|
|
95
95
|
/>
|
|
96
96
|
</div>
|
|
97
97
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
/>
|
|
105
|
-
{:else}
|
|
106
|
-
<CardTags
|
|
107
|
-
className="my-4"
|
|
108
|
-
tags={[{ text: "- - -" }]}
|
|
109
|
-
{isTagBorderBottom}
|
|
110
|
-
{isLoading}
|
|
111
|
-
/>
|
|
112
|
-
{/if}
|
|
98
|
+
<CardTags
|
|
99
|
+
className="my-2"
|
|
100
|
+
tags={tags ?? []}
|
|
101
|
+
{isTagBorderBottom}
|
|
102
|
+
{isLoading}
|
|
103
|
+
/>
|
|
113
104
|
|
|
114
105
|
<CardThumbnailVideo
|
|
115
106
|
{imageUrl}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import CardCart from "../shared/CardCart.svelte";
|
|
6
6
|
import CardDescription from "../shared/CardDescription.svelte";
|
|
7
7
|
import CardFavorite from "../shared/CardFavorite.svelte";
|
|
8
|
-
import CardStartPrice from "
|
|
8
|
+
import CardStartPrice from "./CardPromotionPrice.svelte";
|
|
9
9
|
import CardTags from "../shared/CardTags.svelte";
|
|
10
10
|
import ImgPlaceHolderGallery from "../../../../assets/placeholder-image.png";
|
|
11
11
|
import ImgPlaceholderCompany from "../../../../assets/placeholder-company.png";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
newPrice?: string | number;
|
|
3
|
+
oldPrice?: string | number;
|
|
4
|
+
type?: "start" | "normal";
|
|
5
|
+
};
|
|
6
|
+
declare const CardPromotionPrice: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type CardPromotionPrice = ReturnType<typeof CardPromotionPrice>;
|
|
8
|
+
export default CardPromotionPrice;
|
|
@@ -3,18 +3,25 @@
|
|
|
3
3
|
import { HugeiconsIcon } from "@hugeicons/svelte";
|
|
4
4
|
import type { CardPhoneOrWhatsappProps } from "../types";
|
|
5
5
|
|
|
6
|
-
let {
|
|
7
|
-
|
|
6
|
+
let {
|
|
7
|
+
id,
|
|
8
|
+
className,
|
|
9
|
+
buttonClass,
|
|
10
|
+
btnWhatsappClass,
|
|
11
|
+
btnEmailClass,
|
|
12
|
+
onEmailClick,
|
|
13
|
+
onWhatsappClick,
|
|
14
|
+
}: CardPhoneOrWhatsappProps = $props();
|
|
8
15
|
|
|
9
16
|
let isFlex = $derived(onEmailClick && onWhatsappClick);
|
|
10
17
|
</script>
|
|
11
18
|
|
|
12
|
-
<div class="flex border-t border-gray-300 dark:border-gray-700">
|
|
19
|
+
<div class="flex border-t border-gray-300 dark:border-gray-700 {className}">
|
|
13
20
|
{#if onEmailClick}
|
|
14
21
|
<button
|
|
15
|
-
class="flex-1 flex justify-center items-center gap-2 p-3 hover:bg-red-800 hover:text-white cursor-pointer rounded-bl-lg {isFlex
|
|
22
|
+
class="flex-1 flex justify-center items-center gap-2 p-3 hover:bg-red-800 hover:text-white cursor-pointer rounded-bl-lg {!isFlex
|
|
16
23
|
? 'rounded-br-lg'
|
|
17
|
-
: ''}"
|
|
24
|
+
: ''} {buttonClass} {btnEmailClass}"
|
|
18
25
|
onclick={() => onEmailClick?.(id)}
|
|
19
26
|
>
|
|
20
27
|
<HugeiconsIcon icon={Mail01Icon} size={20} />
|
|
@@ -26,9 +33,9 @@
|
|
|
26
33
|
{/if}
|
|
27
34
|
{#if onWhatsappClick}
|
|
28
35
|
<button
|
|
29
|
-
class="flex-1 flex justify-center items-center gap-2 p-3 hover:bg-green-600 hover:text-white cursor-pointer rounded-br-lg {isFlex
|
|
36
|
+
class="flex-1 flex justify-center items-center gap-2 p-3 hover:bg-green-600 hover:text-white cursor-pointer rounded-br-lg {!isFlex
|
|
30
37
|
? 'rounded-bl-lg'
|
|
31
|
-
: ''}"
|
|
38
|
+
: ''} {buttonClass} {btnWhatsappClass}"
|
|
32
39
|
onclick={() => onWhatsappClick?.(id)}
|
|
33
40
|
>
|
|
34
41
|
<HugeiconsIcon icon={WhatsappIcon} size={20} />
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { HugeiconsIcon } from "@hugeicons/svelte";
|
|
3
3
|
import type { CardTagsProps } from "../types";
|
|
4
4
|
import Skeleton from "../../../ui/skeleton/skeleton.svelte";
|
|
5
|
+
import * as Popover from "../../../ui/popover"; // adjust path to your setup
|
|
5
6
|
|
|
6
7
|
type Props = {
|
|
7
8
|
className?: string;
|
|
@@ -20,13 +21,14 @@
|
|
|
20
21
|
}: Props = $props();
|
|
21
22
|
|
|
22
23
|
let isJustify = $derived(tags?.length == 2 || tags?.length == 3);
|
|
24
|
+
let open = $state(false);
|
|
23
25
|
</script>
|
|
24
26
|
|
|
25
|
-
{#snippet createBadge(tag: CardTagsProps)}
|
|
27
|
+
{#snippet createBadge(tag: CardTagsProps, clasName?: string)}
|
|
26
28
|
<div
|
|
27
29
|
class="flex items-center h-5 shrink-0 {isTagBorderBottom
|
|
28
30
|
? 'border border-gray-200 rounded-full px-2 py-1'
|
|
29
|
-
: ''}"
|
|
31
|
+
: ''} {clasName}"
|
|
30
32
|
>
|
|
31
33
|
{#if tag.icon}
|
|
32
34
|
<HugeiconsIcon icon={tag.icon} class="mr-0.5 h-3.75 w-3.75 shrink-0" />
|
|
@@ -43,28 +45,51 @@
|
|
|
43
45
|
</div>
|
|
44
46
|
{/snippet}
|
|
45
47
|
|
|
46
|
-
{#
|
|
47
|
-
|
|
48
|
-
{
|
|
49
|
-
{
|
|
50
|
-
|
|
51
|
-
{
|
|
52
|
-
{
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
48
|
+
{#snippet tagsRow()}
|
|
49
|
+
{#if isWrap}
|
|
50
|
+
<div class="flex flex-wrap gap-2 md:gap-5 {className}">
|
|
51
|
+
{#if isLoading}
|
|
52
|
+
{@render skeletonTag()}
|
|
53
|
+
{:else if tags && tags.length > 0}
|
|
54
|
+
{#each tags as tag, i (i)}
|
|
55
|
+
{@render createBadge(tag)}
|
|
56
|
+
{/each}
|
|
57
|
+
{/if}
|
|
58
|
+
</div>
|
|
59
|
+
{:else}
|
|
60
|
+
<div
|
|
61
|
+
class="flex overflow-x-auto no-scrollbar w-full min-w-0
|
|
62
|
+
{isJustify ? 'justify-between gap-3' : 'gap-4 md:gap-5 lg:gap-10'}
|
|
63
|
+
{className}"
|
|
64
|
+
>
|
|
65
|
+
{#if isLoading}
|
|
66
|
+
{@render skeletonTag()}
|
|
67
|
+
{:else if tags && tags.length > 0}
|
|
68
|
+
{#each tags as tag, i (i)}
|
|
69
|
+
{@render createBadge(tag)}
|
|
70
|
+
{/each}
|
|
71
|
+
{/if}
|
|
72
|
+
</div>
|
|
73
|
+
{/if}
|
|
74
|
+
{/snippet}
|
|
75
|
+
|
|
76
|
+
<Popover.Root bind:open>
|
|
77
|
+
<Popover.Trigger
|
|
78
|
+
onmouseenter={() => (open = true)}
|
|
79
|
+
onmouseleave={() => (open = false)}
|
|
80
|
+
class="block w-full text-left"
|
|
81
|
+
>
|
|
82
|
+
{@render tagsRow()}
|
|
83
|
+
</Popover.Trigger>
|
|
84
|
+
<Popover.Content
|
|
85
|
+
class="w-auto max-w-xs p-3"
|
|
86
|
+
onmouseenter={() => (open = true)}
|
|
87
|
+
onmouseleave={() => (open = false)}
|
|
61
88
|
>
|
|
62
|
-
|
|
63
|
-
{@render skeletonTag()}
|
|
64
|
-
{:else if tags && tags.length > 0}
|
|
89
|
+
<div class="flex flex-col gap-2">
|
|
65
90
|
{#each tags as tag, i (i)}
|
|
66
|
-
{@render createBadge(tag)}
|
|
91
|
+
{@render createBadge(tag, "gap-2")}
|
|
67
92
|
{/each}
|
|
68
|
-
|
|
69
|
-
</
|
|
70
|
-
|
|
93
|
+
</div>
|
|
94
|
+
</Popover.Content>
|
|
95
|
+
</Popover.Root>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import Skeleton from "../../../ui/skeleton/skeleton.svelte";
|
|
3
|
+
|
|
4
|
+
let { title, isLoading, price } = $props();
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<div class="flex justify-between w-full items-center">
|
|
8
|
+
{#if title}
|
|
9
|
+
{#if isLoading}
|
|
10
|
+
<Skeleton class="h-4 w-30 rounded-lg" />
|
|
11
|
+
{:else}
|
|
12
|
+
<div class="font-semibold line-clamp-1 flex-nowrap">
|
|
13
|
+
{title}
|
|
14
|
+
</div>
|
|
15
|
+
{/if}
|
|
16
|
+
{/if}
|
|
17
|
+
<div class="flex justify-start gap-2">
|
|
18
|
+
{#if isLoading}
|
|
19
|
+
<Skeleton class="h-5 bg-black/10 w-25 my-2 mr-2" />
|
|
20
|
+
{:else if price}
|
|
21
|
+
<div class="text-lg font-semibold text-primary">{price}</div>
|
|
22
|
+
{/if}
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export default CardTitlePrice;
|
|
2
|
+
type CardTitlePrice = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
|
+
};
|
|
6
|
+
declare const CardTitlePrice: import("svelte").Component<{
|
|
7
|
+
title: any;
|
|
8
|
+
isLoading: any;
|
|
9
|
+
price: any;
|
|
10
|
+
}, {}, "">;
|
|
11
|
+
type $$ComponentProps = {
|
|
12
|
+
title: any;
|
|
13
|
+
isLoading: any;
|
|
14
|
+
price: any;
|
|
15
|
+
};
|