premier commit
|
@ -0,0 +1,24 @@
|
||||||
|
# Nuxt dev/build outputs
|
||||||
|
.output
|
||||||
|
.data
|
||||||
|
.nuxt
|
||||||
|
.nitro
|
||||||
|
.cache
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Node dependencies
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
.DS_Store
|
||||||
|
.fleet
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Local env files
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
|
@ -0,0 +1,75 @@
|
||||||
|
# Nuxt 3 Minimal Starter
|
||||||
|
|
||||||
|
Look at the [Nuxt 3 documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
Make sure to install the dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm install
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn install
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development Server
|
||||||
|
|
||||||
|
Start the development server on `http://localhost:3000`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm run dev
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn dev
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Production
|
||||||
|
|
||||||
|
Build the application for production:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm run build
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn build
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun run build
|
||||||
|
```
|
||||||
|
|
||||||
|
Locally preview production build:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run preview
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm run preview
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn preview
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun run preview
|
||||||
|
```
|
||||||
|
|
||||||
|
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
|
|
@ -0,0 +1,75 @@
|
||||||
|
<template>
|
||||||
|
<Header />
|
||||||
|
<main>
|
||||||
|
<NuxtPage />
|
||||||
|
</main>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const { getItems } = useDirectusItems();
|
||||||
|
const global = ref([]);
|
||||||
|
onMounted(async () => {
|
||||||
|
const items = await getItems({ collection: "Global" });
|
||||||
|
global.value = items;
|
||||||
|
});
|
||||||
|
|
||||||
|
provide('globalData', global);
|
||||||
|
|
||||||
|
useSeoMeta({
|
||||||
|
ogImage: '/card.jpg',
|
||||||
|
ogImageAlt: global.value.contact_image_titre,
|
||||||
|
twitterImage: '/card.jpg',
|
||||||
|
});
|
||||||
|
|
||||||
|
useHead({
|
||||||
|
htmlAttrs: {
|
||||||
|
lang: 'fr'
|
||||||
|
},
|
||||||
|
link: [
|
||||||
|
{
|
||||||
|
rel: 'icon',
|
||||||
|
type: 'image/png',
|
||||||
|
href: 'favicon.png'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Latitude';
|
||||||
|
src: url('assets/fonts/latitude-webfont.woff2') format('woff2'),
|
||||||
|
url('assets/fonts/latitude-webfont.woff') format('woff');
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-family: 'Latitude', serif;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: normal;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #0e312f;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
padding: 1rem;
|
||||||
|
header {
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
main {
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-enter-active,
|
||||||
|
.page-leave-active {
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
.page-enter-from,
|
||||||
|
.page-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
</style>
|
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 74 KiB |
|
@ -0,0 +1,157 @@
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<header>
|
||||||
|
<nav>
|
||||||
|
<div>
|
||||||
|
<h1 :class="{ active: isActive('/') }">
|
||||||
|
<div class="hover_el_active" id="indexActive" aria-label="selected element"></div>
|
||||||
|
<NuxtLink to="/">mahée auffret</NuxtLink>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<ul>
|
||||||
|
<li :class="{ active: isActive('/galerie') }">
|
||||||
|
<div class="hover_el_active" id="galeryActive" aria-label="selected element"></div>
|
||||||
|
<NuxtLink to="/galerie">galerie</NuxtLink>
|
||||||
|
</li>
|
||||||
|
<li :class="{ active: isActive('/magasin') }">
|
||||||
|
<div class="hover_el_active" id="shopActive" aria-label="selected element"></div>
|
||||||
|
<NuxtLink to="/magasin">magasin</NuxtLink>
|
||||||
|
</li>
|
||||||
|
<li :class="{ active: isActive('/contact') }">
|
||||||
|
<div class="hover_el_active" id="contactActive" aria-label="selected element"></div>
|
||||||
|
<NuxtLink to="/contact">contact</NuxtLink>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
<div>
|
||||||
|
<a :href="globalData.instagram_link" target="_blank">
|
||||||
|
<img src="/assets/images/instagram.png" alt="Logo Instagram Dessiné" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const globalData = inject('globalData');
|
||||||
|
return { globalData };
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
isActive(path) {
|
||||||
|
return this.$route.path === path;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
header {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
nav {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
h1 {
|
||||||
|
display: inline-block;
|
||||||
|
width: auto;
|
||||||
|
position: relative;
|
||||||
|
margin-top: 1rem;
|
||||||
|
> a {
|
||||||
|
position: relative;
|
||||||
|
padding: 10px;
|
||||||
|
padding-left: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h1 .hover_el_active {
|
||||||
|
left: -40% !important;
|
||||||
|
width: 170% !important;
|
||||||
|
}
|
||||||
|
h1:hover .hover_el_active,
|
||||||
|
h1.active .hover_el_active {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
display: flex;
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin-top: 1rem;
|
||||||
|
> li {
|
||||||
|
position: relative;
|
||||||
|
margin-left: 1.5rem;
|
||||||
|
> a {
|
||||||
|
position: relative;
|
||||||
|
padding: 10px;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
> li:hover .hover_el_active,
|
||||||
|
> li.active .hover_el_active {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
> li:first-of-type {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.hover_el_active {
|
||||||
|
position: absolute;
|
||||||
|
top: -70%;
|
||||||
|
left: -15%;
|
||||||
|
width: 130%;
|
||||||
|
height: 240%;
|
||||||
|
background-size: contain !important;
|
||||||
|
background-repeat: no-repeat !important;
|
||||||
|
background-position: center !important;
|
||||||
|
z-index: 1;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
}
|
||||||
|
#indexActive {
|
||||||
|
background-image: url('/assets/images/hover-index.png');
|
||||||
|
}
|
||||||
|
#galeryActive {
|
||||||
|
background-image: url('/assets/images/hover-index.png');
|
||||||
|
left: -30%;
|
||||||
|
width: 160%;
|
||||||
|
}
|
||||||
|
#shopActive {
|
||||||
|
background-image: url('/assets/images/hover-index.png');
|
||||||
|
}
|
||||||
|
#contactActive {
|
||||||
|
background-image: url('/assets/images/hover-index.png');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
> div {
|
||||||
|
width: 3rem;
|
||||||
|
z-index: 1;
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
transform: rotate(0deg);
|
||||||
|
transition: transform 0.3s ease-out;
|
||||||
|
}
|
||||||
|
img:hover {
|
||||||
|
transform: rotate(10deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 800px) {
|
||||||
|
header {
|
||||||
|
align-items: center;
|
||||||
|
nav {
|
||||||
|
flex-direction: row;
|
||||||
|
h1 {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
margin-top: 0;
|
||||||
|
> li:first-of-type {
|
||||||
|
margin-left: 2.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,205 @@
|
||||||
|
<template>
|
||||||
|
<main>
|
||||||
|
<article v-for="content in contents" :key="content.id">
|
||||||
|
<div>
|
||||||
|
<NuxtImg
|
||||||
|
:src="img((content.image ? content.image : content.shop_image))"
|
||||||
|
:alt="content.titre"
|
||||||
|
format="webp"
|
||||||
|
placeholder
|
||||||
|
lazy
|
||||||
|
sizes="sm:40vw lg:30vw"
|
||||||
|
@click="displaySlider(content.id)" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p v-if="content.titre">{{ content.titre }}</p>
|
||||||
|
<p v-if="content.medium">{{ content.medium }}</p>
|
||||||
|
<p v-if="content.description">{{ content.description }}</p>
|
||||||
|
<p v-if="content.format">{{ content.format }}</p>
|
||||||
|
<p v-if="content.annee">{{ content.annee }}</p>
|
||||||
|
<p v-if="content.prix">{{ content.prix }}</p>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
<swiper
|
||||||
|
:zoom="true"
|
||||||
|
:loop="true"
|
||||||
|
:modules="modules"
|
||||||
|
:navigation="true"
|
||||||
|
@slideChange="onSlideChange"
|
||||||
|
@swiper="onSwiper"
|
||||||
|
>
|
||||||
|
<swiper-slide v-for="content in contents" :key="content.id">
|
||||||
|
<div class="swiper-zoom-container">
|
||||||
|
<NuxtImg
|
||||||
|
:src="img((content.image ? content.image : content.shop_image))"
|
||||||
|
:alt="content.titre"
|
||||||
|
format="webp"
|
||||||
|
placeholder
|
||||||
|
lazy />
|
||||||
|
</div>
|
||||||
|
</swiper-slide>
|
||||||
|
<div class="swiper-button-close" @click="closeSlider()"></div>
|
||||||
|
</swiper>
|
||||||
|
</main>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { A11y, Navigation, Zoom } from "swiper/modules";
|
||||||
|
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||||
|
import "swiper/css";
|
||||||
|
import 'swiper/css/zoom';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const { getThumbnail : img } = useDirectusFiles();
|
||||||
|
|
||||||
|
const swiperInstance = ref(null);
|
||||||
|
const onSwiper = (swiper) => {
|
||||||
|
swiperInstance.value = swiper;
|
||||||
|
};
|
||||||
|
const onSlideChange = () => {};
|
||||||
|
|
||||||
|
const displaySlider = (index) => {
|
||||||
|
const body = document.querySelector('body');
|
||||||
|
body.style.overflowY = 'hidden';
|
||||||
|
const swiper = swiperInstance.value;
|
||||||
|
swiper.slideToLoop(index - 1);
|
||||||
|
const swiperEl = swiper.el;
|
||||||
|
swiperEl.style.display = "block";
|
||||||
|
setTimeout(() => {
|
||||||
|
swiperEl.style.opacity = 1;
|
||||||
|
}, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
const closeSlider = () => {
|
||||||
|
const body = document.querySelector('body');
|
||||||
|
body.style.overflowY = 'auto';
|
||||||
|
const swiperEl = document.querySelector('.swiper');
|
||||||
|
swiperEl.style.opacity = 0;
|
||||||
|
setTimeout(() => {
|
||||||
|
swiperEl.style.display = "none";
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
onSwiper,
|
||||||
|
onSlideChange,
|
||||||
|
modules: [Navigation, A11y, Zoom],
|
||||||
|
displaySlider,
|
||||||
|
closeSlider,
|
||||||
|
img
|
||||||
|
};
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
Swiper,
|
||||||
|
SwiperSlide,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
contents: Object
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
main {
|
||||||
|
margin-top: 5vh;
|
||||||
|
article {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 3vh;
|
||||||
|
> div:first-of-type {
|
||||||
|
width: 40vw;
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
> div:last-of-type {
|
||||||
|
padding-left: 5vw;
|
||||||
|
width: 50vw;
|
||||||
|
p {
|
||||||
|
line-height: 1.2;
|
||||||
|
margin-bottom: 0.5vh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.swiper {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
backdrop-filter: blur(5px);
|
||||||
|
background-color: rgba(255, 255, 255, 0.5);
|
||||||
|
position: fixed;
|
||||||
|
display: none;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.3s ease-out;
|
||||||
|
.swiper-wrapper {
|
||||||
|
.swiper-slide {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
img{
|
||||||
|
width: 60%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.swiper-button-prev,
|
||||||
|
.swiper-button-next,
|
||||||
|
.swiper-button-close {
|
||||||
|
z-index: 1;
|
||||||
|
position: absolute;
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
background-position: center;
|
||||||
|
background-size: cover;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.swiper-button-prev {
|
||||||
|
left: 5vw;
|
||||||
|
bottom: calc(50vh - 1rem);
|
||||||
|
background-image: url(/assets/images/before.png);
|
||||||
|
}
|
||||||
|
.swiper-button-next {
|
||||||
|
right: 5vw;
|
||||||
|
bottom: calc(50vh - 1rem);
|
||||||
|
background-image: url(/assets/images/after.png);
|
||||||
|
}
|
||||||
|
.swiper-button-close {
|
||||||
|
right: 5vw;
|
||||||
|
top: 5vh;
|
||||||
|
background-image: url(/assets/images/close.png);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 800px) {
|
||||||
|
main {
|
||||||
|
article {
|
||||||
|
> div:first-of-type {
|
||||||
|
width: 25vw;
|
||||||
|
}
|
||||||
|
> div:last-of-type {
|
||||||
|
padding-left: 2vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.swiper .swiper-wrapper .swiper-slide img {
|
||||||
|
width: 40%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 1200px) {
|
||||||
|
main {
|
||||||
|
article > div:first-of-type {
|
||||||
|
width: 15vw;
|
||||||
|
}
|
||||||
|
.swiper .swiper-wrapper .swiper-slide img {
|
||||||
|
width: 30%;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,59 @@
|
||||||
|
<template>
|
||||||
|
<Header />
|
||||||
|
<div class="error-page">
|
||||||
|
<h1 v-if="error.statusCode === 404">Erreur 404</h1>
|
||||||
|
<p v-if="error.statusCode === 404">La page {{ error.url }} n'existe pas</p>
|
||||||
|
<NuxtImg
|
||||||
|
v-if="global.error_img"
|
||||||
|
:src="img(global.error_img)"
|
||||||
|
:alt="global.error_img_title"
|
||||||
|
format="webp"
|
||||||
|
placeholder
|
||||||
|
lazy
|
||||||
|
sizes="sm:100vw" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const { getItems } = useDirectusItems();
|
||||||
|
const { getThumbnail : img } = useDirectusFiles();
|
||||||
|
|
||||||
|
const global = ref([]);
|
||||||
|
onMounted(async () => {
|
||||||
|
const items = await getItems({ collection: "Global" });
|
||||||
|
global.value = items;
|
||||||
|
});
|
||||||
|
|
||||||
|
provide('globalData', global);
|
||||||
|
|
||||||
|
return {
|
||||||
|
global,
|
||||||
|
img
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
error: Object
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.error-page {
|
||||||
|
text-align: center;
|
||||||
|
margin: 3rem auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 60vw;
|
||||||
|
margin: auto;
|
||||||
|
margin-top: 5rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
devtools: { enabled: true },
|
||||||
|
modules: [
|
||||||
|
'nuxt-directus',
|
||||||
|
'@nuxt/image',
|
||||||
|
'@nuxtjs/seo'
|
||||||
|
],
|
||||||
|
app: {
|
||||||
|
pageTransition: { name: 'page', mode: 'out-in' }
|
||||||
|
},
|
||||||
|
site: {
|
||||||
|
url: 'https://localhost:3000',
|
||||||
|
defaultLocale: 'fr',
|
||||||
|
name: 'Mahée Auffret',
|
||||||
|
description: 'Portfolio de l\'artiste-peintre basée à Rennes Mahée Auffret'
|
||||||
|
},
|
||||||
|
directus: {
|
||||||
|
url: "http://localhost:8055/",
|
||||||
|
token: process.env.DIRECTUS_API_TOKEN
|
||||||
|
},
|
||||||
|
image: {
|
||||||
|
domains: ['http://localhost:8055/'],
|
||||||
|
format: ['webp'],
|
||||||
|
}
|
||||||
|
})
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"name": "nuxt-app",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"build": "nuxt build",
|
||||||
|
"dev": "nuxt dev",
|
||||||
|
"generate": "nuxt generate",
|
||||||
|
"preview": "nuxt preview",
|
||||||
|
"postinstall": "nuxt prepare"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@nuxt/image": "^1.3.0",
|
||||||
|
"nuxt": "^3.10.1",
|
||||||
|
"nuxt-directus": "^5.6.0",
|
||||||
|
"swiper": "^11.0.6",
|
||||||
|
"vue": "^3.4.15",
|
||||||
|
"vue-router": "^4.2.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@nuxtjs/seo": "^2.0.0-rc.8",
|
||||||
|
"sass": "^1.71.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
<template>
|
||||||
|
<main id="contact">
|
||||||
|
<div v-if="globalData.contact_image">
|
||||||
|
<NuxtImg
|
||||||
|
:src="img(globalData.contact_image)"
|
||||||
|
:alt="globalData.contact_image_titre"
|
||||||
|
format="webp"
|
||||||
|
placeholder
|
||||||
|
lazy
|
||||||
|
sizes="sm:40vw" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p>{{ globalData.contact_texte }}</p>
|
||||||
|
<a :href="'mailto:' + globalData.email">{{ globalData.email }}</a>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const globalData = inject('globalData');
|
||||||
|
const { getThumbnail : img } = useDirectusFiles();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
#contact {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
> div:first-of-type {
|
||||||
|
width: 40vw;
|
||||||
|
> img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
> div:last-of-type {
|
||||||
|
margin-top: 2rem;
|
||||||
|
> p {
|
||||||
|
line-height: 1.2;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 800px) {
|
||||||
|
#contact {
|
||||||
|
flex-direction: row;
|
||||||
|
> div:first-of-type {
|
||||||
|
width: 30vw;
|
||||||
|
}
|
||||||
|
> div:last-of-type {
|
||||||
|
width: 40vw;
|
||||||
|
margin-left: 2rem;
|
||||||
|
align-self: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 1200px) {
|
||||||
|
#contact {
|
||||||
|
> div:first-of-type {
|
||||||
|
width: 15vw;
|
||||||
|
}
|
||||||
|
> div:last-of-type {
|
||||||
|
width: 30vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,25 @@
|
||||||
|
<template>
|
||||||
|
<Projects :contents="galerie" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Projects from '@/components/Projects.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const { getItems } = useDirectusItems();
|
||||||
|
const galerie = ref([]);
|
||||||
|
onMounted(async () => {
|
||||||
|
const items = await getItems({ collection: "galerie" });
|
||||||
|
galerie.value = items;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
galerie
|
||||||
|
};
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
Projects
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -0,0 +1,83 @@
|
||||||
|
<template>
|
||||||
|
<main>
|
||||||
|
<div class="indexImg" v-for="image in itemsAccueil" :key="image.id">
|
||||||
|
<NuxtImg
|
||||||
|
:src="img(image.image_accueil)"
|
||||||
|
:alt="image.titre"
|
||||||
|
format="webp"
|
||||||
|
placeholder
|
||||||
|
lazy
|
||||||
|
sizes="sm:150vw" />
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const { getItems } = useDirectusItems();
|
||||||
|
|
||||||
|
const itemsAccueil = await getItems({
|
||||||
|
collection: "images_accueil"
|
||||||
|
});
|
||||||
|
|
||||||
|
const { getThumbnail : img } = useDirectusFiles();
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
const imgs = document.querySelectorAll('.indexImg img');
|
||||||
|
|
||||||
|
const showingTime = 5000, transitionTime = 2000;
|
||||||
|
|
||||||
|
for (let img of imgs) {
|
||||||
|
img.addEventListener('click', function() {
|
||||||
|
nextSlide();
|
||||||
|
resetTimer();
|
||||||
|
});
|
||||||
|
img.style.transition = `opacity ${transitionTime / 1000}s ease-out`;
|
||||||
|
}
|
||||||
|
|
||||||
|
imgs[0].style.opacity = 1;
|
||||||
|
|
||||||
|
let diapoTimer = setInterval(nextSlide, showingTime + transitionTime);
|
||||||
|
|
||||||
|
let index = 1;
|
||||||
|
|
||||||
|
function nextSlide() {
|
||||||
|
if (index === 0) {
|
||||||
|
imgs[imgs.length - 1].style.opacity = 0;
|
||||||
|
imgs[index].style.opacity = 1;
|
||||||
|
} else {
|
||||||
|
imgs[index - 1].style.opacity = 0;
|
||||||
|
imgs[index].style.opacity = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index === imgs.length - 1) {
|
||||||
|
index = 0;
|
||||||
|
} else {
|
||||||
|
index ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetTimer() {
|
||||||
|
clearInterval(diapoTimer);
|
||||||
|
diapoTimer = setInterval(nextSlide, showingTime + transitionTime);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.indexImg {
|
||||||
|
z-index: -1;
|
||||||
|
position: absolute;
|
||||||
|
overflow: hidden;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
img {
|
||||||
|
object-fit: cover;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,31 @@
|
||||||
|
<template>
|
||||||
|
<main>
|
||||||
|
<p>{{ globalData.magasin_explication }}</p>
|
||||||
|
<Projects :contents="magasin" />
|
||||||
|
</main>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Projects from '@/components/Projects.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const { getItems } = useDirectusItems();
|
||||||
|
const magasin = ref([]);
|
||||||
|
onMounted(async () => {
|
||||||
|
const items = await getItems({ collection: "magasin" });
|
||||||
|
magasin.value = items;
|
||||||
|
});
|
||||||
|
|
||||||
|
const globalData = inject('globalData');
|
||||||
|
|
||||||
|
return {
|
||||||
|
globalData,
|
||||||
|
magasin
|
||||||
|
};
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
Projects
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
After Width: | Height: | Size: 251 KiB |
After Width: | Height: | Size: 20 KiB |
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"extends": "../.nuxt/tsconfig.server.json"
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
// https://nuxt.com/docs/guide/concepts/typescript
|
||||||
|
"extends": "./.nuxt/tsconfig.json"
|
||||||
|
}
|