From a12b2124ba8cda86c661cbff27584d00e2f1a560 Mon Sep 17 00:00:00 2001 From: osmannyildiz Date: Sun, 17 Dec 2023 07:53:57 +0300 Subject: [PATCH] add course enrollment --- src/app/kurslar/[courseSlug]/ogren/page.jsx | 44 +- .../[courseSlug]/ogren/page.module.css | 9 +- src/app/kurslar/[courseSlug]/page.jsx | 29 +- src/components/DTLDisplay.jsx | 59 ++ src/components/Header.jsx | 5 +- src/components/WrapperComponent.jsx | 1 + src/contracts.js | 596 ++++++++++++++++++ 7 files changed, 725 insertions(+), 18 deletions(-) create mode 100644 src/components/DTLDisplay.jsx create mode 100644 src/contracts.js diff --git a/src/app/kurslar/[courseSlug]/ogren/page.jsx b/src/app/kurslar/[courseSlug]/ogren/page.jsx index bc94caa..fb9f3a7 100644 --- a/src/app/kurslar/[courseSlug]/ogren/page.jsx +++ b/src/app/kurslar/[courseSlug]/ogren/page.jsx @@ -1,21 +1,26 @@ "use client"; +import { useState } from "react"; import styles from "./page.module.css"; -const Step = ({ step, completed, onClick }) => ( -
onClick()}> - {completed ? "✅" : "◻️"} {step} -
-); +const Step = ({ label }) => { + const [isCompleted, setIsCompleted] = useState(false); + + return ( +
setIsCompleted((val) => !val)}> + + {label} +
+ ); +}; const Home = () => { return (
@@ -25,11 +30,26 @@ const Home = () => {

Kurs İçeriği

- {}} /> - {}} /> - {}} /> + + + + +
+ +
); diff --git a/src/app/kurslar/[courseSlug]/ogren/page.module.css b/src/app/kurslar/[courseSlug]/ogren/page.module.css index c1002f1..17634aa 100644 --- a/src/app/kurslar/[courseSlug]/ogren/page.module.css +++ b/src/app/kurslar/[courseSlug]/ogren/page.module.css @@ -4,7 +4,8 @@ .sidebar { width: 500px; - padding: 50px; + padding: 20px; + padding-top: 0; border-left: 2px solid #ccc; } @@ -15,16 +16,18 @@ .courseContent { flex: 1; - padding: 10px; } .step { cursor: pointer; margin-bottom: 10px; + padding: 1rem; + background-color: var(--color-bg1); + border-radius: var(--border-radius); } .video { - width: 120%; + width: 100%; max-width: 1000px; aspect-ratio: 16 / 9; display: block; diff --git a/src/app/kurslar/[courseSlug]/page.jsx b/src/app/kurslar/[courseSlug]/page.jsx index 10bd7cf..0c16034 100644 --- a/src/app/kurslar/[courseSlug]/page.jsx +++ b/src/app/kurslar/[courseSlug]/page.jsx @@ -1,12 +1,33 @@ +"use client"; + import Container from "@/components/Container"; +import { CubLearn } from "@/contracts"; import { COURSES } from "@/mockData"; import { cn, formatPrice } from "@/utils"; import Link from "next/link"; +import { useContractRead, useContractWrite, useWalletClient } from "wagmi"; import styles from "./page.module.css"; export default function CourseDetailPage({ params }) { + const { data: walletClient } = useWalletClient(); + const course = COURSES.find((c) => c.slug === params.courseSlug); + const amIEnrolledInCourse = useContractRead({ + address: CubLearn.address, + abi: CubLearn.abi, + functionName: "amIEnrolledInCourse", + args: [course.id], + account: walletClient?.account, + }); + + const enroll = useContractWrite({ + address: CubLearn.address, + abi: CubLearn.abi, + functionName: "enroll", + args: [course.id], + }); + return (
@@ -19,7 +40,7 @@ export default function CourseDetailPage({ params }) {

{course.name}

{course.instructor.name}
- {true ? ( + {amIEnrolledInCourse.data ? ( ) : ( - )} diff --git a/src/components/DTLDisplay.jsx b/src/components/DTLDisplay.jsx new file mode 100644 index 0000000..ca95a2e --- /dev/null +++ b/src/components/DTLDisplay.jsx @@ -0,0 +1,59 @@ +"use client"; + +import { CubLearn, DTLToken } from "@/contracts"; +import { useEffect } from "react"; +import { + useAccount, + useContractRead, + useContractWrite, + usePrepareContractWrite, + useWalletClient, +} from "wagmi"; + +export default function DTLDisplay() { + const { address } = useAccount(); + const { data: walletClient } = useWalletClient(); + + const getMyBalance = useContractRead({ + address: DTLToken.address, + abi: DTLToken.abi, + functionName: "getMyBalance", + account: walletClient?.account, + }); + + const getAllowanceOfSpender = useContractRead({ + address: DTLToken.address, + abi: DTLToken.abi, + functionName: "getAllowanceOfSpender", + args: [CubLearn.address], + account: walletClient?.account, + }); + + const { config: approveMaxConfig } = usePrepareContractWrite({ + address: DTLToken.address, + abi: DTLToken.abi, + functionName: "approveMax", + args: [CubLearn.address], + }); + const approveMax = useContractWrite(approveMaxConfig); + + useEffect(() => { + if (address) { + getMyBalance.refetch(); + } + }, [address]); + + return !getAllowanceOfSpender.data || getAllowanceOfSpender.data === 0n ? ( + + ) : ( + + ); +} diff --git a/src/components/Header.jsx b/src/components/Header.jsx index d09f5fe..ba483fd 100644 --- a/src/components/Header.jsx +++ b/src/components/Header.jsx @@ -1,6 +1,7 @@ import { cn } from "@/utils"; import { ConnectButton } from "@rainbow-me/rainbowkit"; import Link from "next/link"; +import DTLDisplay from "./DTLDisplay"; import styles from "./Header.module.css"; export default function Header() { @@ -16,7 +17,9 @@ export default function Header() { Hesabım - + + +
); diff --git a/src/components/WrapperComponent.jsx b/src/components/WrapperComponent.jsx index 8ebe652..3b0fafe 100644 --- a/src/components/WrapperComponent.jsx +++ b/src/components/WrapperComponent.jsx @@ -33,6 +33,7 @@ export default function WrapperComponent({ children }) { accentColor: "var(--color-accent)", })} locale="tr-TR" + coolMode > {children} diff --git a/src/contracts.js b/src/contracts.js new file mode 100644 index 0000000..5f820a4 --- /dev/null +++ b/src/contracts.js @@ -0,0 +1,596 @@ +export const DTLToken = { + address: "0x205A56Be24CC41d32f1Ec64D19954e9e86398ceC", + abi: [ + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "allowance", + type: "uint256", + }, + { + internalType: "uint256", + name: "needed", + type: "uint256", + }, + ], + name: "ERC20InsufficientAllowance", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "sender", + type: "address", + }, + { + internalType: "uint256", + name: "balance", + type: "uint256", + }, + { + internalType: "uint256", + name: "needed", + type: "uint256", + }, + ], + name: "ERC20InsufficientBalance", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "approver", + type: "address", + }, + ], + name: "ERC20InvalidApprover", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "receiver", + type: "address", + }, + ], + name: "ERC20InvalidReceiver", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "sender", + type: "address", + }, + ], + name: "ERC20InvalidSender", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + ], + name: "ERC20InvalidSpender", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "spender", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "from", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "to", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Transfer", + type: "event", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "approve", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + ], + name: "approveMax", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "transfer", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "transferFrom", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "initialHolder", + type: "address", + }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "address", + name: "spender", + type: "address", + }, + ], + name: "allowance", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "balanceOf", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "decimals", + outputs: [ + { + internalType: "uint8", + name: "", + type: "uint8", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + ], + name: "getAllowanceOfSpender", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getMyBalance", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "symbol", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "totalSupply", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + ], +}; + +export const CubLearn = { + address: "0x2eA6235131CC9233aAD3842C5d14C9Cf7107FdA1", + abi: [ + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + ], + name: "OwnableInvalidOwner", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "OwnableUnauthorizedAccount", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "previousOwner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "OwnershipTransferred", + type: "event", + }, + { + inputs: [ + { + internalType: "string", + name: "courseId", + type: "string", + }, + ], + name: "enroll", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "string", + name: "courseId", + type: "string", + }, + { + internalType: "string", + name: "studentFullName", + type: "string", + }, + { + internalType: "string", + name: "courseName", + type: "string", + }, + { + internalType: "string", + name: "instructorFullName", + type: "string", + }, + ], + name: "finishCourse", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "renounceOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "newValue", + type: "uint256", + }, + ], + name: "setCashbackPercentage", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "transferAllDTLBalanceToMe", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "dtlContractAddress", + type: "address", + }, + { + internalType: "address", + name: "cubcertContractAddress", + type: "address", + }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + inputs: [ + { + internalType: "string", + name: "courseId", + type: "string", + }, + ], + name: "amIEnrolledInCourse", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "cashbackPercentage", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "string", + name: "courseId", + type: "string", + }, + ], + name: "didICompleteCourse", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "getDTLBalance", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "owner", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + ], +};