ndimatteo / HULL

💀 Headless Shopify Starter – powered by Next.js + Sanity.io
https://hull.dev
MIT License
1.36k stars 167 forks source link

How to add separate photo gallery for each specific variant combination? #101

Closed ansmlc closed 1 year ago

ansmlc commented 2 years ago

For example, I'm selling safety glasses which have following variants:

In shopify, each variant combination is automatically grouped and can have separate price, e.g:

Likewise, in Sanity, I'd like to upload photos for each variant combination separately. So if a user has "Yellow" color selected, and than switches between "Clear" or "Tinted", the gallery should show different photos.

I guess I could "hardcode" each combination as a single variant in Shopify, but than on the front-end the options won't be visually separated which makes UX more complicated.

Is there a way to do this? Am I missing something? If not, can you give me an idea on how to go about implementing this?

Thanks!

ndimatteo commented 2 years ago

Hey there @ansmlc!

This is a great question, and is totally possible! Currently, galleries are associated by selecting a single variant option, like Color: Yellow (see here).

Then, on the front-end, when you select a variant (i.e. Yellow / Tinted), it sees if there is a gallery setup that matches one of the selected variant options (see here).

In order to achieve what you're after, two things would need to happen:

  1. Update the Schema, to allow the ability to associate more than one option (likely with an AND/OR association as well)
  2. Update the front-end to find a gallery with the most matches (instead of just accounting for the single match)

With that, you could create a gallery for Yellow AND Tinted, and then when a selected variant has both of those options, it would show that gallery instead of whatever fallback you may have.

I hope that points you in the right direction! If you wind up creating this, feel free to share your solution and/or send a PR

ndimatteo commented 2 years ago

Another idea that would work for shops with products that don't have many** variants:

Rather than the forOption approach, you could change the entire setup to be an array of references, where you would manually select all the variants to associate with a gallery.

** this could get cumbersome with a product that has 50, 100, etc. variants. The forOption approach might be easier to manage, in cases like that.

ansmlc commented 2 years ago

@ndimatteo Thank You! I'll try out these suggestions and update the thread when I settle on a solution.

Edit: closed by accident

ansmlc commented 1 year ago

I tried to making it with an array of references but for some reason it kept returning all variants instead of just the selected one (I'm not very familiar with GROQ). So I ended up manually adding a hard-coded list of string options, like so:

    {
      title: 'Variants',
      name: 'selectVariant',
      type: 'string',
      options: {
        list: [
          { title: 'Clear - Black', value: 'clearblack' },
          { title: 'Clear - Yellow', value: 'clearyellow' },
          { title: 'Clear - Blue', value: 'clearblue' },
          { title: 'Clear - Pink', value: 'clearpink' },
          { title: 'Clear - Purple', value: 'clearpurple' },
          { title: 'Tinted - Black', value: 'tintedblack' },
          { title: 'Tinted - Yellow', value: 'tintedyellow' },
          { title: 'Tinted - Blue', value: 'tintedblue' },
          { title: 'Tinted - Pink', value: 'tintedpink' },
          { title: 'Tinted - Purple', value: 'tintedpurple' },
        ],
      },
    },

And than on the front-end:

const [ selectedSet, setSelectedSet ] = useState({});

  let optionsValues = []
  options.forEach((option) => {
    optionsValues.push(option.value)
  });

  const optionsJoined = optionsValues.join('').toLowerCase();

  const defaultPhotoset = photosets.find((set) => set.selectVariant === 'clearblack')

  useEffect(() => {
    photosets.forEach((set) => {
      if (set.selectVariant == optionsJoined) {
        setSelectedSet(set)
      } 
    }
  )},[optionsJoined]);

  const photos = Object.keys(selectedSet).length ? selectedSet?.photos
    : defaultPhotoset?.photos
ndimatteo commented 1 year ago

Hey there @ansmlc,

Without seeing what your GROQ looked like or how you set up the array of references field, it's hard to say what the issue could've been.

It seems like you found a solution, though I would caution against manually setting these values as they will be different for every product, and can get out of sync with Shopify if variants are ever added.

I'm going to mark this issue as closed, but feel free to continue to post comments if you need anything else!