diff --git a/components/features/community-poi/CommunityPoiBluemap.vue b/components/features/community-poi/CommunityPoiBluemap.vue
new file mode 100644
index 0000000..24505f1
--- /dev/null
+++ b/components/features/community-poi/CommunityPoiBluemap.vue
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('community_poi.bluemap.embed_note', { host: baseUrl }) }}
+
+
+
+
diff --git a/components/features/community-poi/CommunityPoiCard.vue b/components/features/community-poi/CommunityPoiCard.vue
new file mode 100644
index 0000000..f5afbe4
--- /dev/null
+++ b/components/features/community-poi/CommunityPoiCard.vue
@@ -0,0 +1,141 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('community_poi.card.showcase_only') }}
+
+
+
+
+
+
+
+
+ {{ poi.title }}
+
+
+
+ {{ poi.location }}
+
+
+
+
+ {{ poi.summary }}
+
+
+
+
+
+
+
+
diff --git a/components/features/community-poi/CommunityPoiCategoryBadge.vue b/components/features/community-poi/CommunityPoiCategoryBadge.vue
new file mode 100644
index 0000000..0ad6572
--- /dev/null
+++ b/components/features/community-poi/CommunityPoiCategoryBadge.vue
@@ -0,0 +1,62 @@
+
+
+
+
+
+ {{ label }}
+
+
diff --git a/components/features/community-poi/CommunityPoiCollaboration.vue b/components/features/community-poi/CommunityPoiCollaboration.vue
new file mode 100644
index 0000000..26d7bb8
--- /dev/null
+++ b/components/features/community-poi/CommunityPoiCollaboration.vue
@@ -0,0 +1,102 @@
+
+
+
+
+
diff --git a/components/features/community-poi/CommunityPoiContributeInfo.vue b/components/features/community-poi/CommunityPoiContributeInfo.vue
new file mode 100644
index 0000000..3c504da
--- /dev/null
+++ b/components/features/community-poi/CommunityPoiContributeInfo.vue
@@ -0,0 +1,71 @@
+
+
+
+
+
diff --git a/components/features/community-poi/CommunityPoiCoordsCopy.vue b/components/features/community-poi/CommunityPoiCoordsCopy.vue
new file mode 100644
index 0000000..c8a4aac
--- /dev/null
+++ b/components/features/community-poi/CommunityPoiCoordsCopy.vue
@@ -0,0 +1,96 @@
+
+
+
+
+
+
+
+
diff --git a/components/features/community-poi/CommunityPoiGallery.vue b/components/features/community-poi/CommunityPoiGallery.vue
new file mode 100644
index 0000000..1147da5
--- /dev/null
+++ b/components/features/community-poi/CommunityPoiGallery.vue
@@ -0,0 +1,199 @@
+
+
+
+
+
+ -
+
+
+ {{ img.caption }}
+
+
+
+
+
+
+
+
+ {{ activeIndex + 1 }} / {{ images.length }}
+
+
+
+
+
+
+
+ {{ activeImage.caption }}
+
+
+
+
+
+
+
+
diff --git a/components/features/community-poi/CommunityPoiGoalState.vue b/components/features/community-poi/CommunityPoiGoalState.vue
new file mode 100644
index 0000000..f4abd24
--- /dev/null
+++ b/components/features/community-poi/CommunityPoiGoalState.vue
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+ {{ t('community_poi.goal_state.goal') }}
+
+ {{ goal }}
+
+
+
+ {{ t('community_poi.goal_state.current') }}
+
+ {{ currentState }}
+
+
+
diff --git a/components/features/community-poi/CommunityPoiGrid.vue b/components/features/community-poi/CommunityPoiGrid.vue
new file mode 100644
index 0000000..75f2a1f
--- /dev/null
+++ b/components/features/community-poi/CommunityPoiGrid.vue
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+ {{ t('community_poi.overview.empty') }}
+
+
+
diff --git a/components/features/community-poi/CommunityPoiLitematicaHelp.vue b/components/features/community-poi/CommunityPoiLitematicaHelp.vue
new file mode 100644
index 0000000..b8ca9a1
--- /dev/null
+++ b/components/features/community-poi/CommunityPoiLitematicaHelp.vue
@@ -0,0 +1,132 @@
+
+
+
+
+
+
+
+
+
+ -
+
+
+ {{ entry.q }}
+
+
+
+
+
+
+
+
diff --git a/components/features/community-poi/CommunityPoiLore.vue b/components/features/community-poi/CommunityPoiLore.vue
new file mode 100644
index 0000000..d42c4a2
--- /dev/null
+++ b/components/features/community-poi/CommunityPoiLore.vue
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+ {{ t('community_poi.lore.title') }}
+
+ {{ lore }}
+
+
diff --git a/components/features/community-poi/CommunityPoiMeta.vue b/components/features/community-poi/CommunityPoiMeta.vue
new file mode 100644
index 0000000..b01d00e
--- /dev/null
+++ b/components/features/community-poi/CommunityPoiMeta.vue
@@ -0,0 +1,140 @@
+
+
+
+
+
+
-
+ {{ t('community_poi.meta.location') }}
+
+ - {{ poi.location }}
+
+
+
+ {{ t('community_poi.meta.coordinates') }}
+
+
+ {{ coordsLabel }}
+
+ ({{ dimensionLabel }})
+
+
+ {{ t('community_poi.meta.coordinates_hint') }}
+
+
+
+
+
+
+ {{ t('community_poi.meta.builders') }}
+
+
+
+
+
+
+
+ {{ t('community_poi.meta.started') }}
+
+
+
+
+
+
+
+ {{ t('community_poi.meta.updated') }}
+
+
+
+
+
+
+
+
diff --git a/components/features/community-poi/CommunityPoiProgressBar.vue b/components/features/community-poi/CommunityPoiProgressBar.vue
new file mode 100644
index 0000000..776e1c2
--- /dev/null
+++ b/components/features/community-poi/CommunityPoiProgressBar.vue
@@ -0,0 +1,49 @@
+
+
+
+
+
+ {{ visibleLabel }}
+
+ {{ clamped }}%
+
+
+
+
+
diff --git a/components/features/community-poi/CommunityPoiSchematicList.vue b/components/features/community-poi/CommunityPoiSchematicList.vue
new file mode 100644
index 0000000..e76ae8d
--- /dev/null
+++ b/components/features/community-poi/CommunityPoiSchematicList.vue
@@ -0,0 +1,125 @@
+
+
+
+
+
+ -
+
+
+
+
+ {{ t('community_poi.schematics.setup.title') }}
+
+
+
+
- {{ t('community_poi.schematics.setup.origin') }}:
+ -
+ {{ schematic.origin.x }} / {{ schematic.origin.y }} / {{ schematic.origin.z }}
+
+
+
+
- {{ t('community_poi.schematics.setup.facing') }}:
+ - {{ facingLabel(schematic.facing) }}
+
+
+
- {{ t('community_poi.schematics.setup.rotation') }}:
+ - {{ rotationLabel(schematic.rotation) }}
+
+
+
+ {{ schematic.setupNotes }}
+
+
+
+
+
+ {{ t('community_poi.schematics.hint') }}
+
+
+
diff --git a/components/features/community-poi/CommunityPoiStatusBadge.vue b/components/features/community-poi/CommunityPoiStatusBadge.vue
new file mode 100644
index 0000000..8291a78
--- /dev/null
+++ b/components/features/community-poi/CommunityPoiStatusBadge.vue
@@ -0,0 +1,58 @@
+
+
+
+
+
+ {{ label }}
+
+
diff --git a/components/features/home/carousel/Carousel.vue b/components/features/home/carousel/Carousel.vue
index ff900b6..1db00f1 100644
--- a/components/features/home/carousel/Carousel.vue
+++ b/components/features/home/carousel/Carousel.vue
@@ -6,6 +6,7 @@ import CarouselItemImage from '~/components/features/home/carousel/items/Carouse
import CarouselItemBlog from '~/components/features/home/carousel/items/CarouselItemBlog.vue'
import CarouselItemNews from '~/components/features/home/carousel/items/CarouselItemNews.vue'
import CarouselItemEvent from '~/components/features/home/carousel/items/CarouselItemEvent.vue'
+import CarouselItemPoi from '~/components/features/home/carousel/items/CarouselItemPoi.vue'
import type { AnySlide, NormalizedSlide } from '~/types/carousel'
import { normalizeSlides, getSlideAriaText } from '~/composables/useCarousel'
@@ -59,10 +60,13 @@ const preloadLink = computed(() => {
const slide = normalizedSlides.value[0]
if (!slide) return null
- const src =
- slide.type === 'image'
+ const src
+ = slide.type === 'image'
? slide.src
- : slide.type === 'blog' || slide.type === 'news' || slide.type === 'event'
+ : slide.type === 'blog'
+ || slide.type === 'news'
+ || slide.type === 'event'
+ || slide.type === 'poi'
? slide.image
: undefined
@@ -136,7 +140,10 @@ const stop = () => {
// Only watch and start autoplay on the client to avoid SSR interval usage
if (import.meta.client) {
watch(
- () => [props.autoPlay, props.interval, slidesCount.value, prefersReducedMotion.value],
+ () => [props.autoPlay,
+props.interval,
+slidesCount.value,
+prefersReducedMotion.value],
() => start(),
{ immediate: true }
)
@@ -204,6 +211,7 @@ const componentFor = (slide: NormalizedSlide) => {
case 'blog': return CarouselItemBlog
case 'news': return CarouselItemNews
case 'event': return CarouselItemEvent
+ case 'poi': return CarouselItemPoi
default: return CarouselItemImage
}
}
@@ -246,6 +254,7 @@ function withAlpha(rgb: string, a: number) {