2025-12-23 20:48:07 +08:00

223 lines
5.2 KiB
Vue

<template>
<Dialog :options="{ title: 'Edit Plan' }" v-model="showEditPlanDialog">
<template v-slot:body-content>
<div>
<div class="mb-4">
<input
type="checkbox"
id="enabled-checkbox"
class="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500"
v-model="currentEditingPlan.enabled"
/>
<label for="enabled-checkbox" class="ml-1 text-sm text-gray-900">
Enabled
</label>
</div>
<div class="mb-4">
<FormControl
placeholder="My Pro Plan"
label="Name"
v-model="currentEditingPlan.title"
></FormControl>
</div>
<div class="mb-8">
<h3 class="mb-4 text-lg font-semibold">Subscription Price</h3>
<div class="grid grid-cols-2 gap-2">
<FormControl
label="Price INR"
v-model="currentEditingPlan.price_inr"
></FormControl>
<FormControl
label="Price USD"
v-model="currentEditingPlan.price_usd"
></FormControl>
</div>
</div>
<div>
<h3 class="mb-4 text-lg font-semibold">Features</h3>
<div>
<div
v-for="(feature, idx) in currentEditingPlan.features"
class="mb-3.5 flex w-full items-stretch"
>
<div
class="mr-3 flex h-6 w-6 items-center justify-center rounded-full bg-gray-100 text-xs"
>
{{ idx + 1 }}
</div>
<div class="w-full">
<FormControl
class="w-full"
v-model="currentEditingPlan.features[idx]"
></FormControl>
</div>
<Button
v-if="idx > 0"
class="ml-3 rounded-full"
icon="x"
@click="deleteFeatureInput(idx)"
></Button>
</div>
</div>
<div>
<Button icon-left="plus" @click="addFeatureInput">Add</Button>
</div>
<div>
<ErrorMessage
class="mt-3"
:message="$resources.updateAppPlan.error"
/>
<ErrorMessage
class="mt-3"
:message="$resources.createAppPlan.error"
/>
</div>
</div>
</div>
</template>
<template #actions>
<Button
class="w-full"
variant="solid"
:loading="
$resources.updateAppPlan.loading || $resources.createAppPlan.loading
"
@click="savePlan"
@close="resetCurrentEditingPlan"
>Save</Button
>
</template>
</Dialog>
</template>
<script>
import { toast } from 'vue-sonner';
import { DashboardError } from '../../utils/error';
import { getToastErrorMessage } from '../../utils/toast';
export default {
name: 'PlanDialog',
props: ['app', 'plan'],
emits: ['plan-created', 'plan-updated'],
data() {
return {
showEditPlanDialog: true,
currentEditingPlan: {
price_inr: 0,
price_usd: 0,
features: [''],
title: '',
enabled: true,
},
};
},
mounted() {
if (this.plan) {
Object.assign(this.currentEditingPlan, this.plan);
this.currentEditingPlan.enabled = Boolean(this.plan.enabled);
this.currentEditingPlan.features = Array.from(this.plan.features); // Non-reference copy
}
},
resources: {
appPlans() {
return {
url: 'jcloude.api.marketplace.get_app_plans',
params: {
app: this.app,
include_disabled: true,
},
auto: true,
};
},
updateAppPlan() {
return {
url: 'jcloude.api.marketplace.update_app_plan',
onSuccess() {
this.refreshState();
},
};
},
createAppPlan() {
return {
url: 'jcloude.api.marketplace.create_app_plan',
validate() {
if (!this.currentEditingPlan.title) {
throw new DashboardError('Plan name is required');
}
},
onSuccess() {
this.refreshState();
},
};
},
},
methods: {
editPlan() {
if (this.plan) {
Object.assign(this.currentEditingPlan, this.plan);
this.currentEditingPlan.enabled = Boolean(this.plan.enabled);
this.currentEditingPlan.features = Array.from(this.plan.features); // Non-reference copy
}
this.showEditPlanDialog = true;
},
addFeatureInput() {
this.currentEditingPlan.features.push('');
},
deleteFeatureInput(idx) {
this.currentEditingPlan.features.splice(idx, 1);
},
savePlan() {
toast.promise(
this.currentEditingPlan.name
? this.$resources.updateAppPlan.submit({
app_plan_name: this.currentEditingPlan.name,
updated_plan_data: this.currentEditingPlan,
})
: this.$resources.createAppPlan.submit({
plan_data: this.currentEditingPlan,
marketplace_app: this.app,
}),
{
loading: 'Saving plan...',
success: () => {
this.showEditPlanDialog = false;
if (this.currentEditingPlan.name) {
this.$emit('plan-updated', this.currentEditingPlan);
return 'Plan updated successfully';
} else {
this.$emit('plan-created', this.currentEditingPlan);
return 'Plan created successfully';
}
},
error: (e) => getToastErrorMessage(e),
},
);
},
refreshState() {
this.$resources.appPlans.fetch();
this.showEditPlanDialog = false;
this.resetCurrentEditingPlan();
},
resetCurrentEditingPlan() {
Object.assign(this.currentEditingPlan, {
price_inr: 0,
price_usd: 0,
features: [''],
title: '',
enabled: true,
});
this.$resources.updateAppPlan.error = null;
this.$resources.createAppPlan.error = null;
},
},
};
</script>