-
{{ eventTypeText(scope.row.event_type) }}
{{ scope.row.status }}
{{ formatDate(scope.row.start_time) }}
{{ formatDate(scope.row.end_time) }}
{{ scope.row.current_products }}
No Image
{{ pp.product_title }}
Yes
-
{{ formatDate(scope.row.created_at) }}
✓ Enrolled
View ({{ scope.row.enrolled_product_count }})
Add More
Add More
Enroll
Enroll
Enrollment closed
{{ enrollEventName }}
{{ p.name }}
Cancel
Confirm
{{ themeEnrollEventName }}
+ Add Proposal
Cancel
Confirm
Type
{{ eventTypeText(row.event_type) }}
Time
{{ formatDate(row.start_time) }} ~ {{ formatDate(row.end_time) }}
Products
{{ row.current_products || 0 }}
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');