add course enrollment
This commit is contained in:
parent
c7ce43eee8
commit
a12b2124ba
|
|
@ -1,21 +1,26 @@
|
|||
"use client";
|
||||
import { useState } from "react";
|
||||
import styles from "./page.module.css";
|
||||
|
||||
const Step = ({ step, completed, onClick }) => (
|
||||
<div className={styles.step} onClick={() => onClick()}>
|
||||
{completed ? "✅" : "◻️"} {step}
|
||||
</div>
|
||||
);
|
||||
const Step = ({ label }) => {
|
||||
const [isCompleted, setIsCompleted] = useState(false);
|
||||
|
||||
return (
|
||||
<div className={styles.step} onClick={() => setIsCompleted((val) => !val)}>
|
||||
<input type="checkbox" checked={isCompleted} />
|
||||
<span style={{ marginLeft: "0.5rem" }}>{label}</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const Home = () => {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.videoContainer}>
|
||||
<iframe
|
||||
src="https://www.youtube.com/embed/VIDEO_ID"
|
||||
title="YouTube video player"
|
||||
frameBorder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
src="https://www.youtube.com/embed/r3P58Y1OL0g"
|
||||
// frameBorder="0"
|
||||
allow="autoplay; encrypted-media"
|
||||
allowFullScreen
|
||||
className={styles.video}
|
||||
></iframe>
|
||||
|
|
@ -25,11 +30,26 @@ const Home = () => {
|
|||
<div className={styles.courseContainer}>
|
||||
<h2>Kurs İçeriği</h2>
|
||||
<div className={styles.courseContent}>
|
||||
<Step step="Adım 1" completed={false} onClick={() => {}} />
|
||||
<Step step="Adım 2" completed={false} onClick={() => {}} />
|
||||
<Step step="Adım 3" completed={false} onClick={() => {}} />
|
||||
<Step label="1. Blokzincir Nedir?" />
|
||||
<Step label="2. Kullanım Alanları" />
|
||||
<Step label="3. Ethereum Nedir?" />
|
||||
<Step label="4. Akıllı Kontratlar" />
|
||||
<Step label="5. Solidity Programlama Dili" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary"
|
||||
style={{
|
||||
marginTop: "2rem",
|
||||
marginLeft: "auto",
|
||||
marginRight: "auto",
|
||||
display: "block",
|
||||
}}
|
||||
>
|
||||
Sertifikayı Al
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<main className={styles.root}>
|
||||
<Container>
|
||||
|
|
@ -19,7 +40,7 @@ export default function CourseDetailPage({ params }) {
|
|||
<div>
|
||||
<h1>{course.name}</h1>
|
||||
<div>{course.instructor.name}</div>
|
||||
{true ? (
|
||||
{amIEnrolledInCourse.data ? (
|
||||
<Link
|
||||
href={`/kurslar/${params.courseSlug}/ogren`}
|
||||
className={cn(styles.button, "btn btn-primary")}
|
||||
|
|
@ -27,7 +48,11 @@ export default function CourseDetailPage({ params }) {
|
|||
Eğitime Başla
|
||||
</Link>
|
||||
) : (
|
||||
<button className={cn(styles.button, "btn btn-primary")}>
|
||||
<button
|
||||
className={cn(styles.button, "btn btn-primary")}
|
||||
disabled={!enroll.write}
|
||||
onClick={() => enroll.write?.()}
|
||||
>
|
||||
Satın Al: {formatPrice(course.price)}
|
||||
</button>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -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 ? (
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary"
|
||||
onClick={() => approveMax.write?.() && getAllowanceOfSpender.refetch()}
|
||||
>
|
||||
APPROVE!!!
|
||||
</button>
|
||||
) : (
|
||||
<button type="button" className="btn btn-flat" disabled>
|
||||
{parseInt(getMyBalance.data)} DTL
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
|
@ -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
|
||||
</Link>
|
||||
|
||||
<ConnectButton />
|
||||
<DTLDisplay />
|
||||
|
||||
<ConnectButton showBalance={false} />
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ export default function WrapperComponent({ children }) {
|
|||
accentColor: "var(--color-accent)",
|
||||
})}
|
||||
locale="tr-TR"
|
||||
coolMode
|
||||
>
|
||||
<WalletManager />
|
||||
{children}
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
},
|
||||
],
|
||||
};
|
||||
Loading…
Reference in New Issue