Compare commits

..

10 Commits

Author SHA1 Message Date
osmannyildiz 89b4835543 up 2023-12-17 08:00:49 +03:00
osmannyildiz 019612c9e5 up 2023-12-17 08:00:32 +03:00
osmannyildiz d8f14b3ce6 up 2023-12-17 07:58:57 +03:00
osmannyildiz a12b2124ba add course enrollment 2023-12-17 07:53:57 +03:00
osmannyildiz c7ce43eee8 use slug for course urls & improve design 2023-12-17 00:00:31 +03:00
osmannyildiz 03c726605d change course data 2023-12-16 23:29:30 +03:00
Muhammed Akıncı f5bf674066 frontend geliştirildi. Hatalar düzeltildi.Fixlendi 2023-12-16 22:43:45 +03:00
Muhammed Akıncı 25d8c76889 fix 2023-12-16 17:50:33 +03:00
Muhammed Akıncı 711eeef127 Frontend kısmında iyileştirmeler yapıldı. Fixlendi 2023-12-16 15:17:07 +03:00
osmannyildiz 5fe6d25933 add my account page 2023-12-16 09:58:31 +03:00
31 changed files with 1235 additions and 179 deletions

View File

@ -10,9 +10,9 @@
}, },
"dependencies": { "dependencies": {
"@rainbow-me/rainbowkit": "^1.3.1", "@rainbow-me/rainbowkit": "^1.3.1",
"next": "13.5.6", "next": "^14.0.4",
"react": "^18", "react": "^18.2.0",
"react-dom": "^18", "react-dom": "^18.2.0",
"viem": "^1.20.0", "viem": "^1.20.0",
"wagmi": "^1.4.12" "wagmi": "^1.4.12"
} }

View File

