diff --git a/src/components/VContentSwitcher/VContentSwitcherButton.vue b/src/components/VContentSwitcher/VContentSwitcherButton.vue new file mode 100644 index 0000000000..09042091e0 --- /dev/null +++ b/src/components/VContentSwitcher/VContentSwitcherButton.vue @@ -0,0 +1,85 @@ + + diff --git a/src/components/VContentSwitcher/VContentSwitcherPopover.vue b/src/components/VContentSwitcher/VContentSwitcherPopover.vue new file mode 100644 index 0000000000..8acec2b724 --- /dev/null +++ b/src/components/VContentSwitcher/VContentSwitcherPopover.vue @@ -0,0 +1,68 @@ + + + diff --git a/src/components/VContentSwitcher/VContentTypes.vue b/src/components/VContentSwitcher/VContentTypes.vue new file mode 100644 index 0000000000..053480f536 --- /dev/null +++ b/src/components/VContentSwitcher/VContentTypes.vue @@ -0,0 +1,59 @@ + + diff --git a/src/composables/use-content-type.js b/src/composables/use-content-type.js new file mode 100644 index 0000000000..20cc551b6a --- /dev/null +++ b/src/composables/use-content-type.js @@ -0,0 +1,34 @@ +import { computed, ref, useContext } from '@nuxtjs/composition-api' +import { supportedContentTypes } from '~/constants/media' +import { SEARCH } from '~/constants/store-modules' +import { UPDATE_QUERY } from '~/constants/action-types' +import allIcon from '~/assets/icons/all-content.svg' +import audioIcon from '~/assets/icons/audio-content.svg' +import imageIcon from '~/assets/icons/image-content.svg' + +const icons = { + all: allIcon, + audio: audioIcon, + image: imageIcon, +} +export default function useContentType() { + const { store } = useContext() + + const contentTypes = [...supportedContentTypes] + + const activeType = computed(() => store.state.search.searchType) + const previousContentType = ref(activeType.value) + const setActiveType = async (contentType) => { + if (previousContentType.value === contentType) return + await store.dispatch(`${SEARCH}/${UPDATE_QUERY}`, { + searchType: contentType, + }) + previousContentType.value = contentType + } + return { + setActiveType, + activeType, + types: contentTypes, + icons, + } +} diff --git a/src/constants/media.js b/src/constants/media.js index 6a7b7e570f..852d89deec 100644 --- a/src/constants/media.js +++ b/src/constants/media.js @@ -5,11 +5,15 @@ export const ALL_MEDIA = 'all' /** @typedef {typeof AUDIO | typeof IMAGE | typeof VIDEO | typeof ALL_MEDIA} MediaType */ -// Media types -/** @type {MediaType[]} */ -export const mediaTypes = [AUDIO, IMAGE] -// Media types which support custom filters -/** @type {MediaType[]} */ -export const supportedMediaTypes = [AUDIO, IMAGE, VIDEO] -/** @type {MediaType[]} */ -export const allMediaTypes = [ALL_MEDIA, IMAGE, AUDIO, VIDEO] +/** + * Media types that the API supports. + * These types also support custom filters. + * @type {MediaType[]} + */ +export const supportedMediaTypes = [IMAGE, AUDIO] + +/** + * The types of content that users can search. `All` is also an option here. + * @type {MediaType[]} + */ +export const supportedContentTypes = [ALL_MEDIA, IMAGE, AUDIO] diff --git a/src/locales/en.json b/src/locales/en.json index da716e56ea..55de052caf 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -690,5 +690,13 @@ "interpunct": "•", "modal": { "close": "Close" + }, + "search-type": { + "image": "Images", + "audio": "Audio", + "all": "All content", + "video": "Videos", + "label": "Type of content to search", + "heading": "Content types" } } diff --git a/src/locales/po-files/openverse.pot b/src/locales/po-files/openverse.pot index 0251efa53f..fcfe6f228c 100644 --- a/src/locales/po-files/openverse.pot +++ b/src/locales/po-files/openverse.pot @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: Openverse \n" "Report-Msgid-Bugs-To: https://github.com/wordpress/openverse/issues \n" -"POT-Creation-Date: 2022-01-19T10:51:29+00:00\n" +"POT-Creation-Date: 2022-01-19T15:13:27+00:00\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -18,6 +18,31 @@ msgctxt "interpunct" msgid "•" msgstr "" +msgctxt "search-type.image" +msgid "Images" +msgstr "" + +msgctxt "search-type.audio" +msgid "Audio" +msgstr "" + +msgctxt "search-type.all" +msgid "All content" +msgstr "" + +msgctxt "search-type.video" +msgid "Videos" +msgstr "" + +#: src/components/VContentSwitcher/VContentSwitcherPopover.vue:5 +msgctxt "search-type.label" +msgid "Type of content to search" +msgstr "" + +msgctxt "search-type.heading" +msgid "Content types" +msgstr "" + #: src/components/VModal/VModalContent.vue:25 msgctxt "modal.close" msgid "Close" @@ -2135,12 +2160,12 @@ msgid "I want something I can" msgstr "" #. Do not translate words between ### ###. -#: src/pages/index.vue:18 +#: src/pages/index.vue:26 msgctxt "hero.disclaimer.content" msgid "All our content is under a ###license### or in the public domain." msgstr "" -#: src/pages/index.vue:27 +#: src/pages/index.vue:35 msgctxt "hero.disclaimer.license" msgid "Creative Commons license" msgstr "" diff --git a/src/pages/index.vue b/src/pages/index.vue index da6d3c61ea..0b3b79a117 100644 --- a/src/pages/index.vue +++ b/src/pages/index.vue @@ -13,7 +13,15 @@

{{ $t('hero.subtitle') }}

- + + + @@ -140,8 +154,33 @@ const HomePage = { } }) + const isMounted = ref(false) + onMounted(() => { + isMounted.value = true + }) + onBeforeUnmount(() => { + isMounted.value = false + }) + + const isMinScreenMd = isMinScreen('md', { shouldPassInSSR: true }) + + const contentSwitcher = ref(null) + const contentType = ref(ALL_MEDIA) + const setContentType = (type) => { + contentType.value = type + contentSwitcher.value?.closeMenu() + } + return { featuredSearch, + + isMounted, + + isMinScreenMd, + + contentSwitcher, + contentType, + setContentType, } }, }