Skip to content

Commit

Permalink
Exhibition Bar
Browse files Browse the repository at this point in the history
Created UI for exhibitions
Added function to get only current exhibitions
Refined transition effects for search overlay
  • Loading branch information
ethanfox committed Jul 23, 2024
1 parent 906aec6 commit 4cf57ef
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 16 deletions.
12 changes: 11 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"axios": "^1.7.2",
"pinia": "^2.1.7",
"vue": "^3.4.32",
"vue-router": "^4.4.0"
"vue-router": "^4.4.0",
"vue3-carousel": "^0.3.3"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.10.3",
Expand Down
8 changes: 8 additions & 0 deletions src/assets/style.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

.glass-shadow {
/* Your existing box-shadow styles */
box-shadow:
0 1px 3px rgba(18, 18, 18, 0.2),
inset 0 1px 0.5px rgba(255, 255, 255, 0.06),
inset 0 -1px 0 rgba(18, 18, 18, 0.08);
}
68 changes: 68 additions & 0 deletions src/components/ExhibitionBar.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<template>
<!-- EXHIBITIONS -->
<div
class="flex flex-col gap-4 pt-2 pb-4 px-10 bg-white rounded-full glass-shadow border border-neutral-100 w-full"
>
<p class="text-sm text-neutral-950 font-semibold">Current Exhibitions</p>
<Carousel class="p-0" v-bind="settings" :breakpoints="breakpoints">
<Slide v-for="exhibition in exhibitions" :key="exhibition.id">
<div
class="carousel__item bg-white overflow-hidden border glass-shadow rounded-full"
>
<div class="flex gap-4">
<img
class="size-12 rounded-full glass-shadow"
:src="exhibition.image_url"
:alt="exhibition.title"
v-if="exhibition.image_url"
/>
<h1 class="font-bold text-sm line-clamp-2 text-left">
{{ exhibition.title }}
</h1>
</div>
</div>
</Slide>

<template #addons>
<Navigation />
</template>
</Carousel>
</div>
<!-- EXHIBITIONS -->
</template>
<script>
import { defineComponent } from "vue";
// import "vue3-carousel/dist/carousel.css";
import { Carousel, Slide, Pagination, Navigation } from "vue3-carousel";
export default defineComponent({
props: ["exhibitions"],
name: "Breakpoints",
components: {
Carousel,
Slide,
Navigation,
},
data: () => ({
// carousel settings
settings: {
itemsToShow: 1,
snapAlign: "center",
},
// breakpoints are mobile first
// any settings not specified will fallback to the carousel settings
breakpoints: {
// 700px and up
700: {
itemsToShow: 3.5,
snapAlign: "center",
},
// 1024 and up
1024: {
itemsToShow: 5,
snapAlign: "start",
},
},
}),
});
</script>
2 changes: 1 addition & 1 deletion src/components/Navigation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<nav
class="hidden z-20 lg:flex justify-between text-black fixed xl:bottom-20 xl:left-24 xl:border-0 xl:w-full w-full bottom-16 left-4 rounded-sm"
>
<div class="bg-white flex shadow-lg">
<div class="bg-white flex shadow-lg rounded-sm">
<a href="/">
<img
src="../assets/logo.svg"
Expand Down
135 changes: 122 additions & 13 deletions src/components/SearchOverlay.vue
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
<template>
<transition name="fade">
<transition name="search-fade">
<div v-if="showSearchOverlay" class="search-overlay">
<div
class="bg-neutral-950/50 backdrop-blur-md fixed inset-0 flex items-center justify-center z-[9999]"
class="bg-neutral-950/50 backdrop fixed inset-0 flex flex-col gap-8 items-center justify-center z-[10] px-16 lg:px-32 xl:px-96"
>
<!-- SEARCH -->
<form
class="flex gap-4 p-2 bg-white rounded-full shadow-lg border border-neutral-100 w-[900px]"
class="flex gap-4 p-2 bg-white rounded-full glass-shadow border border-neutral-100 w-full"
>
<div class="flex flex-col w-full pl-8">
<label for="search" class="text-sm text-neutral-500 font-semibold"
>Search</label
<label for="search" class="text-sm text-neutral-950 font-semibold"
>Artwork</label
>
<input
placeholder="Search by name"
type="text"
id="search"
name="search"
class="p-2 border-0 border-b focus:border-b-2 outline-none border-neutral-500 transition-all h-12"
class="border-0 border-b focus:border-b-2 outline-none border-neutral-500 transition-all h-10"
/>
</div>
<button
Expand All @@ -30,33 +32,140 @@
/>
</button>
</form>
<!-- SEARCH -->
<!-- EXHIBITIONS -->
<div class="px-2 w-full">
<ExhibitionBar :exhibitions="exhibitions" />
<!-- <div
class="flex gap-4 p-2 bg-white rounded-full glass-shadow border border-neutral-100 w-full"
>
<p for="search" class="text-sm text-neutral-950 font-semibold">
Current Exhibitions
</p>
</div> -->
</div>
<!-- EXHIBITIONS -->
</div>
</div>
</transition>
</template>

