cleanup
This commit is contained in:
@@ -19,7 +19,7 @@
|
|||||||
@change="handleFilter" />
|
@change="handleFilter" />
|
||||||
</SMToolbar>
|
</SMToolbar>
|
||||||
<SMPagination
|
<SMPagination
|
||||||
v-if="postsTotal > 0"
|
v-if="postsTotal > postsPerPage"
|
||||||
v-model="postsPage"
|
v-model="postsPage"
|
||||||
:total="postsTotal"
|
:total="postsTotal"
|
||||||
:per-page="postsPerPage" />
|
:per-page="postsPerPage" />
|
||||||
@@ -29,30 +29,39 @@
|
|||||||
type="error"
|
type="error"
|
||||||
:message="formMessage"
|
:message="formMessage"
|
||||||
class="mt-5" />
|
class="mt-5" />
|
||||||
<SMPanelList
|
|
||||||
:loading="loading"
|
<div class="events-list">
|
||||||
:not-found="events.length == 0"
|
<router-link
|
||||||
not-found-text="No workshops found">
|
class="event"
|
||||||
<SMPanel
|
v-for="event in events"
|
||||||
v-for="item in events"
|
:key="event.id"
|
||||||
:key="item.event.id"
|
:to="{ name: 'event', params: { id: event.id } }">
|
||||||
:to="{ name: 'event', params: { id: item.event.id } }"
|
<div
|
||||||
:title="item.event.title"
|
class="image"
|
||||||
:image="mediaGetVariantUrl(item.event.hero, 'medium')"
|
:style="{
|
||||||
:show-time="true"
|
backgroundImage: `url('${event.hero.url}')`,
|
||||||
:date="item.event.start_at"
|
}"></div>
|
||||||
:end-date="item.event.end_at"
|
<div class="content">
|
||||||
:date-in-image="true"
|
<h3 class="title">{{ event.title }}</h3>
|
||||||
:price="item.event.price"
|
<div class="row date">
|
||||||
:location="
|
<ion-icon name="calendar-outline" class="icon" />
|
||||||
item.event.location == 'online'
|
<div class="text">{{ computedDate(event) }}</div>
|
||||||
? 'Online Event'
|
</div>
|
||||||
: item.event.address
|
<div class="row location">
|
||||||
"
|
<ion-icon name="location-outline" class="icon" />
|
||||||
:banner="item.banner"
|
<div class="text">{{ computedLocation(event) }}</div>
|
||||||
:banner-type="item.bannerType"
|
</div>
|
||||||
:ages="computedAges(item.event)"></SMPanel>
|
<div class="row ages">
|
||||||
</SMPanelList>
|
<ion-icon name="body-outline" class="icon" />
|
||||||
|
<div class="text">{{ computedAges(event.ages) }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="row price">
|
||||||
|
<div class="icon">$</div>
|
||||||
|
<div class="text">{{ computedPrice(event.price) }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
</SMContainer>
|
</SMContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -61,13 +70,10 @@ import { reactive, ref, watch } from "vue";
|
|||||||
import SMInput from "../components/SMInput.vue";
|
import SMInput from "../components/SMInput.vue";
|
||||||
import SMMessage from "../components/SMMessage.vue";
|
import SMMessage from "../components/SMMessage.vue";
|
||||||
import SMPagination from "../components/SMPagination.vue";
|
import SMPagination from "../components/SMPagination.vue";
|
||||||
import SMPanel from "../components/SMPanel.vue";
|
|
||||||
import SMPanelList from "../components/SMPanelList.vue";
|
|
||||||
import SMToolbar from "../components/SMToolbar.vue";
|
import SMToolbar from "../components/SMToolbar.vue";
|
||||||
import { api } from "../helpers/api";
|
import { api } from "../helpers/api";
|
||||||
import { Event, EventCollection } from "../helpers/api.types";
|
import { Event, EventCollection } from "../helpers/api.types";
|
||||||
import { SMDate } from "../helpers/datetime";
|
import { SMDate } from "../helpers/datetime";
|
||||||
import { mediaGetVariantUrl } from "../helpers/media";
|
|
||||||
import SMMastHead from "../components/SMMastHead.vue";
|
import SMMastHead from "../components/SMMastHead.vue";
|
||||||
import SMContainer from "../components/SMContainer.vue";
|
import SMContainer from "../components/SMContainer.vue";
|
||||||
|
|
||||||
@@ -78,7 +84,7 @@ interface EventData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
let events: EventData[] = reactive([]);
|
let events: Event[] = reactive([]);
|
||||||
const dateRangeError = ref("");
|
const dateRangeError = ref("");
|
||||||
|
|
||||||
const formMessage = ref("");
|
const formMessage = ref("");
|
||||||
@@ -87,7 +93,7 @@ const filterKeywords = ref("");
|
|||||||
const filterLocation = ref("");
|
const filterLocation = ref("");
|
||||||
const filterDateRange = ref("");
|
const filterDateRange = ref("");
|
||||||
|
|
||||||
const postsPerPage = 9;
|
const postsPerPage = 24;
|
||||||
let postsPage = ref(1);
|
let postsPage = ref(1);
|
||||||
let postsTotal = ref(0);
|
let postsTotal = ref(0);
|
||||||
|
|
||||||
@@ -209,11 +215,10 @@ const handleLoad = async () => {
|
|||||||
bannerType = "warning";
|
bannerType = "warning";
|
||||||
}
|
}
|
||||||
|
|
||||||
events.push({
|
item["banner"] = banner;
|
||||||
event: item,
|
item["bannerType"] = bannerType;
|
||||||
banner: banner,
|
|
||||||
bannerType: bannerType,
|
events.push(item);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -231,20 +236,86 @@ const handleFilter = async () => {
|
|||||||
handleLoad();
|
handleLoad();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a human readable Date string.
|
||||||
|
*
|
||||||
|
* @param {Event} event The event to convert.
|
||||||
|
* @returns The converted string.
|
||||||
|
*/
|
||||||
|
const computedDate = (event: Event) => {
|
||||||
|
let str = "";
|
||||||
|
|
||||||
|
if (event.start_at.length > 0) {
|
||||||
|
if (
|
||||||
|
event.end_at.length > 0 &&
|
||||||
|
event.start_at.substring(0, event.start_at.indexOf(" ")) !=
|
||||||
|
event.end_at.substring(0, event.end_at.indexOf(" "))
|
||||||
|
) {
|
||||||
|
str = new SMDate(event.start_at, { format: "yMd" }).format(
|
||||||
|
"dd/MM/yyyy"
|
||||||
|
);
|
||||||
|
if (event.end_at.length > 0) {
|
||||||
|
str =
|
||||||
|
str +
|
||||||
|
" - " +
|
||||||
|
new SMDate(event.end_at, { format: "yMd" }).format(
|
||||||
|
"dd/MM/yyyy"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
str = new SMDate(event.start_at, { format: "yMd" }).format(
|
||||||
|
"dd/MM/yyyy @ h:mm aa"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a human readable Location string.
|
||||||
|
*
|
||||||
|
* @param {Event} event The event to convert.
|
||||||
|
* @returns The converted string.
|
||||||
|
*/
|
||||||
|
const computedLocation = (event: Event): string => {
|
||||||
|
if (event.location == "online") {
|
||||||
|
return "Online";
|
||||||
|
}
|
||||||
|
|
||||||
|
return event.address;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a human readable Ages string.
|
* Return a human readable Ages string.
|
||||||
*
|
*
|
||||||
* @param item
|
* @param {string} ages The string to convert.
|
||||||
|
* @returns The converted string.
|
||||||
*/
|
*/
|
||||||
const computedAges = (item: Event): string => {
|
const computedAges = (ages: string): string => {
|
||||||
const trimmed = item.ages.trim();
|
const trimmed = ages.trim();
|
||||||
const regex = /^(\d+)(\s*\+?\s*|\s*-\s*\d+\s*)?$/;
|
const regex = /^(\d+)(\s*\+?\s*|\s*-\s*\d+\s*)?$/;
|
||||||
|
|
||||||
if (regex.test(trimmed)) {
|
if (regex.test(trimmed)) {
|
||||||
return `Ages ${trimmed}`;
|
return `Ages ${trimmed}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return item.ages;
|
return ages;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a human readable Price string.
|
||||||
|
*
|
||||||
|
* @param {string} price The string to convert.
|
||||||
|
* @returns The converted string.
|
||||||
|
*/
|
||||||
|
const computedPrice = (price: string): string => {
|
||||||
|
const trimmed = parseInt(price.trim());
|
||||||
|
if (trimmed == 0) {
|
||||||
|
return "Free";
|
||||||
|
}
|
||||||
|
|
||||||
|
return trimmed.toString();
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
@@ -258,37 +329,109 @@ handleLoad();
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.sm-page-workshop-list {
|
.page-workshops {
|
||||||
background-color: #f8f8f8;
|
.events-list {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 30px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
.toolbar {
|
.event {
|
||||||
display: flex;
|
background-color: var(--base-color-light);
|
||||||
flex-direction: row;
|
box-shadow: 0 5px 10px -3px rgba(0, 0, 0, 0.25);
|
||||||
flex: 1;
|
border-radius: 8px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--base-color-text);
|
||||||
|
|
||||||
& > * {
|
.image {
|
||||||
padding-left: map-get($spacer, 1);
|
width: 100%;
|
||||||
padding-right: map-get($spacer, 1);
|
aspect-ratio: 16 / 9;
|
||||||
|
background-position: center;
|
||||||
&:first-child {
|
background-repeat: no-repeat;
|
||||||
padding-left: 0;
|
background-size: cover;
|
||||||
|
border-radius: 8px 8px 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:last-child {
|
.content {
|
||||||
padding-right: 0;
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin: 0 0 16px 0;
|
||||||
|
font-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-size: 80%;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
width: 20px;
|
||||||
|
text-align: center;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
filter: none;
|
||||||
|
|
||||||
|
.image {
|
||||||
|
filter: brightness(115%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.sm-page-workshop-list .toolbar {
|
.page-workshops {
|
||||||
flex-direction: column;
|
.events-list {
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
& > * {
|
|
||||||
padding-left: 0;
|
|
||||||
padding-right: 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.page-workshops {
|
||||||
|
.events-list {
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// .sm-page-workshop-list {
|
||||||
|
// background-color: #f8f8f8;
|
||||||
|
|
||||||
|
// .toolbar {
|
||||||
|
// display: flex;
|
||||||
|
// flex-direction: row;
|
||||||
|
// flex: 1;
|
||||||
|
|
||||||
|
// & > * {
|
||||||
|
// padding-left: map-get($spacer, 1);
|
||||||
|
// padding-right: map-get($spacer, 1);
|
||||||
|
|
||||||
|
// &:first-child {
|
||||||
|
// padding-left: 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// &:last-child {
|
||||||
|
// padding-right: 0;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @media screen and (max-width: 768px) {
|
||||||
|
// .sm-page-workshop-list .toolbar {
|
||||||
|
// flex-direction: column;
|
||||||
|
|
||||||
|
// & > * {
|
||||||
|
// padding-left: 0;
|
||||||
|
// padding-right: 0;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user