Filter
{{ enrollEventName }}
{{ p.name }}
{{ themeEnrollEventName }}
Proposal {{ pIndex + 1 }} Remove
+ Add Proposal
{{ row.event_name }}
{{ row.status }}
Type {{ eventTypeText(row.event_type) }}
Time {{ formatDate(row.start_time) }} ~ {{ formatDate(row.end_time) }}
Products {{ row.current_products || 0 }}
No Image
{{ pp.product_title }}
Creators {{ row.current_creators || 0 }}
Featured Yes
Enroll Closed
Enroll Closed
✓ Enrolled View ({{ row.enrolled_product_count }}) Add Add
=> p.submission_type === 1 && p.shopify_product_id) .map(p => ({ id: p.shopify_product_id, name: p.product_title })); const existingProductIds = this._enrolledProducts.map(p => p.id); this.enrollForm.product_ids = existingProductIds; console.log('Loaded existing products (shopify IDs):', existingProductIds); } else { this.enrollForm.product_ids = []; } this.enrollDialogVisible = true; this.$nextTick(() => { this.$refs.enrollFormRef && this.$refs.enrollFormRef.clearValidate(); }); await this.fetchEnrollProducts(); }, removeSelectedProduct(id) { this.enrollForm.product_ids = this.enrollForm.product_ids.filter(x => x !== id); }, async fetchEnrollProducts() { this.enrollProductLoading = true; try { const res = await fetch(API_ENDPOINT + '/get-products.php', { method: 'POST', headers: { 'Content-Type': 'application/json','X-API-KEY': API_KEY }, body: JSON.stringify({ page: 1, pageSize: 10000, filters: { name: '', category: '', state: 'active', tags: '' }, customerId: SHOPIFY_CUSTOMER_ID, }), }); const data = await res.json(); if (data.code == '200') { const list = Array.isArray(data.products) ? data.products : []; let allProducts = list.filter(p => !(p.tags && p.tags.includes('customer_delete'))); // Only show products owned by this creator (already enrolled ones are pre-selected below) this.enrollProductOptions = allProducts; // Merge enrolled products that are not in the options list if (this._enrolledProducts && this._enrolledProducts.length) { const existingIds = new Set(this.enrollProductOptions.map(p => p.id)); for (const ep of this._enrolledProducts) { if (!existingIds.has(ep.id)) { this.enrollProductOptions.unshift({ id: ep.id, name: ep.name }); } } } } else { ElementPlus.ElMessage.error(data.msg || 'Failed to load products'); } } catch (err) { console.error(err); ElementPlus.ElMessage.error('Failed to load products'); } finally { this.enrollProductLoading = false; } }, async submitEnroll() { try { await this.$refs.enrollFormRef.validate(); } catch { return; } this.enrollLoading = true; try { const productIds = this.enrollForm.product_ids.map(id => { const extracted = this.extractProductId(id); const num = Number(extracted); return Number.isNaN(num) ? extracted : num; }); // Build product_urls map: GID => link const productUrls = {}; for (const p of this.enrollProductOptions) { if (p.link) { productUrls[p.id] = p.link; } } const res = await fetch(API_ENDPOINT + '/event/enroll-event.php', { method: 'POST', headers: { 'Content-Type': 'application/json','X-API-KEY': API_KEY }, body: JSON.stringify({ customer_id: Number(SHOPIFY_CUSTOMER_ID) || SHOPIFY_CUSTOMER_ID, event_id: this.enrollEventId, product_ids: productIds, product_urls: productUrls, }), }); const data = await res.json(); if (data.code == '200') { ElementPlus.ElMessage.success('Enrolled successfully'); this.enrollDialogVisible = false; this.fetchEvents(); } else { ElementPlus.ElMessage.error(data.msg || 'Enroll failed'); } } catch (err) { console.error(err); ElementPlus.ElMessage.error('Request failed'); } finally { this.enrollLoading = false; } }, createEmptyProposal() { return { title: '', description: '', images: [], uploading: false }; }, openThemeEnrollDialog(row) { this.themeEnrollEventId = row.id; this.themeEnrollEventName = row.event_name; this.themeEnrollForm.proposals = [this.createEmptyProposal()]; this.themeEnrollDialogVisible = true; this.$nextTick(() => { this.$refs.themeEnrollFormRef && this.$refs.themeEnrollFormRef.clearValidate(); }); }, addProposal() { this.themeEnrollForm.proposals.push(this.createEmptyProposal()); }, removeProposal(index) { this.themeEnrollForm.proposals.splice(index, 1); }, removeProposalImage(pIndex, imgIndex) { this.themeEnrollForm.proposals[pIndex].images.splice(imgIndex, 1); }, async uploadShopifyImage(file) { const res = await fetch(API_ENDPOINT + '/get-upload-url.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ filename: file.name, mimeType: file.type, resource: 'IMAGE', fileSize: file.size, }), }); const target = await res.json(); if (!target || !target.url) { throw new Error('Failed to get upload URL'); } const formData = new FormData(); (target.parameters || []).forEach(param => formData.append(param.name, param.value)); formData.append('file', file); const resUpload = await fetch(target.url, { method: 'POST', body: formData }); if (!resUpload.ok) { throw new Error('Upload failed'); } return target.resourceUrl; }, async uploadProposalImage(e, pIndex) { const proposal = this.themeEnrollForm.proposals[pIndex]; if (proposal.images.length >= 5) { ElementPlus.ElMessage.warning('Maximum 5 images per proposal'); e.onError && e.onError(new Error('Limit reached')); return; } proposal.uploading = true; try { const url = await this.uploadShopifyImage(e.file); proposal.images.push(url); e.onSuccess && e.onSuccess(); } catch (err) { console.error(err); ElementPlus.ElMessage.error('Upload failed'); e.onError && e.onError(err); } finally { proposal.uploading = false; } }, async submitThemeEnroll() { try { await this.$refs.themeEnrollFormRef.validate(); } catch { return; } this.themeEnrollLoading = true; try { const proposals = this.themeEnrollForm.proposals.map(p => ({ title: p.title, description: p.description, images: [...p.images], })); const res = await fetch(API_ENDPOINT + '/event/enroll-event.php', { method: 'POST', headers: { 'Content-Type': 'application/json' ,'X-API-KEY': API_KEY}, body: JSON.stringify({ customer_id: Number(SHOPIFY_CUSTOMER_ID) || SHOPIFY_CUSTOMER_ID, event_id: this.themeEnrollEventId, proposals, }), }); const data = await res.json(); if (data.code == '200') { ElementPlus.ElMessage.success('Enrolled successfully'); this.themeEnrollDialogVisible = false; this.fetchEvents(); } else { ElementPlus.ElMessage.error(data.msg || 'Enroll failed'); } } catch (err) { console.error(err); ElementPlus.ElMessage.error('Request failed'); } finally { this.themeEnrollLoading = false; } }, viewMyProducts(event) { // Navigate to creator's event products page window.location.href = `/pages/my-event-products?event_id=${event.id}&event_name=${encodeURIComponent(event.event_name)}`; }, }, }) eventListApp.use(ElementPlus); for (const [key, component] of Object.entries(ElementPlusIconsVue)) { eventListApp.component(key, component); } eventListApp.mount('#event-list-app');