<script>
import { ref, watchEffect } from "vue";
import axios from "axios";
import ExhibitionBar from "./ExhibitionBar.vue";
import "vue3-carousel/dist/carousel.css";
import { Carousel, Slide, Pagination, Navigation } from "vue3-carousel";
export default {
components: {
Carousel,
Slide,
Pagination,
Navigation,
ExhibitionBar,
},
props: {
showSearchOverlay: Boolean,
},
setup(props) {
const exhibitionPage = ref(1);
const loadingExhibitions = ref(true);
const exhibitions = ref([]);
const fetchExhibitions = async () => {
loadingExhibitions.value = true;
try {
console.log("Fetching exhibitions...");
const today = new Date().toISOString().split("T")[0]; // Get today's date in YYYY-MM-DD format
const response = await axios.get(
"https://api.artic.edu/api/v1/exhibitions/search",
{
params: {
query: {
bool: {
must: [
{ range: { aic_start_at: { lte: today } } },
{ range: { aic_end_at: { gte: today } } },
],
},
},
fields: "id,title,image_id,image_url,aic_start_at,aic_end_at",
limit: 100,
page: exhibitionPage.value,
},
}
);
const newExhibitions = response.data.data.map((exhibition) => ({
...exhibition,
// image_url: exhibition.image_id
// ? `https://www.artic.edu/iiif/2/${exhibition.image_id}/full/200,/0/default.jpg`
// : null,
}));
exhibitions.value = newExhibitions;
exhibitionPage.value++;
} catch (error) {
console.error("Error fetching exhibitions:", error);
} finally {
console.log("Exhibitions fetched");
console.log(exhibitions.value);
setTimeout(() => {
loadingExhibitions.value = false;
}, 3000);
}
};
watchEffect(() => {
if (props.showSearchOverlay && exhibitions.value.length === 0) {
fetchExhibitions();
console.log("exhibitions.value", exhibitions.value);
}
});
return {
loadingExhibitions,
exhibitions,
};
},
};
</script>

<style scoped>
.backdrop {
transition:
backdrop-filter 0.5s ease,
opacity 0.5s ease;
backdrop-filter: blur(8px);
}
.search-overlay {
position: fixed;
inset: 0;
z-index: 9999;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
.search-fade-enter-active,
.search-fade-leave-active {
transition: opacity 0.5s ease;
}
.fade-enter-from,
.fade-leave-to {
.search-fade-enter-from .backdrop,
.search-fade-leave-to .backdrop {
opacity: 0;
backdrop-filter: blur(0px);
}
.search-fade-enter-to .backdrop,
.search-fade-leave-from .backdrop {
opacity: 1;
backdrop-filter: blur(8px);
}
/* .search-fade-enter-active,
.search-fade-leave-active {
transition: opacity 0.5s ease;
}
.search-fade-enter-from,
.search-fade-leave-to {
opacity: 0;
} */
</style>

0 comments on commit 4cf57ef

Please sign in to comment.