Skip to content

Commit 9337aee

Browse files
author
Rajat Saxena
committed
WIP: Courses migrated to membership; testing required
1 parent c110373 commit 9337aee

67 files changed

Lines changed: 1930 additions & 1340 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// create a free payment plan for all domains
2+
3+
import mongoose from "mongoose";
4+
import { nanoid } from "nanoid";
5+
6+
function generateUniqueId() {
7+
return nanoid();
8+
}
9+
10+
mongoose.connect(process.env.DB_CONNECTION_STRING, {
11+
useNewUrlParser: true,
12+
useUnifiedTopology: true,
13+
});
14+
15+
const PaymentPlanSchema = new mongoose.Schema(
16+
{
17+
domain: { type: mongoose.Schema.Types.ObjectId, required: true },
18+
planId: {
19+
type: String,
20+
required: true,
21+
unique: true,
22+
default: generateUniqueId,
23+
},
24+
name: { type: String, required: true },
25+
type: {
26+
type: String,
27+
required: true,
28+
},
29+
oneTimeAmount: { type: Number },
30+
emiAmount: { type: Number },
31+
emiTotalInstallments: { type: Number },
32+
subscriptionMonthlyAmount: { type: Number },
33+
subscriptionYearlyAmount: { type: Number },
34+
userId: { type: String, required: true },
35+
archived: { type: Boolean, default: false },
36+
internal: { type: Boolean, default: false },
37+
},
38+
{
39+
timestamps: true,
40+
},
41+
);
42+
43+
PaymentPlanSchema.pre("save", async function (next) {
44+
if (this.internal) {
45+
const existingInternalPlan = await this.constructor.findOne({
46+
domain: this.domain,
47+
internal: true,
48+
_id: { $ne: this._id },
49+
});
50+
51+
if (existingInternalPlan) {
52+
const error = new Error(
53+
"Only one internal payment plan allowed per domain",
54+
);
55+
return next(error);
56+
}
57+
58+
if (this.type !== "free") {
59+
const error = new Error("Internal payment plans must be free");
60+
return next(error);
61+
}
62+
}
63+
next();
64+
});
65+
66+
const PaymentPlan = mongoose.model("PaymentPlan", PaymentPlanSchema);
67+
68+
const DomainSchema = new mongoose.Schema({
69+
name: { type: String, required: true, unique: true },
70+
});
71+
72+
const Domain = mongoose.model("Domain", DomainSchema);
73+
74+
const UserSchema = new mongoose.Schema({
75+
userId: { type: String, required: true, default: generateUniqueId },
76+
email: { type: String, required: true },
77+
});
78+
const User = mongoose.model("User", UserSchema);
79+
80+
const setupFreePayment = async () => {
81+
const domains = await Domain.find({}, { name: 1 });
82+
for (const domain of domains) {
83+
const creator = await User.findOne({
84+
domain: domain._id,
85+
permissions: { $elemMatch: { $eq: "site:manage" } },
86+
});
87+
const paymentPlan = await PaymentPlan.create({
88+
domain: domain._id,
89+
name: "Internal Payment Plan",
90+
internal: true,
91+
type: "free",
92+
userId: creator.userId,
93+
});
94+
console.log(
95+
`Added payment plan for '${domain.name}':`,
96+
paymentPlan.planId,
97+
);
98+
}
99+
};
100+
101+
(async () => {
102+
await setupFreePayment();
103+
mongoose.connection.close();
104+
})();

apps/web/.migrations/migrate-customers-to-memberships.js

Whitespace-only changes.

apps/web/app/(with-contexts)/(with-layout)/checkout/page.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export default function CheckoutPage() {
2323

2424
const getProduct = useCallback(async () => {
2525
const query = `
26-
query ($id: String) {
26+
query ($id: String!) {
2727
course: getCourse(id: $id) {
2828
courseId
2929
title
@@ -42,6 +42,7 @@ export default function CheckoutPage() {
4242
subscriptionMonthlyAmount
4343
subscriptionYearlyAmount
4444
}
45+
defaultPaymentPlan
4546
}
4647
}
4748
`;

apps/web/app/(with-contexts)/dashboard/(sidebar)/my-content/page.tsx

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
"use client";
22

33
import { useState, useEffect, useContext } from "react";
4-
import { ContentCard } from "@/components/admin/my-content/content-card";
4+
// import { ContentCard } from "@/components/admin/my-content/content-card";
55
import { SkeletonCard } from "@/components/admin/my-content/skeleton-card";
66
import type { ContentItem } from "@/components/admin/my-content/content";
77
import { AddressContext, ProfileContext } from "@components/contexts";
88
import { MY_CONTENT_HEADER } from "@ui-config/strings";
99
import DashboardContent from "@components/admin/dashboard-content";
1010
import { FetchBuilder } from "@courselit/utils";
1111
import { Constants, MembershipEntityType } from "@courselit/common-models";
12-
import { Link } from "@courselit/components-library";
12+
import { MyContentCard } from "@components/admin/my-content/content-card";
1313

1414
function ContentGrid({
1515
items,
@@ -21,16 +21,10 @@ function ContentGrid({
2121
return (
2222
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
2323
{items.map((item) => (
24-
<Link
24+
<MyContentCard
2525
key={item.entity.id}
26-
href={
27-
type === Constants.MembershipEntityType.COURSE
28-
? `/course/${item.entity.slug}/${item.entity.id}`
29-
: `/dashboard/community/${item.entity.id}`
30-
}
31-
>
32-
<ContentCard item={item} />
33-
</Link>
26+
item={item}
27+
/>
3428
))}
3529
</div>
3630
);
@@ -70,6 +64,7 @@ export default function Page() {
7064
file
7165
thumbnail
7266
}
67+
type
7368
}
7469
}
7570
}

apps/web/app/(with-contexts)/dashboard/(sidebar)/my-content/page2.tsx

Lines changed: 0 additions & 111 deletions
This file was deleted.

0 commit comments

Comments
 (0)