forked from contentstack/kickstart-nuxt
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.vue
More file actions
152 lines (145 loc) · 4.94 KB
/
Copy pathapp.vue
File metadata and controls
152 lines (145 loc) · 4.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
<!--
Main application component that integrates Contentstack CMS with Nuxt.js
This component:
1. Fetches and displays content from Contentstack
2. Supports live preview functionality for content updates
3. Implements responsive layout with dynamic content blocks
4. Handles rich text content and image rendering
Key features:
- Contentstack integration with live preview
- Responsive design with mobile-first approach
- Dynamic content blocks with flexible layouts
- Rich text support with HTML rendering
- Image optimization and responsive sizing
-->
<script lang="ts" setup>
/**
* Import the empty block parent class from Contentstack Live Preview utils
* This class is used to style empty block containers in the live preview mode
*/
import VB_EmptyBlockParentClass from "@contentstack/live-preview-utils";
/**
* Fetch the page data and refresh function using the useGetPage composable
* This gets the content for the root ('/') page from Contentstack
* 'page' contains all the content data, and 'refresh' is used to update the content
*/
const { data: page, refresh } = await useGetPage("/");
// Set up live preview functionality when the component is mounted
onMounted(() => {
// Get preview utilities from Nuxt app context
const { $preview, $ContentstackLivePreview } = useNuxtApp();
// Type assertion for ContentstackLivePreview
const livePreview = $ContentstackLivePreview as unknown as ContentstackLivePreview;
// If preview mode is active, set up live content updates
// This will automatically refresh the page when content changes in Contentstack
$preview && livePreview.onEntryChange(refresh);
});
</script>
<template>
<!-- Main content wrapper with max width and center alignment -->
<main class="max-w-screen-md mx-auto">
<!-- Content section with padding -->
<section class="p-4">
<!-- Page title with live preview binding -->
<h1
v-if="page?.title"
class="text-4xl font-bold mb-4 text-center"
v-bind="page?.$ && page?.$.title"
>
{{ page?.title }} with Nuxt
</h1>
<!-- Page description with live preview binding -->
<p
v-if="page?.description"
class="mb-4 text-center"
v-bind="page?.$ && page?.$.description"
>
{{ page?.description }}
</p>
<!-- Featured image with responsive dimensions -->
<img
v-if="page?.image"
class="mb-4"
width="768"
height="414"
:src="page?.image.url"
:alt="page?.image.title"
v-bind="page?.image?.$ && page?.image?.$.url"
/>
<!-- Rich text content with HTML rendering -->
<div
v-if="page?.rich_text"
v-bind="page?.$ && page?.$.rich_text"
v-html="page?.rich_text"
/>
<!-- Dynamic blocks container with live preview support -->
<div
:class="[
'space-y-8 max-w-full mt-4',
// Apply empty block class for live preview when no blocks exist
!page?.blocks || page.blocks.length === 0
? VB_EmptyBlockParentClass
: '',
]"
v-bind="page?.$ && page?.$.blocks"
>
<!-- Iterate through content blocks -->
<div
v-for="(item, index) in page?.blocks"
:key="item.block._metadata.uid"
v-bind="page?.$ && page?.$[`blocks__${index}`]"
:class="[
'flex flex-col md:flex-row items-center space-y-4 md:space-y-0 bg-white',
// Dynamic layout class based on image position preference
item.block.layout === 'image_left'
? 'md:flex-row'
: 'md:flex-row-reverse',
]"
>
<!-- Block image section - takes up half width on desktop -->
<div class="w-full md:w-1/2">
<img
v-if="item.block.image"
:src="item.block.image.url"
:alt="item.block.image.title"
width="200"
height="112"
class="w-full"
v-bind="item.block.$ && item.block.$.image"
/>
</div>
<!-- Block text content section - takes up half width on desktop -->
<div class="w-full md:w-1/2 p-4">
<!-- Block title with live preview binding -->
<h2
v-if="item.block.title"
class="text-2xl font-bold"
v-bind="item.block.$ && item.block.$.title"
>
{{ item.block.title }}
</h2>
<!-- Block copy/content with HTML rendering and typography styles -->
<div
v-if="item.block.copy"
v-html="item.block.copy"
class="prose"
v-bind="item.block.$ && item.block.$.copy"
/>
</div>
</div>
</div>
</section>
</main>
</template>
<style lang="css">
/**
* Base styles for the application
* These styles apply to the entire application
*/
body {
background: #e9e9e9;
}
a {
text-decoration: underline;
}
</style>