@ -3,22 +3,22 @@ lockfileVersion: '6.0'
dependencies: dependencies:
'@rainbow-me/rainbowkit': '@rainbow-me/rainbowkit':
specifier: ^1.3.1 specifier: ^1.3.1
version: 1.3.1(react-dom@18.0.0)(react@18.0.0)(viem@1.20.0)(wagmi@1.4.12) version: 1.3.1(react-dom@18.2.0)(react@18.2.0)(viem@1.20.0)(wagmi@1.4.12)
next: next:
specifier: 13.5.6 specifier: ^14.0.4
version: 13.5.6(react-dom@18.0.0)(react@18.0.0) version: 14.0.4(react-dom@18.2.0)(react@18.2.0)
react: react:
specifier: ^18 specifier: ^18.2.0
version: 18.0.0 version: 18.2.0
react-dom: react-dom:
specifier: ^18 specifier: ^18.2.0
version: 18.0.0(react@18.0.0) version: 18.2.0(react@18.2.0)
viem: viem:
specifier: ^1.20.0 specifier: ^1.20.0
version: 1.20.0(typescript@5.3.3) version: 1.20.0(typescript@5.3.3)
wagmi: wagmi:
specifier: ^1.4.12 specifier: ^1.4.12
version: 1.4.12(react-dom@18.0.0)(react@18.0.0)(typescript@5.3.3)(viem@1.20.0) version: 1.4.12(react-dom@18.2.0)(react@18.2.0)(typescript@5.3.3)(viem@1.20.0)
packages: packages:
@ -156,12 +156,12 @@ packages:
tslib: 2.6.2 tslib: 2.6.2
dev: false dev: false
/@next/env@13.5.6: /@next/env@14.0.4:
resolution: {integrity: sha512-Yac/bV5sBGkkEXmAX5FWPS9Mmo2rthrOPRQQNfycJPkjUAUclomCPH7QFVCDQ4Mp2k2K1SSM6m0zrxYrOwtFQw==} resolution: {integrity: sha512-irQnbMLbUNQpP1wcE5NstJtbuA/69kRfzBrpAD7Gsn8zm/CY6YQYc3HQBz8QPxwISG26tIm5afvvVbu508oBeQ==}
dev: false dev: false
/@next/swc-darwin-arm64@13.5.6: /@next/swc-darwin-arm64@14.0.4:
resolution: {integrity: sha512-5nvXMzKtZfvcu4BhtV0KH1oGv4XEW+B+jOfmBdpFI3C7FrB/MfujRpWYSBBO64+qbW8pkZiSyQv9eiwnn5VIQA==} resolution: {integrity: sha512-mF05E/5uPthWzyYDyptcwHptucf/jj09i2SXBPwNzbgBNc+XnwzrL0U6BmPjQeOL+FiB+iG1gwBeq7mlDjSRPg==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
@ -169,8 +169,8 @@ packages:
dev: false dev: false
optional: true optional: true
/@next/swc-darwin-x64@13.5.6: /@next/swc-darwin-x64@14.0.4:
resolution: {integrity: sha512-6cgBfxg98oOCSr4BckWjLLgiVwlL3vlLj8hXg2b+nDgm4bC/qVXXLfpLB9FHdoDu4057hzywbxKvmYGmi7yUzA==} resolution: {integrity: sha512-IZQ3C7Bx0k2rYtrZZxKKiusMTM9WWcK5ajyhOZkYYTCc8xytmwSzR1skU7qLgVT/EY9xtXDG0WhY6fyujnI3rw==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
@ -178,8 +178,8 @@ packages:
dev: false dev: false
optional: true optional: true
/@next/swc-linux-arm64-gnu@13.5.6: /@next/swc-linux-arm64-gnu@14.0.4:
resolution: {integrity: sha512-txagBbj1e1w47YQjcKgSU4rRVQ7uF29YpnlHV5xuVUsgCUf2FmyfJ3CPjZUvpIeXCJAoMCFAoGnbtX86BK7+sg==} resolution: {integrity: sha512-VwwZKrBQo/MGb1VOrxJ6LrKvbpo7UbROuyMRvQKTFKhNaXjUmKTu7wxVkIuCARAfiI8JpaWAnKR+D6tzpCcM4w==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
@ -187,8 +187,8 @@ packages:
dev: false dev: false
optional: true optional: true
/@next/swc-linux-arm64-musl@13.5.6: /@next/swc-linux-arm64-musl@14.0.4:
resolution: {integrity: sha512-cGd+H8amifT86ZldVJtAKDxUqeFyLWW+v2NlBULnLAdWsiuuN8TuhVBt8ZNpCqcAuoruoSWynvMWixTFcroq+Q==} resolution: {integrity: sha512-8QftwPEW37XxXoAwsn+nXlodKWHfpMaSvt81W43Wh8dv0gkheD+30ezWMcFGHLI71KiWmHK5PSQbTQGUiidvLQ==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
@ -196,8 +196,8 @@ packages:
dev: false dev: false
optional: true optional: true
/@next/swc-linux-x64-gnu@13.5.6: /@next/swc-linux-x64-gnu@14.0.4:
resolution: {integrity: sha512-Mc2b4xiIWKXIhBy2NBTwOxGD3nHLmq4keFk+d4/WL5fMsB8XdJRdtUlL87SqVCTSaf1BRuQQf1HvXZcy+rq3Nw==} resolution: {integrity: sha512-/s/Pme3VKfZAfISlYVq2hzFS8AcAIOTnoKupc/j4WlvF6GQ0VouS2Q2KEgPuO1eMBwakWPB1aYFIA4VNVh667A==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
@ -205,8 +205,8 @@ packages:
dev: false dev: false
optional: true optional: true
/@next/swc-linux-x64-musl@13.5.6: /@next/swc-linux-x64-musl@14.0.4:
resolution: {integrity: sha512-CFHvP9Qz98NruJiUnCe61O6GveKKHpJLloXbDSWRhqhkJdZD2zU5hG+gtVJR//tyW897izuHpM6Gtf6+sNgJPQ==} resolution: {integrity: sha512-m8z/6Fyal4L9Bnlxde5g2Mfa1Z7dasMQyhEhskDATpqr+Y0mjOBZcXQ7G5U+vgL22cI4T7MfvgtrM2jdopqWaw==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
@ -214,8 +214,8 @@ packages:
dev: false dev: false
optional: true optional: true
/@next/swc-win32-arm64-msvc@13.5.6: /@next/swc-win32-arm64-msvc@14.0.4:
resolution: {integrity: sha512-aFv1ejfkbS7PUa1qVPwzDHjQWQtknzAZWGTKYIAaS4NMtBlk3VyA6AYn593pqNanlicewqyl2jUhQAaFV/qXsg==} resolution: {integrity: sha512-7Wv4PRiWIAWbm5XrGz3D8HUkCVDMMz9igffZG4NB1p4u1KoItwx9qjATHz88kwCEal/HXmbShucaslXCQXUM5w==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
@ -223,8 +223,8 @@ packages:
dev: false dev: false
optional: true optional: true
/@next/swc-win32-ia32-msvc@13.5.6: /@next/swc-win32-ia32-msvc@14.0.4:
resolution: {integrity: sha512-XqqpHgEIlBHvzwG8sp/JXMFkLAfGLqkbVsyN+/Ih1mR8INb6YCc2x/Mbwi6hsAgUnqQztz8cvEbHJUbSl7RHDg==} resolution: {integrity: sha512-zLeNEAPULsl0phfGb4kdzF/cAVIfaC7hY+kt0/d+y9mzcZHsMS3hAS829WbJ31DkSlVKQeHEjZHIdhN+Pg7Gyg==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [ia32] cpu: [ia32]
os: [win32] os: [win32]
@ -232,8 +232,8 @@ packages:
dev: false dev: false
optional: true optional: true
/@next/swc-win32-x64-msvc@13.5.6: /@next/swc-win32-x64-msvc@14.0.4:
resolution: {integrity: sha512-Cqfe1YmOS7k+5mGu92nl5ULkzpKuxJrP3+4AEuPmrpFZ3BHxTY3TnHmU1On3bFmFFs6FbTcdF58CCUProGpIGQ==} resolution: {integrity: sha512-yEh2+R8qDlDCjxVpzOTEpBLQTEFAcP2A8fUFLaWNap9GitYKkKv1//y2S6XY6zsR4rCOPRpU7plYDR+az2n30A==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
@ -350,6 +350,7 @@ packages:
dependencies: dependencies:
is-glob: 4.0.3 is-glob: 4.0.3
micromatch: 4.0.5 micromatch: 4.0.5
napi-wasm: 1.1.0
dev: false dev: false
bundledDependencies: bundledDependencies:
- napi-wasm - napi-wasm
@ -404,7 +405,7 @@ packages:
'@parcel/watcher-win32-x64': 2.3.0 '@parcel/watcher-win32-x64': 2.3.0
dev: false dev: false
/@rainbow-me/rainbowkit@1.3.1(react-dom@18.0.0)(react@18.0.0)(viem@1.20.0)(wagmi@1.4.12): /@rainbow-me/rainbowkit@1.3.1(react-dom@18.2.0)(react@18.2.0)(viem@1.20.0)(wagmi@1.4.12):
resolution: {integrity: sha512-4Upi+S12ZHosimzlUpCiOocg4dtfGU2wkzcpxeat/FYHrvhVIOgm0TuzbsIM96W1p7OXabosd7xuxPvwduUygQ==} resolution: {integrity: sha512-4Upi+S12ZHosimzlUpCiOocg4dtfGU2wkzcpxeat/FYHrvhVIOgm0TuzbsIM96W1p7OXabosd7xuxPvwduUygQ==}
engines: {node: '>=12.4'} engines: {node: '>=12.4'}
peerDependencies: peerDependencies:
@ -419,12 +420,12 @@ packages:
clsx: 1.1.1 clsx: 1.1.1
i18n-js: 4.3.2 i18n-js: 4.3.2
qrcode: 1.5.0 qrcode: 1.5.0
react: 18.0.0 react: 18.2.0
react-dom: 18.0.0(react@18.0.0) react-dom: 18.2.0(react@18.2.0)
react-remove-scroll: 2.5.4(react@18.0.0) react-remove-scroll: 2.5.4(react@18.2.0)
ua-parser-js: 1.0.37 ua-parser-js: 1.0.37
viem: 1.20.0(typescript@5.3.3) viem: 1.20.0(typescript@5.3.3)
wagmi: 1.4.12(react-dom@18.0.0)(react@18.0.0)(typescript@5.3.3)(viem@1.20.0) wagmi: 1.4.12(react-dom@18.2.0)(react@18.2.0)(typescript@5.3.3)(viem@1.20.0)
transitivePeerDependencies: transitivePeerDependencies:
- '@types/react' - '@types/react'
dev: false dev: false
@ -652,10 +653,10 @@ packages:
'@tanstack/react-query': ^4.36.1 '@tanstack/react-query': ^4.36.1
dependencies: dependencies:
'@tanstack/query-persist-client-core': 4.36.1 '@tanstack/query-persist-client-core': 4.36.1
'@tanstack/react-query': 4.36.1(react-dom@18.0.0)(react@18.0.0) '@tanstack/react-query': 4.36.1(react-dom@18.2.0)(react@18.2.0)
dev: false dev: false
/@tanstack/react-query@4.36.1(react-dom@18.0.0)(react@18.0.0): /@tanstack/react-query@4.36.1(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-y7ySVHFyyQblPl3J3eQBWpXZkliroki3ARnBKsdJchlgt7yJLRDUcf4B8soufgiYt3pEQIkBWBx1N9/ZPIeUWw==} resolution: {integrity: sha512-y7ySVHFyyQblPl3J3eQBWpXZkliroki3ARnBKsdJchlgt7yJLRDUcf4B8soufgiYt3pEQIkBWBx1N9/ZPIeUWw==}
peerDependencies: peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 react: ^16.8.0 || ^17.0.0 || ^18.0.0
@ -668,9 +669,9 @@ packages:
optional: true optional: true
dependencies: dependencies:
'@tanstack/query-core': 4.36.1 '@tanstack/query-core': 4.36.1
react: 18.0.0 react: 18.2.0
react-dom: 18.0.0(react@18.0.0) react-dom: 18.2.0(react@18.2.0)
use-sync-external-store: 1.2.0(react@18.0.0) use-sync-external-store: 1.2.0(react@18.2.0)
dev: false dev: false
/@types/connect@3.4.38: /@types/connect@3.4.38:
@ -737,7 +738,7 @@ packages:
'@vanilla-extract/css': 1.9.1 '@vanilla-extract/css': 1.9.1
dev: false dev: false
/@wagmi/connectors@3.1.10(react@18.0.0)(typescript@5.3.3)(viem@1.20.0): /@wagmi/connectors@3.1.10(react@18.2.0)(typescript@5.3.3)(viem@1.20.0):
resolution: {integrity: sha512-ZLJC1QaeiZarkF07Cr9mOlVjPO1Lf5TBx+JKBms2y5fUIXlKrxCfQgO/gDCureboI+Us2X3IRI659+XacSGpbA==} resolution: {integrity: sha512-ZLJC1QaeiZarkF07Cr9mOlVjPO1Lf5TBx+JKBms2y5fUIXlKrxCfQgO/gDCureboI+Us2X3IRI659+XacSGpbA==}
peerDependencies: peerDependencies:
typescript: '>=5.0.4' typescript: '>=5.0.4'
@ -749,9 +750,9 @@ packages:
'@coinbase/wallet-sdk': 3.7.2 '@coinbase/wallet-sdk': 3.7.2
'@safe-global/safe-apps-provider': 0.18.1(typescript@5.3.3) '@safe-global/safe-apps-provider': 0.18.1(typescript@5.3.3)
'@safe-global/safe-apps-sdk': 8.1.0(typescript@5.3.3) '@safe-global/safe-apps-sdk': 8.1.0(typescript@5.3.3)
'@walletconnect/ethereum-provider': 2.10.6(react@18.0.0) '@walletconnect/ethereum-provider': 2.10.6(react@18.2.0)
'@walletconnect/legacy-provider': 2.0.0 '@walletconnect/legacy-provider': 2.0.0
'@walletconnect/modal': 2.6.2(react@18.0.0) '@walletconnect/modal': 2.6.2(react@18.2.0)
'@walletconnect/utils': 2.10.2 '@walletconnect/utils': 2.10.2
abitype: 0.8.7(typescript@5.3.3) abitype: 0.8.7(typescript@5.3.3)
eventemitter3: 4.0.7 eventemitter3: 4.0.7
@ -779,7 +780,7 @@ packages:
- zod - zod
dev: false dev: false
/@wagmi/core@1.4.12(react@18.0.0)(typescript@5.3.3)(viem@1.20.0): /@wagmi/core@1.4.12(react@18.2.0)(typescript@5.3.3)(viem@1.20.0):
resolution: {integrity: sha512-bLcYmmGgjtl3jAGo8X3Sm6oUwsdjbVxFMu9SWnwHdE4S9JdYeWM57dEhQgq8SYul2yQ7yY2/gimBf1Or0Ky3dQ==} resolution: {integrity: sha512-bLcYmmGgjtl3jAGo8X3Sm6oUwsdjbVxFMu9SWnwHdE4S9JdYeWM57dEhQgq8SYul2yQ7yY2/gimBf1Or0Ky3dQ==}
peerDependencies: peerDependencies:
typescript: '>=5.0.4' typescript: '>=5.0.4'
@ -788,12 +789,12 @@ packages:
typescript: typescript:
optional: true optional: true
dependencies: dependencies:
'@wagmi/connectors': 3.1.10(react@18.0.0)(typescript@5.3.3)(viem@1.20.0) '@wagmi/connectors': 3.1.10(react@18.2.0)(typescript@5.3.3)(viem@1.20.0)
abitype: 0.8.7(typescript@5.3.3) abitype: 0.8.7(typescript@5.3.3)
eventemitter3: 4.0.7 eventemitter3: 4.0.7
typescript: 5.3.3 typescript: 5.3.3
viem: 1.20.0(typescript@5.3.3) viem: 1.20.0(typescript@5.3.3)
zustand: 4.4.7(react@18.0.0) zustand: 4.4.7(react@18.2.0)
transitivePeerDependencies: transitivePeerDependencies:
- '@azure/app-configuration' - '@azure/app-configuration'
- '@azure/cosmos' - '@azure/cosmos'
@ -879,14 +880,14 @@ packages:
tslib: 1.14.1 tslib: 1.14.1
dev: false dev: false
/@walletconnect/ethereum-provider@2.10.6(react@18.0.0): /@walletconnect/ethereum-provider@2.10.6(react@18.2.0):
resolution: {integrity: sha512-bBQ+yUfxLv8VxNttgNKY7nED35gSVayO/BnLHbNKvyV1gpvSCla5mWB9MsXuQs70MK0g+/qtgRVSrOtdSubaNQ==} resolution: {integrity: sha512-bBQ+yUfxLv8VxNttgNKY7nED35gSVayO/BnLHbNKvyV1gpvSCla5mWB9MsXuQs70MK0g+/qtgRVSrOtdSubaNQ==}
dependencies: dependencies:
'@walletconnect/jsonrpc-http-connection': 1.0.7 '@walletconnect/jsonrpc-http-connection': 1.0.7
'@walletconnect/jsonrpc-provider': 1.0.13 '@walletconnect/jsonrpc-provider': 1.0.13
'@walletconnect/jsonrpc-types': 1.0.3 '@walletconnect/jsonrpc-types': 1.0.3
'@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/jsonrpc-utils': 1.0.8
'@walletconnect/modal': 2.6.2(react@18.0.0) '@walletconnect/modal': 2.6.2(react@18.2.0)
'@walletconnect/sign-client': 2.10.6 '@walletconnect/sign-client': 2.10.6
'@walletconnect/types': 2.10.6 '@walletconnect/types': 2.10.6
'@walletconnect/universal-provider': 2.10.6 '@walletconnect/universal-provider': 2.10.6
@ -1064,19 +1065,19 @@ packages:
tslib: 1.14.1 tslib: 1.14.1
dev: false dev: false
/@walletconnect/modal-core@2.6.2(react@18.0.0): /@walletconnect/modal-core@2.6.2(react@18.2.0):
resolution: {integrity: sha512-cv8ibvdOJQv2B+nyxP9IIFdxvQznMz8OOr/oR/AaUZym4hjXNL/l1a2UlSQBXrVjo3xxbouMxLb3kBsHoYP2CA==} resolution: {integrity: sha512-cv8ibvdOJQv2B+nyxP9IIFdxvQznMz8OOr/oR/AaUZym4hjXNL/l1a2UlSQBXrVjo3xxbouMxLb3kBsHoYP2CA==}
dependencies: dependencies:
valtio: 1.11.2(react@18.0.0) valtio: 1.11.2(react@18.2.0)
transitivePeerDependencies: transitivePeerDependencies:
- '@types/react' - '@types/react'
- react - react
dev: false dev: false
/@walletconnect/modal-ui@2.6.2(react@18.0.0): /@walletconnect/modal-ui@2.6.2(react@18.2.0):
resolution: {integrity: sha512-rbdstM1HPGvr7jprQkyPggX7rP4XiCG85ZA+zWBEX0dVQg8PpAgRUqpeub4xQKDgY7pY/xLRXSiCVdWGqvG2HA==} resolution: {integrity: sha512-rbdstM1HPGvr7jprQkyPggX7rP4XiCG85ZA+zWBEX0dVQg8PpAgRUqpeub4xQKDgY7pY/xLRXSiCVdWGqvG2HA==}
dependencies: dependencies:
'@walletconnect/modal-core': 2.6.2(react@18.0.0) '@walletconnect/modal-core': 2.6.2(react@18.2.0)
lit: 2.8.0 lit: 2.8.0
motion: 10.16.2 motion: 10.16.2
qrcode: 1.5.3 qrcode: 1.5.3
@ -1085,11 +1086,11 @@ packages:
- react - react
dev: false dev: false
/@walletconnect/modal@2.6.2(react@18.0.0): /@walletconnect/modal@2.6.2(react@18.2.0):
resolution: {integrity: sha512-eFopgKi8AjKf/0U4SemvcYw9zlLpx9njVN8sf6DAkowC2Md0gPU/UNEbH1Wwj407pEKnEds98pKWib1NN1ACoA==} resolution: {integrity: sha512-eFopgKi8AjKf/0U4SemvcYw9zlLpx9njVN8sf6DAkowC2Md0gPU/UNEbH1Wwj407pEKnEds98pKWib1NN1ACoA==}
dependencies: dependencies:
'@walletconnect/modal-core': 2.6.2(react@18.0.0) '@walletconnect/modal-core': 2.6.2(react@18.2.0)
'@walletconnect/modal-ui': 2.6.2(react@18.0.0) '@walletconnect/modal-ui': 2.6.2(react@18.2.0)
transitivePeerDependencies: transitivePeerDependencies:
- '@types/react' - '@types/react'
- react - react
@ -2382,9 +2383,13 @@ packages:
hasBin: true hasBin: true
dev: false dev: false
/next@13.5.6(react-dom@18.0.0)(react@18.0.0): /napi-wasm@1.1.0:
resolution: {integrity: sha512-Y2wTcTbO4WwEsVb4A8VSnOsG1I9ok+h74q0ZdxkwM3EODqrs4pasq7O0iUxbcS9VtWMicG7f3+HAj0r1+NtKSw==} resolution: {integrity: sha512-lHwIAJbmLSjF9VDRm9GoVOy9AGp3aIvkjv+Kvz9h16QR3uSVYH78PNQUnT2U4X53mhlnV2M7wrhibQ3GHicDmg==}
engines: {node: '>=16.14.0'} dev: false
/next@14.0.4(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-qbwypnM7327SadwFtxXnQdGiKpkuhaRLE2uq62/nRul9cj9KhQ5LhHmlziTNqUidZotw/Q1I9OjirBROdUJNgA==}
engines: {node: '>=18.17.0'}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
'@opentelemetry/api': ^1.1.0 '@opentelemetry/api': ^1.1.0
@ -2397,25 +2402,26 @@ packages:
sass: sass:
optional: true optional: true
dependencies: dependencies:
'@next/env': 13.5.6 '@next/env': 14.0.4
'@swc/helpers': 0.5.2 '@swc/helpers': 0.5.2
busboy: 1.6.0 busboy: 1.6.0
caniuse-lite: 1.0.30001570 caniuse-lite: 1.0.30001570
graceful-fs: 4.2.11
postcss: 8.4.31 postcss: 8.4.31
react: 18.0.0 react: 18.2.0
react-dom: 18.0.0(react@18.0.0) react-dom: 18.2.0(react@18.2.0)
styled-jsx: 5.1.1(react@18.0.0) styled-jsx: 5.1.1(react@18.2.0)
watchpack: 2.4.0 watchpack: 2.4.0
optionalDependencies: optionalDependencies:
'@next/swc-darwin-arm64': 13.5.6 '@next/swc-darwin-arm64': 14.0.4
'@next/swc-darwin-x64': 13.5.6 '@next/swc-darwin-x64': 14.0.4
'@next/swc-linux-arm64-gnu': 13.5.6 '@next/swc-linux-arm64-gnu': 14.0.4
'@next/swc-linux-arm64-musl': 13.5.6 '@next/swc-linux-arm64-musl': 14.0.4
'@next/swc-linux-x64-gnu': 13.5.6 '@next/swc-linux-x64-gnu': 14.0.4
'@next/swc-linux-x64-musl': 13.5.6 '@next/swc-linux-x64-musl': 14.0.4
'@next/swc-win32-arm64-msvc': 13.5.6 '@next/swc-win32-arm64-msvc': 14.0.4
'@next/swc-win32-ia32-msvc': 13.5.6 '@next/swc-win32-ia32-msvc': 14.0.4
'@next/swc-win32-x64-msvc': 13.5.6 '@next/swc-win32-x64-msvc': 14.0.4
transitivePeerDependencies: transitivePeerDependencies:
- '@babel/core' - '@babel/core'
- babel-plugin-macros - babel-plugin-macros
@ -2677,17 +2683,17 @@ packages:
safe-buffer: 5.2.1 safe-buffer: 5.2.1
dev: false dev: false
/react-dom@18.0.0(react@18.0.0): /react-dom@18.2.0(react@18.2.0):
resolution: {integrity: sha512-XqX7uzmFo0pUceWFCt7Gff6IyIMzFUn7QMZrbrQfGxtaxXZIcGQzoNpRLE3fQLnS4XzLLPMZX2T9TRcSrasicw==} resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
peerDependencies: peerDependencies:
react: ^18.0.0 react: ^18.2.0
dependencies: dependencies:
loose-envify: 1.4.0 loose-envify: 1.4.0
react: 18.0.0 react: 18.2.0
scheduler: 0.21.0 scheduler: 0.23.0
dev: false dev: false
/react-remove-scroll-bar@2.3.4(react@18.0.0): /react-remove-scroll-bar@2.3.4(react@18.2.0):
resolution: {integrity: sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A==} resolution: {integrity: sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A==}
engines: {node: '>=10'} engines: {node: '>=10'}
peerDependencies: peerDependencies:
@ -2697,12 +2703,12 @@ packages:
'@types/react': '@types/react':
optional: true optional: true
dependencies: dependencies:
react: 18.0.0 react: 18.2.0
react-style-singleton: 2.2.1(react@18.0.0) react-style-singleton: 2.2.1(react@18.2.0)
tslib: 2.6.2 tslib: 2.6.2
dev: false dev: false
/react-remove-scroll@2.5.4(react@18.0.0): /react-remove-scroll@2.5.4(react@18.2.0):
resolution: {integrity: sha512-xGVKJJr0SJGQVirVFAUZ2k1QLyO6m+2fy0l8Qawbp5Jgrv3DeLalrfMNBFSlmz5kriGGzsVBtGVnf4pTKIhhWA==} resolution: {integrity: sha512-xGVKJJr0SJGQVirVFAUZ2k1QLyO6m+2fy0l8Qawbp5Jgrv3DeLalrfMNBFSlmz5kriGGzsVBtGVnf4pTKIhhWA==}
engines: {node: '>=10'} engines: {node: '>=10'}
peerDependencies: peerDependencies:
@ -2712,15 +2718,15 @@ packages:
'@types/react': '@types/react':
optional: true optional: true
dependencies: dependencies:
react: 18.0.0 react: 18.2.0
react-remove-scroll-bar: 2.3.4(react@18.0.0) react-remove-scroll-bar: 2.3.4(react@18.2.0)
react-style-singleton: 2.2.1(react@18.0.0) react-style-singleton: 2.2.1(react@18.2.0)
tslib: 2.6.2 tslib: 2.6.2
use-callback-ref: 1.3.0(react@18.0.0) use-callback-ref: 1.3.0(react@18.2.0)
use-sidecar: 1.1.2(react@18.0.0) use-sidecar: 1.1.2(react@18.2.0)
dev: false dev: false
/react-style-singleton@2.2.1(react@18.0.0): /react-style-singleton@2.2.1(react@18.2.0):
resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==} resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==}
engines: {node: '>=10'} engines: {node: '>=10'}
peerDependencies: peerDependencies:
@ -2732,12 +2738,12 @@ packages:
dependencies: dependencies:
get-nonce: 1.0.1 get-nonce: 1.0.1
invariant: 2.2.4 invariant: 2.2.4
react: 18.0.0 react: 18.2.0
tslib: 2.6.2 tslib: 2.6.2
dev: false dev: false
/react@18.0.0: /react@18.2.0:
resolution: {integrity: sha512-x+VL6wbT4JRVPm7EGxXhZ8w8LTROaxPXOqhlGyVSrv0sB1jkyFGgXxJ8LVoPRLvPR6/CIZGFmfzqUa2NYeMr2A==} resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
dependencies: dependencies:
loose-envify: 1.4.0 loose-envify: 1.4.0
@ -2817,8 +2823,8 @@ packages:
engines: {node: '>=10'} engines: {node: '>=10'}
dev: false dev: false
/scheduler@0.21.0: /scheduler@0.23.0:
resolution: {integrity: sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ==} resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==}
dependencies: dependencies:
loose-envify: 1.4.0 loose-envify: 1.4.0
dev: false dev: false
@ -2954,7 +2960,7 @@ packages:
engines: {node: '>=6'} engines: {node: '>=6'}
dev: false dev: false
/styled-jsx@5.1.1(react@18.0.0): /styled-jsx@5.1.1(react@18.2.0):
resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
peerDependencies: peerDependencies:
@ -2968,7 +2974,7 @@ packages:
optional: true optional: true
dependencies: dependencies:
client-only: 0.0.1 client-only: 0.0.1
react: 18.0.0 react: 18.2.0
dev: false dev: false
/superstruct@0.14.2: /superstruct@0.14.2:
@ -3134,7 +3140,7 @@ packages:
resolution: {integrity: sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA==} resolution: {integrity: sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA==}
dev: false dev: false
/use-callback-ref@1.3.0(react@18.0.0): /use-callback-ref@1.3.0(react@18.2.0):
resolution: {integrity: sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w==} resolution: {integrity: sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w==}
engines: {node: '>=10'} engines: {node: '>=10'}
peerDependencies: peerDependencies:
@ -3144,11 +3150,11 @@ packages:
'@types/react': '@types/react':
optional: true optional: true
dependencies: dependencies:
react: 18.0.0 react: 18.2.0
tslib: 2.6.2 tslib: 2.6.2
dev: false dev: false
/use-sidecar@1.1.2(react@18.0.0): /use-sidecar@1.1.2(react@18.2.0):
resolution: {integrity: sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==} resolution: {integrity: sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==}
engines: {node: '>=10'} engines: {node: '>=10'}
peerDependencies: peerDependencies:
@ -3159,16 +3165,16 @@ packages:
optional: true optional: true
dependencies: dependencies:
detect-node-es: 1.1.0 detect-node-es: 1.1.0
react: 18.0.0 react: 18.2.0
tslib: 2.6.2 tslib: 2.6.2
dev: false dev: false
/use-sync-external-store@1.2.0(react@18.0.0): /use-sync-external-store@1.2.0(react@18.2.0):
resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==}
peerDependencies: peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 react: ^16.8.0 || ^17.0.0 || ^18.0.0
dependencies: dependencies:
react: 18.0.0 react: 18.2.0
dev: false dev: false
/utf-8-validate@5.0.10: /utf-8-validate@5.0.10:
@ -3198,7 +3204,7 @@ packages:
hasBin: true hasBin: true
dev: false dev: false
/valtio@1.11.2(react@18.0.0): /valtio@1.11.2(react@18.2.0):
resolution: {integrity: sha512-1XfIxnUXzyswPAPXo1P3Pdx2mq/pIqZICkWN60Hby0d9Iqb+MEIpqgYVlbflvHdrp2YR/q3jyKWRPJJ100yxaw==} resolution: {integrity: sha512-1XfIxnUXzyswPAPXo1P3Pdx2mq/pIqZICkWN60Hby0d9Iqb+MEIpqgYVlbflvHdrp2YR/q3jyKWRPJJ100yxaw==}
engines: {node: '>=12.20.0'} engines: {node: '>=12.20.0'}
peerDependencies: peerDependencies:
@ -3211,8 +3217,8 @@ packages:
optional: true optional: true
dependencies: dependencies:
proxy-compare: 2.5.1 proxy-compare: 2.5.1
react: 18.0.0 react: 18.2.0
use-sync-external-store: 1.2.0(react@18.0.0) use-sync-external-store: 1.2.0(react@18.2.0)
dev: false dev: false
/viem@1.20.0(typescript@5.3.3): /viem@1.20.0(typescript@5.3.3):
@ -3238,7 +3244,7 @@ packages:
- zod - zod
dev: false dev: false
/wagmi@1.4.12(react-dom@18.0.0)(react@18.0.0)(typescript@5.3.3)(viem@1.20.0): /wagmi@1.4.12(react-dom@18.2.0)(react@18.2.0)(typescript@5.3.3)(viem@1.20.0):
resolution: {integrity: sha512-QRxpjhdMlZmbYTfn9VQkQMKq+l3kwA1O7tF10vaykPrjbGX+IIlyn72ib9oqW9BfQO7n/Sf/mnVz1zbxRhGPWA==} resolution: {integrity: sha512-QRxpjhdMlZmbYTfn9VQkQMKq+l3kwA1O7tF10vaykPrjbGX+IIlyn72ib9oqW9BfQO7n/Sf/mnVz1zbxRhGPWA==}
peerDependencies: peerDependencies:
react: '>=17.0.0' react: '>=17.0.0'
@ -3249,13 +3255,13 @@ packages:
optional: true optional: true
dependencies: dependencies:
'@tanstack/query-sync-storage-persister': 4.36.1 '@tanstack/query-sync-storage-persister': 4.36.1
'@tanstack/react-query': 4.36.1(react-dom@18.0.0)(react@18.0.0) '@tanstack/react-query': 4.36.1(react-dom@18.2.0)(react@18.2.0)
'@tanstack/react-query-persist-client': 4.36.1(@tanstack/react-query@4.36.1) '@tanstack/react-query-persist-client': 4.36.1(@tanstack/react-query@4.36.1)
'@wagmi/core': 1.4.12(react@18.0.0)(typescript@5.3.3)(viem@1.20.0) '@wagmi/core': 1.4.12(react@18.2.0)(typescript@5.3.3)(viem@1.20.0)
abitype: 0.8.7(typescript@5.3.3) abitype: 0.8.7(typescript@5.3.3)
react: 18.0.0 react: 18.2.0
typescript: 5.3.3 typescript: 5.3.3
use-sync-external-store: 1.2.0(react@18.0.0) use-sync-external-store: 1.2.0(react@18.2.0)
viem: 1.20.0(typescript@5.3.3) viem: 1.20.0(typescript@5.3.3)
transitivePeerDependencies: transitivePeerDependencies:
- '@azure/app-configuration' - '@azure/app-configuration'
@ -3416,7 +3422,7 @@ packages:
yargs-parser: 18.1.3 yargs-parser: 18.1.3
dev: false dev: false
/zustand@4.4.7(react@18.0.0): /zustand@4.4.7(react@18.2.0):
resolution: {integrity: sha512-QFJWJMdlETcI69paJwhSMJz7PPWjVP8Sjhclxmxmxv/RYI7ZOvR5BHX+ktH0we9gTWQMxcne8q1OY8xxz604gw==} resolution: {integrity: sha512-QFJWJMdlETcI69paJwhSMJz7PPWjVP8Sjhclxmxmxv/RYI7ZOvR5BHX+ktH0we9gTWQMxcne8q1OY8xxz604gw==}
engines: {node: '>=12.7.0'} engines: {node: '>=12.7.0'}
peerDependencies: peerDependencies:
@ -3431,6 +3437,6 @@ packages:
react: react:
optional: true optional: true
dependencies: dependencies:
react: 18.0.0 react: 18.2.0
use-sync-external-store: 1.2.0(react@18.0.0) use-sync-external-store: 1.2.0(react@18.2.0)
dev: false dev: false

BIN
public/course-images/ai.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

View File

@ -1,5 +1,5 @@
:root { :root {
--max-width: 1100px; --max-width: 1280px;
--border-radius: 12px; --border-radius: 12px;
--color-bg0: hsl(210deg 40% 4%); --color-bg0: hsl(210deg 40% 4%);
--color-bg1: hsl(210deg 40% 12%); --color-bg1: hsl(210deg 40% 12%);
@ -26,13 +26,11 @@ a {
} }
.btn { .btn {
color: white; display: inline-block;
background-color: var(--color-accent);
border: none;
border-radius: var(--border-radius); border-radius: var(--border-radius);
padding: 0.75rem 1rem; padding: 0.75rem 1rem;
font-size: 1rem; font-size: 1rem;
font-weight: 700; font-weight: 600;
cursor: pointer; cursor: pointer;
transition: transform 0.125s; transition: transform 0.125s;
} }
@ -42,6 +40,43 @@ a {
.btn:active { .btn:active {
transform: scale(0.95); transform: scale(0.95);
} }
.btn-primary {
color: white;
background-color: var(--color-accent);
border: none;
}
.btn-flat {
color: white;
background-color: transparent;
border: none;
}
.pressable {
transition: transform 0.125s;
}
.pressable:hover {
transform: scale(1.025);
}
.pressable:active {
transform: scale(0.95);
}
.input {
padding: 0.75rem;
border: none;
border-radius: var(--border-radius);
}
.input-group {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.page-title {
font-size: 2.5rem;
font-weight: 300;
}
.fg-accent { .fg-accent {
color: var(--color-accent); color: var(--color-accent);

33
src/app/hesabim/page.jsx Normal file
View File

@ -0,0 +1,33 @@
import Container from "@/components/Container";
import styles from "./page.module.css";
export default function MyAccountPage() {
return (
<main className={styles.root}>
<Container>
<h1 className="page-title">Hesabım</h1>
<form className={styles.form}>
<div className="input-group">
<label htmlFor="first-name">Ad</label>
<input className="input" type="text" id="first-name" />
</div>
<div className="input-group">
<label htmlFor="last-name">Soyad</label>
<input className="input" type="text" id="last-name" />
</div>
<div className="input-group">
<label htmlFor="email">E-posta adresi</label>
<input className="input" type="email" id="email" />
</div>
<button className="btn btn-primary" type="submit">
Kaydet
</button>
</form>
</Container>
</main>
);
}

View File

@ -0,0 +1,9 @@
.root {
margin-top: 3rem;
}
.form {
display: flex;
flex-direction: column;
gap: 1.5rem;
}

View File

@ -0,0 +1,40 @@
import Container from "@/components/Container";
import CourseGrid from "@/components/CourseGrid";
import { COURSES } from "@/mockData";
import styles from "./page.module.css";
export default function CategoryPage({ params }) {
const filteredCourses = COURSES.filter(
(course) => course.category.slug === params.categorySlug
);
if (filteredCourses.length === 0) {
return (
<main className={styles.root}>
<Container>
<section>
<div>
<h1 className={styles.sectionTitle}>
Bu kategoriye ait kurs bulunamadı.
</h1>
</div>
</section>
</Container>
</main>
);
}
return (
<main className={styles.root}>
<Container>
<section>
<div>
<h1 className={styles.sectionTitle}>{params.categorySlug}</h1>
<h2 className={styles.sectionTitle}>Çok Satanlar</h2>
<CourseGrid courses={filteredCourses} />
</div>
</section>
</Container>
</main>
);
}

View File

@ -1,31 +0,0 @@
import Container from "@/components/Container";
import { COURSES } from "@/mockData";
import { cn, formatPrice } from "@/utils";
import styles from "./page.module.css";
export default function CourseDetailPage({ params }) {
const course = COURSES.find((c) => c.id === params.courseId);
return (
<main className={styles.root}>
<Container>
<div className={styles.columns}>
<img
className={styles.image}
src={course.imageUrl}
alt="Kurs resmi"
/>
<div>
<h1>{course.name}</h1>
<div>{course.instructor.name}</div>
<button className={cn(styles.buyButton, "btn")}>
Satın Al: {formatPrice(course.price)}
</button>
</div>
</div>
<p className={styles.description}>{course.description}</p>
</Container>
</main>
);
}

View File

@ -0,0 +1,78 @@
"use client";
import { CubLearn } from "@/contracts";
import { COURSES } from "@/mockData";
import { useState } from "react";
import { useContractWrite, usePrepareContractWrite } from "wagmi";
import styles from "./page.module.css";
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 LearnPage = ({ params }) => {
const course = COURSES.find((c) => c.slug === params.courseSlug);
const { config: finishCourseConfig } = usePrepareContractWrite({
address: CubLearn.address,
abi: CubLearn.abi,
functionName: "finishCourse",
args: [
course.id,
"Osman Nuri Yıldız",
"Akıllı Kontrat Güvenliği",
"Atıl Samancıoğlu",
],
});
const finishCourse = useContractWrite(finishCourseConfig);
return (
<div className={styles.container}>
<div className={styles.videoContainer}>
<iframe
src="https://www.youtube.com/embed/r3P58Y1OL0g"
// frameBorder="0"
allow="autoplay; encrypted-media"
allowFullScreen
className={styles.video}
></iframe>
</div>
<div className={styles.sidebar}>
<div className={styles.courseContainer}>
<h2>Kurs İçeriği</h2>
<div className={styles.courseContent}>
<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",
}}
onClick={() => finishCourse.write?.()}
>
Sertifikayı Al
</button>
</div>
</div>
);
};
export default LearnPage;

View File

@ -0,0 +1,36 @@
.container {
display: flex;
}
.sidebar {
width: 500px;
padding: 20px;
padding-top: 0;
border-left: 2px solid #ccc;
}
.videoContainer {
flex: 1;
padding: 20px;
}
.courseContent {
flex: 1;
}
.step {
cursor: pointer;
margin-bottom: 10px;
padding: 1rem;
background-color: var(--color-bg1);
border-radius: var(--border-radius);
}
.video {
width: 100%;
max-width: 1000px;
aspect-ratio: 16 / 9;
display: block;
margin-left: auto;
margin-right: auto;
}

View File

@ -0,0 +1,66 @@
"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>
<div className={styles.columns}>
<img
className={styles.image}
src={course.imageUrl}
alt="Kurs resmi"
/>
<div>
<h1>{course.name}</h1>
<div>{course.instructor.name}</div>
{amIEnrolledInCourse.data ? (
<Link
href={`/kurslar/${params.courseSlug}/ogren`}
className={cn(styles.button, "btn btn-primary")}
>
Eğitime Başla
</Link>
) : (
<button
className={cn(styles.button, "btn btn-primary")}
disabled={!enroll.write}
onClick={() => enroll.write?.()}
>
Satın Al: {formatPrice(course.price)}
</button>
)}
</div>
</div>
<p className={styles.description}>{course.description}</p>
</Container>
</main>
);
}

View File

@ -0,0 +1,33 @@
@media screen and (max-width: 900px) {
.root {
text-align: center;
}
}
.columns {
display: flex;
gap: 1.5rem;
align-items: flex-start;
}
@media screen and (max-width: 900px) {
.columns {
flex-direction: column;
align-items: center;
}
}
.image {
width: 50%;
max-width: 1280px;
aspect-ratio: 16 / 9;
object-fit: cover;
border-radius: var(--border-radius);
}
.button {
margin-top: 2rem;
}
.description {
margin-top: 1.5rem;
}

View File

@ -1,12 +1,25 @@
import Container from "@/components/Container"; import Container from "@/components/Container";
import CourseGrid from "@/components/CourseGrid"; import CourseGrid from "@/components/CourseGrid";
import { COURSES } from "@/mockData"; import { CATEGORIES, COURSES } from "@/mockData";
import Link from "next/link";
import styles from "./page.module.css"; import styles from "./page.module.css";
export default function HomePage() { export default function HomePage() {
return ( return (
<main className={styles.root}> <main className={styles.root}>
<Container> <Container>
<div className={styles.categories}>
{CATEGORIES.map((category) => (
<Link
key={category.id}
href={`/kategoriler/${category.slug}`}
className="btn btn-primary"
>
{category.name}
</Link>
))}
</div>
<section> <section>
<h1 className={styles.sectionTitle}>Çok Satanlar</h1> <h1 className={styles.sectionTitle}>Çok Satanlar</h1>
<CourseGrid courses={COURSES} /> <CourseGrid courses={COURSES} />

View File

@ -7,3 +7,8 @@
font-weight: 300; font-weight: 300;
margin-bottom: 1rem; margin-bottom: 1rem;
} }
.categories {
display: flex;
gap: 0.5rem;
}

View File

@ -1,6 +1,6 @@
.root { .root {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, 300px); grid-template-columns: repeat(auto-fill, minmax(275px, 1fr));
justify-content: stretch; justify-content: stretch;
gap: 1rem; gap: 1rem;
} }

View File

@ -1,10 +1,13 @@
import { formatPrice } from "@/utils"; import { cn, formatPrice } from "@/utils";
import Link from "next/link"; import Link from "next/link";
import styles from "./CourseGridItem.module.css"; import styles from "./CourseGridItem.module.css";
export default function CourseGridItem({ course }) { export default function CourseGridItem({ course }) {
return ( return (
<Link href={`/kurslar/${course.id}`} className={styles.root}> <Link
href={`/kurslar/${course.slug}`}
className={cn(styles.root, "pressable")}
>
<img className={styles.image} src={course.imageUrl} alt="Kurs resmi" /> <img className={styles.image} src={course.imageUrl} alt="Kurs resmi" />
<div className={styles.body}> <div className={styles.body}>
<span className={styles.name}>{course.name}</span> <span className={styles.name}>{course.name}</span>

View File

@ -0,0 +1,64 @@
"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(() => {
const interval = setInterval(() => getMyBalance.refetch(), 2000);
return () => clearInterval(interval);
}, []);
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>
);
}

View File

@ -1,14 +1,26 @@
import { cn } from "@/utils";
import { ConnectButton } from "@rainbow-me/rainbowkit"; import { ConnectButton } from "@rainbow-me/rainbowkit";
import Link from "next/link";
import DTLDisplay from "./DTLDisplay";
import styles from "./Header.module.css"; import styles from "./Header.module.css";
export default function Header() { export default function Header() {
return ( return (
<header className={styles.root}> <header className={styles.root}>
<div className={styles.brand}> <Link className={cn(styles.brand, "pressable")} href="/">
<span>Cub</span> <span>Cub</span>
<span className="fg-accent">Learn</span> <span className="fg-accent">Learn</span>
</Link>
<div className={styles.nav}>
<Link href="/hesabim" className="btn btn-flat">
Hesabım
</Link>
<DTLDisplay />
<ConnectButton showBalance={false} />
</div> </div>
<ConnectButton />
</header> </header>
); );
} }

View File

@ -12,3 +12,9 @@
font-size: 2rem; font-size: 2rem;
font-weight: 300; font-weight: 300;
} }
.nav {
display: flex;
align-items: center;
gap: 1.5rem;
}

View File

@ -9,19 +9,8 @@ export default function WalletManager() {
useEffect(() => { useEffect(() => {
if (address) { if (address) {
console.log("** Wallet connected. Address: ", address); console.log("** Wallet connected. Address: ", address);
// fetchMe();
} else { } else {
console.log("** Wallet disconnected."); console.log("** Wallet disconnected.");
} }
}, [address]); }, [address]);
// const fetchMe = async () => {
// const resp = await fetch(`${CONFIG.BACKEND_ADDRESS}/me`, {
// headers: {
// authorization: `Basic ${address}`,
// },
// });
// const respData = await resp.json();
// console.log("hey user:", respData.data);
// };
} }

View File

@ -7,13 +7,10 @@ import {
RainbowKitProvider, RainbowKitProvider,
} from "@rainbow-me/rainbowkit"; } from "@rainbow-me/rainbowkit";
import { configureChains, createConfig, WagmiConfig } from "wagmi"; import { configureChains, createConfig, WagmiConfig } from "wagmi";
import { hardhat, sepolia } from "wagmi/chains"; import { sepolia } from "wagmi/chains";
import { publicProvider } from "wagmi/providers/public"; import { publicProvider } from "wagmi/providers/public";
const { chains, publicClient } = configureChains( const { chains, publicClient } = configureChains([sepolia], [publicProvider()]);
[sepolia, hardhat],
[publicProvider()]
);
const { connectors } = getDefaultWallets({ const { connectors } = getDefaultWallets({
appName: "GSB Genç Blokzincir Hackathon Project", appName: "GSB Genç Blokzincir Hackathon Project",
@ -36,6 +33,7 @@ export default function WrapperComponent({ children }) {
accentColor: "var(--color-accent)", accentColor: "var(--color-accent)",
})} })}
locale="tr-TR" locale="tr-TR"
coolMode
> >
<WalletManager /> <WalletManager />
{children} {children}

596
src/contracts.js Normal file
View File

@ -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",
},
],
};

View File

@ -1,35 +1,100 @@
export const CATEGORIES = [
{ id: "1", slug: "blokzincir", name: "Blokzincir" },
{ id: "2", slug: "onyuz", name: "Önyüz Geliştirme" },
{ id: "3", slug: "linux", name: "Linux" },
{ id: "4", slug: "yapay-zeka", name: "Yapay Zeka" },
];
export const COURSES = [ export const COURSES = [
{ {
id: "6a3753e8-5f4e-4f4d-a05e-44b84b8f7aed", id: "1",
slug: "ethereum-ve-solidity",
name: "Ethereum ve Solidity", name: "Ethereum ve Solidity",
description: description:
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Autem vitae veritatis deserunt quidem hic ea repellendus fugiat ducimus tenetur. Fugit cumque quo saepe possimus rem qui odit vitae dignissimos reprehenderit!", "Lorem ipsum dolor sit amet consectetur adipisicing elit. Autem vitae veritatis deserunt quidem hic ea repellendus fugiat ducimus tenetur. Fugit cumque quo saepe possimus rem qui odit vitae dignissimos reprehenderit!",
price: "0.05", price: "300",
imageUrl: "https://osmannyildiz.tk/cublearn/akinci.webp", imageUrl: "/course-images/ethereum-and-solidity.webp",
instructor: { instructor: {
name: "Baturalp Güvenç", name: "Baturalp Güvenç",
}, },
category: CATEGORIES.find((c) => c.slug === "blokzincir"),
}, },
{ {
id: "c7253736-5756-4a64-a072-917c66afa877", id: "2",
slug: "akilli-sozlesme-guvenligi",
name: "Akıllı Sözleşme Güvenliği",
description:
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Autem vitae veritatis deserunt quidem hic ea repellendus fugiat ducimus tenetur. Fugit cumque quo saepe possimus rem qui odit vitae dignissimos reprehenderit!",
price: "500",
imageUrl: "/course-images/smart-contract-security.jpg",
instructor: {
name: "Mehmet Hayırlı",
},
category: CATEGORIES.find((c) => c.slug === "blokzincir"),
},
{
id: "3",
slug: "next-js-ile-onyuz-uygulamalari-gelistirme",
name: "Next.js ile Önyüz Uygulamaları Geliştirme", name: "Next.js ile Önyüz Uygulamaları Geliştirme",
description: description:
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Autem vitae veritatis deserunt quidem hic ea repellendus fugiat ducimus tenetur. Fugit cumque quo saepe possimus rem qui odit vitae dignissimos reprehenderit!", "Lorem ipsum dolor sit amet consectetur adipisicing elit. Autem vitae veritatis deserunt quidem hic ea repellendus fugiat ducimus tenetur. Fugit cumque quo saepe possimus rem qui odit vitae dignissimos reprehenderit!",
price: "0.05", price: "200",
imageUrl: "https://osmannyildiz.tk/cublearn/elmacik.webp", imageUrl: "/course-images/nextjs.jpg",
instructor: { instructor: {
name: "Furkan Ayvaz", name: "Furkan Ayvaz",
}, },
category: CATEGORIES.find((c) => c.slug === "onyuz"),
}, },
{ {
id: "59a8f94b-7358-4ffe-bced-a54cccc93e64", id: "4",
slug: "pardus-a-giris",
name: "Pardus'a Giriş", name: "Pardus'a Giriş",
description: description:
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Autem vitae veritatis deserunt quidem hic ea repellendus fugiat ducimus tenetur. Fugit cumque quo saepe possimus rem qui odit vitae dignissimos reprehenderit!", "Lorem ipsum dolor sit amet consectetur adipisicing elit. Autem vitae veritatis deserunt quidem hic ea repellendus fugiat ducimus tenetur. Fugit cumque quo saepe possimus rem qui odit vitae dignissimos reprehenderit!",
price: "0.05", price: "150",
imageUrl: "https://osmannyildiz.tk/cublearn/masalik.webp", imageUrl: "/course-images/pardus.jpg",
instructor: { instructor: {
name: "Berk Çiçek", name: "Berk Çiçek",
}, },
category: CATEGORIES.find((c) => c.slug === "linux"),
},
{
id: "5",
slug: "yapay-zekaya-giris",
name: "Yapay Zekaya Giriş",
description:
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Autem vitae veritatis deserunt quidem hic ea repellendus fugiat ducimus tenetur. Fugit cumque quo saepe possimus rem qui odit vitae dignissimos reprehenderit!",
price: "250",
imageUrl: "/course-images/ai.png",
instructor: {
name: "Muhammed Akıncı",
},
category: CATEGORIES.find((c) => c.slug === "yapay-zeka"),
},
{
id: "6",
slug: "react-js-temelleri",
name: "React.js Temelleri",
description:
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Autem vitae veritatis deserunt quidem hic ea repellendus fugiat ducimus tenetur. Fugit cumque quo saepe possimus rem qui odit vitae dignissimos reprehenderit!",
price: "250",
imageUrl: "/course-images/reactjs.jpg",
instructor: {
name: "Recep Akkaya",
},
category: CATEGORIES.find((c) => c.slug === "onyuz"),
},
{
id: "7",
slug: "avalanche-ile-merkeziyetsiz-uygulamalar",
name: "Avalanche ile Merkeziyetsiz Uygulamalar",
description:
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Autem vitae veritatis deserunt quidem hic ea repellendus fugiat ducimus tenetur. Fugit cumque quo saepe possimus rem qui odit vitae dignissimos reprehenderit!",
price: "450",
imageUrl: "/course-images/avalanche.png",
instructor: {
name: "Ali Gedikli",
},
category: CATEGORIES.find((c) => c.slug === "blokzincir"),
}, },
]; ];

View File

@ -2,4 +2,4 @@ export const cn = (...args) => {
return args.filter((arg) => typeof arg === "string").join(" "); return args.filter((arg) => typeof arg === "string").join(" ");
}; };
export const formatPrice = (price) => `${price} ETH`; export const formatPrice = (price) => `${price} DTL`;