diff --git a/.hintrc b/.hintrc new file mode 100644 index 0000000..2fa1a2e --- /dev/null +++ b/.hintrc @@ -0,0 +1,13 @@ +{ + "extends": [ + "development" + ], + "hints": { + "axe/forms": [ + "default", + { + "select-name": "off" + } + ] + } +} \ No newline at end of file diff --git a/README.md b/README.md index 965a122..91561d6 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). +Figma file +[https://www.figma.com/file/4AnazUQXHdoJK1zEt4JQSx/Fluently?type=design&node-id=236-850&t=pKDK4WK3kfPbA3zZ-0](https://www.figma.com/file/4AnazUQXHdoJK1zEt4JQSx/Fluently?type=design&node-id=236-850&t=pKDK4WK3kfPbA3zZ-0) ## Getting Started First, run the development server: @@ -10,6 +12,7 @@ npm run dev yarn dev # or pnpm dev + ``` Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. diff --git a/package-lock.json b/package-lock.json index 6ca9342..5e95afd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "@types/node": "18.15.11", "@types/react": "18.0.37", "@types/react-dom": "18.0.11", + "axios": "^1.4.0", "eslint": "8.38.0", "eslint-config-next": "13.3.0", "ethers": "^5.7.2", @@ -2844,6 +2845,15 @@ "zustand": "^4.0.0-rc.1" } }, + "node_modules/@huddle01/huddle01-client/node_modules/axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "dependencies": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, "node_modules/@huddle01/huddle01-iframe": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/@huddle01/huddle01-iframe/-/huddle01-iframe-0.0.9.tgz", @@ -4046,6 +4056,15 @@ "@ethersproject/properties": "^5.7.0" } }, + "node_modules/@safe-global/safe-ethers-adapters/node_modules/axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "dependencies": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, "node_modules/@safe-global/safe-ethers-lib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/@safe-global/safe-ethers-lib/-/safe-ethers-lib-1.9.3.tgz", @@ -5565,12 +5584,13 @@ } }, "node_modules/axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", "dependencies": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, "node_modules/axobject-query": { @@ -10756,6 +10776,11 @@ "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.5.0.tgz", "integrity": "sha512-f1us0OsVAJ3tdIMXGQx2lmseYS4YXe4W+sKF5g5ww/jV+5ogMadPt+sIZ+88Ga9kvMJsrRNWzCrKPpr6pMWYbA==" }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", diff --git a/package.json b/package.json index c25b034..1152b83 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "@types/node": "18.15.11", "@types/react": "18.0.37", "@types/react-dom": "18.0.11", + "axios": "^1.4.0", "eslint": "8.38.0", "eslint-config-next": "13.3.0", "ethers": "^5.7.2", diff --git a/src/components/Dashboard.tsx b/src/components/Dashboard.tsx index 1f7ed56..5380abc 100644 --- a/src/components/Dashboard.tsx +++ b/src/components/Dashboard.tsx @@ -12,208 +12,93 @@ import { Text, Flex, useDisclosure, + Link, } from "@chakra-ui/react"; import { useAddress } from "@thirdweb-dev/react"; import Setup from "./modal/Setup"; -import { motion } from "framer-motion"; +import truncateEthAddress from "truncate-eth-address"; +type Props = { + item: any[]; // I assumed this prop is an array of objects with the structure that the `getAllMeeting` function returns +}; -const containerVariants = { - hidden: { - opacity: 0, - x: '100vw' - }, - visible: { - opacity: 1, - x: 0, - transition: { - type: 'spring', - delay: 0.5, - stiffness: 28 - } - }, -} - -const Dashboard = () => { +const Dashboard = ({ item }: Props) => { + console.log(item); const address = useAddress(); const { isOpen, onOpen, onClose } = useDisclosure(); + + const userMeetings = item.filter((meeting) => meeting.user === address && meeting.matched === true); - function truncateEthAddress(address: any) { - throw new Error("Function not implemented."); - } + return ( + <> + - return ( - <> - - - - Hey {address && `${truncateEthAddress(address)}`} - - - Your language partner is waiting for you. - - - - - - Upcoming session - - - - - - - - - - - - - - - - - - - - - - - - -
Date & Time scheduledSpoken languageLanguage to learn
Thurs, 27th April, 4:00 PMIrishPakistan - - - - -
Thurs, 27th April, 4:00 PMIrishPakistan - - - - -
-
-
-
-
- - ) -} -// return ( -// <> -// -// -// {/* -// Hey {address && `${truncateEthAddress(address)}`} -// -// -// Your language partner is waiting for you. -// */} + + + Hey {address ? truncateEthAddress(address) : ""} + + + Your language partner is waiting for you. + -// + -// -// -// Upcoming session -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -//
Date & Time scheduledSpoken languageLanguage to learn
Thurs, 27th April, 4:00 PMIrishPakistan -// -// -// -// -//
Thurs, 27th April, 4:00 PMIrishPakistan -// -// -// -// -//
-//
-//
-//
-// -// ); -// }; + + + Upcoming session + + + + + + + + + + + + + {userMeetings.map((detail, i) => ( + + {/* TODO: Use `detail.time` to render the actual date */} + + + + + ))} + +
Date & Time scheduledSpoken languageLanguage to learn
Thurs, 27th April, 4:00 PM{detail.language}{detail.native} + + + + + + +
+
+
+
+ + ); +}; -export default Dashboard; +export default Dashboard; \ No newline at end of file diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 878f106..e05cc6a 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -62,7 +62,7 @@ const Header = () => { bgRepeat="no-repeat" bgSize="cover" > - group + group diff --git a/src/components/modal/Setup.tsx b/src/components/modal/Setup.tsx index 1bd28ab..442bfc8 100644 --- a/src/components/modal/Setup.tsx +++ b/src/components/modal/Setup.tsx @@ -1,4 +1,20 @@ -import { Box, Button, Flex, FormControl, FormLabel, Image, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, Select, Text } from "@chakra-ui/react" +import { + Box, + Button, + Flex, + FormControl, + FormLabel, + Image, + Modal, + ModalBody, + ModalCloseButton, + ModalContent, + ModalFooter, + ModalHeader, + ModalOverlay, + Select, + Text, +} from "@chakra-ui/react"; import { useState } from "react"; import Availability from "./component/Availability"; import Learn from "./component/Learn"; @@ -6,12 +22,12 @@ import Speak from "./component/Speak"; import Complete from "./component/Complete"; interface Props { - isOpen: boolean; - onClose: () => void; + isOpen: boolean; + onClose: () => void; } -const Setup : React.FC = ({ isOpen, onClose }) => { - const [activeComponent, setActiveComponent] = useState('learn') +const Setup: React.FC = ({ isOpen, onClose }) => { + const [activeComponent, setActiveComponent] = useState("learn"); return ( @@ -30,4 +46,4 @@ const Setup : React.FC = ({ isOpen, onClose }) => { ) } -export default Setup \ No newline at end of file +export default Setup; diff --git a/src/components/modal/component/Availability.tsx b/src/components/modal/component/Availability.tsx index 592385b..d8a5eae 100644 --- a/src/components/modal/component/Availability.tsx +++ b/src/components/modal/component/Availability.tsx @@ -1,57 +1,101 @@ -import { Box, Button, Center, Flex, FormControl, FormLabel, Image, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, Select, Text, Wrap, WrapItem } from "@chakra-ui/react" +import { useFluentContext } from "@/context"; +import { + Box, + Button, + Center, + Flex, + FormControl, + FormLabel, + Image, + Modal, + ModalBody, + ModalCloseButton, + ModalContent, + ModalFooter, + ModalHeader, + ModalOverlay, + Select, + Text, + Wrap, + WrapItem, +} from "@chakra-ui/react"; import { FiArrowRight } from "react-icons/fi"; -import { MdKeyboardArrowLeft, MdKeyboardArrowRight } from "react-icons/md" +import { MdKeyboardArrowLeft, MdKeyboardArrowRight } from "react-icons/md"; +import { useState } from "react"; type Props = { - setActiveComponent: React.Dispatch>; + setActiveComponent: React.Dispatch>; }; const Availability: React.FC = ({ setActiveComponent }) => { + const { time, setTime,createMeeting, getRoomId } = useFluentContext(); + const [complete, setComplete] = useState(""); + console.log(time); - return ( - <> - - Select availabilty - Please select from the available time slots to increase the chances of finding a suitable language exchange partner. - - - - - - Thurs - April 27 - - - - -
- - - 04:00 PM - - -
-
-
- - - - - - ) -} + const meeting = async () => { + try { + const meetings = await getRoomId() + const meeting = createMeeting(meetings); + setActiveComponent("complete"); + console.log(meetings); + } catch (error) { + console.log(error); + } + }; + return ( + <> + + + Select availabilty + + + Please select from the available time slots to increase the chances of + finding a suitable language exchange partner. + + + + + + + Thurs + April 27 + + + + +
+ + setTime(440)} + > + 04:00 PM + + +
+
+
+ + + + + + ); +}; -export default Availability; \ No newline at end of file +export default Availability; diff --git a/src/components/modal/component/Complete.tsx b/src/components/modal/component/Complete.tsx index c68a9ae..1f9253f 100644 --- a/src/components/modal/component/Complete.tsx +++ b/src/components/modal/component/Complete.tsx @@ -15,7 +15,7 @@ const Complete: React.FC = ({ onClose, setActiveComponent }) => { icon Congratulations! - You've been matched successfully! + You`ve been matched successfully! diff --git a/src/components/modal/component/Learn.tsx b/src/components/modal/component/Learn.tsx index d0165b3..19c1092 100644 --- a/src/components/modal/component/Learn.tsx +++ b/src/components/modal/component/Learn.tsx @@ -1,28 +1,69 @@ -import { Box, Button, Flex, FormControl, FormLabel, Image, Menu, MenuButton, MenuItem, MenuList, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, Select, Text } from "@chakra-ui/react" +import { useFluentContext } from "@/context"; +import { + Box, + Button, + Flex, + FormControl, + FormLabel, + Image, + Menu, + MenuButton, + MenuItem, + MenuList, + Modal, + ModalBody, + ModalCloseButton, + ModalContent, + ModalFooter, + ModalHeader, + ModalOverlay, + Select, + Text, + +} from "@chakra-ui/react"; +import { + BsQuestionCircleFill, + BsSearch, + BsSearchHeartFill, + BsStar, + BsStarFill, +} from "react-icons/bs"; import { useState } from "react"; -import { BsQuestionCircleFill, BsSearch, BsSearchHeartFill, BsStarFill, BsStar } from "react-icons/bs"; import { FiArrowRight } from "react-icons/fi"; type Props = { - setActiveComponent: React.Dispatch>; + setActiveComponent: React.Dispatch>; }; const Learn: React.FC = ({ setActiveComponent }) => { + const { language, setLanguage } = useFluentContext(); + console.log(language) const [beginner, setBeginner] = useState(false) const [intermediate, setIntermediate] = useState(false) const [native, setNative] = useState(false) - return ( - <> - - Set up languagues preferences - Please select the language you want to learn and your proficiency level in that language. - - - Select language - + return ( + <> + + + Set up languagues preferences + + + Please select the language you want to learn and your proficiency + level in that language. + + + + + Select language + + Select your proficiency level @@ -99,4 +140,4 @@ const Learn: React.FC = ({ setActiveComponent }) => { ) } -export default Learn; \ No newline at end of file +export default Learn; diff --git a/src/components/modal/component/Speak.tsx b/src/components/modal/component/Speak.tsx index fc9330b..82677de 100644 --- a/src/components/modal/component/Speak.tsx +++ b/src/components/modal/component/Speak.tsx @@ -1,109 +1,97 @@ -import { Box, Button, Flex, FormControl, FormLabel, Image, Menu, MenuButton, MenuItem, MenuList, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, Select, Text } from "@chakra-ui/react" -import { useState } from "react"; -import { BsQuestionCircleFill, BsSearch, BsSearchHeartFill, BsStarFill, BsStar } from "react-icons/bs"; +import { useFluentContext } from "@/context"; +import { + Box, + Button, + Flex, + FormControl, + FormLabel, + Image, + Modal, + ModalBody, + ModalCloseButton, + ModalContent, + ModalFooter, + ModalHeader, + ModalOverlay, + Select, + Text, +} from "@chakra-ui/react"; +import { + BsQuestionCircleFill, + BsSearch, + BsSearchHeartFill, + BsStar, +} from "react-icons/bs"; import { FiArrowRight } from "react-icons/fi"; type Props = { - setActiveComponent: React.Dispatch>; + setActiveComponent: React.Dispatch>; }; const Speak: React.FC = ({ setActiveComponent }) => { - const [beginner, setBeginner] = useState(false) - const [intermediate, setIntermediate] = useState(false) - const [native, setNative] = useState(false) - - return ( - <> - - Choose spoken language - Please select the language you can speak to help us find the best language exchange partner for you. - - - Select language - - - - Select your proficiency level - - - setBeginner(prev => !prev)}> - {beginner ? : } - - { - setBeginner(true) - !native && setIntermediate(prev => !prev) - }} - > - {intermediate ? : } - - { - setBeginner(true) - setIntermediate(true) - setNative(prev => !prev) - }} - > - {native ? : } - - - - - - - - - - - beginner - - Beginner - I have a basic understanding of the language. - - - - intermediate - - Intermediate - I can communicate effectively. - - - - native - - Native speaker - Native speaker seeking fluency in another language. - - - - - - - - - - - - - - - - ) -} + const { native, setNative } = useFluentContext(); + console.log(native) + return ( + <> + + + Choose spoken language + + + Please select the language you can speak to help us find the best + language exchange partner for you. + + + + + Select language + + + + + + Select your proficiency level + + + + + + + + + + + + + + + + + + ); +}; -export default Speak; \ No newline at end of file +export default Speak; diff --git a/src/constant/index.ts b/src/constant/index.ts index 514e3f4..00e6cb9 100644 --- a/src/constant/index.ts +++ b/src/constant/index.ts @@ -3,7 +3,7 @@ import FluentTokenAbi from "./FLUENTOKEN.json"; import { ethers } from "ethers"; export const tokenAddress = "0x7cc168Ed905f1160C6AfcFf64FA691f5462a13CA"; -export const tokenAccount = "0xE4c84a30D8c6D8f6f86D916Dc62387A5Fc12193D"; +export const tokenAccount = "0x86Ae062a625e1950009D6f3863199282C196F528"; export const accountAbi = FlentAccountAbi.abi; export const tokenAbi = FluentTokenAbi.abi; diff --git a/src/context/index.tsx b/src/context/index.tsx index e69de29..94a80c5 100644 --- a/src/context/index.tsx +++ b/src/context/index.tsx @@ -0,0 +1,160 @@ +import connectWithContract from "@/constant"; +import React, { useContext, createContext, useState, useEffect } from "react"; +import { ethers } from "ethers"; +import { useHuddleStore } from "@huddle01/huddle01-client/store"; +import { getHuddleClient } from "@huddle01/huddle01-client"; +import { useAddress } from "@thirdweb-dev/react"; +import { useRouter } from "next/router"; +import axios from "axios"; + +type FluentProviderProps = { + children: React.ReactNode; +}; + +interface PodcastContextProps { + language: string; + native: string; + allMeeting: any[]; + setLanguage: React.Dispatch>; + setNative: React.Dispatch>; + setAllMeeting: React.Dispatch>; + setTime: React.Dispatch>; + time: number | undefined; + createMeeting: (meetingLink: string) => Promise; + getAllMeeting: () => Promise; + getUserMeeting: () => void; + getRoomId: () => Promise; +} + +const FluentContext = createContext({ + language: "", + native: "", + allMeeting: [], + setAllMeeting: () => {}, + setLanguage: () => {}, + setNative: () => {}, + setTime: () => {}, + time: undefined, + createMeeting: async (meetingLink: string) => {}, + getAllMeeting: async () => [], + getUserMeeting: () => {}, + getRoomId: async () => "", +}); + +export const FluentProvider = ({ children }: FluentProviderProps) => { + const roomId = useHuddleStore((state) => state.roomState.roomId); + // const huddleClient = getHuddleClient("VwTZ4AGTxme9snANex9tep3NwvVMGfYd"); + // console.log(huddleClient) + + const API_KEY = "VwTZ4AGTxme9snANex9tep3NwvVMGfYd"; + + const [meetingLink, setMeetingLink] = useState(""); + // console.log(meetingLink); + const router = useRouter(); + + const getRoomId = async () => { + try { + const { data } = await axios.post( + "https://iriko.testing.huddle01.com/api/v1/create-iframe-room", + { + title: "Huddle01-Test", + roomLocked: false, + }, + { + headers: { + "Content-Type": "application/json", + "x-api-key": API_KEY, + }, + } + ); + setMeetingLink(data.data.meetingLink); + console.log(data); + return data.data.meetingLink; + } catch (error) { + console.log(error); + return ""; + } + }; + + useEffect(() => { + if (address) { + router.push("/welcome"); + } + }, []); + + const address = useAddress(); + const [language, setLanguage] = useState(""); + const [native, setNative] = useState(""); + const [time, setTime] = useState(); + const [allMeeting, setAllMeeting] = useState([]); + // const meetingLink = `https://iframe.huddle01.com/${roomId}`; + + const createMeeting = async (meetingLink: string) => { + const meetingContract = await connectWithContract(); + const meeting = meetingContract.createMeeting( + language, + native, + meetingLink, + time + ); + console.log(meeting); + }; + + const getAllMeeting = async () => { + try { + const meeetingContract = await connectWithContract(); + const meeting = await meeetingContract._allMeetings(); + //console.log(meeting) + const parsedAccount = meeting.map((user: any, i: any) => ({ + user: user.user, + language: user.language, + native: user.nativeLanguage, + status: user.matchStatus, + pid: user.matchId.toNumber(), + time: user.time.toNumber(), + meeting: user.meetingLink, + matched: user.userMatched, + })); + setAllMeeting(parsedAccount); + return parsedAccount; + } catch (error) { + console.log(error); + } + }; + + const getUserMeeting = async () => { + const meeting = await getAllMeeting(); + console.log(meeting); + const filterUserMeeting = meeting.filter( + (account: any) => account.user === address + ); + console.log(filterUserMeeting); + }; + + useEffect(() => { + getAllMeeting(); + getUserMeeting(); + }, []); + + const value = { + language, + setLanguage, + setNative, + native, + time, + setTime, + createMeeting, + getAllMeeting, + allMeeting, + setAllMeeting, + getRoomId, + getUserMeeting, + }; + + return ( + {children} + ); +}; + +export const useFluentContext = (): PodcastContextProps => + useContext(FluentContext); diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 7f31eb7..86ebdd9 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -21,6 +21,7 @@ import { useAddress, } from "@thirdweb-dev/react"; import { useRouter } from "next/router"; +import { FluentProvider } from "@/context"; export const theme = extendTheme({ colors }); @@ -33,7 +34,7 @@ export default function App({ Component, pageProps }: AppProps) { useEffect(() => { if (address) { - Router.push("/dasboard"); + Router.push("/welcome"); } }, [address]); @@ -44,7 +45,9 @@ export default function App({ Component, pageProps }: AppProps) { supportedWallets={[metamaskWallet(), coinbaseWallet(), walletConnect()]} > - + + + diff --git a/src/pages/dashboard.tsx b/src/pages/dashboard.tsx index 145bdae..e72c090 100644 --- a/src/pages/dashboard.tsx +++ b/src/pages/dashboard.tsx @@ -23,10 +23,13 @@ import { ConnectWallet as ConnectWeb3Wallet, } from "@thirdweb-dev/react"; import truncateEthAddress from "truncate-eth-address"; +import { useFluentContext } from "@/context"; const Dashboard = () => { const address = useAddress(); const connect = useMetamask(); + const { allMeeting } = useFluentContext() + //console.log(allMeeting) return ( @@ -67,7 +70,7 @@ const Dashboard = () => { /> - + diff --git a/src/pages/loabby.tsx b/src/pages/loabby.tsx index 7d60c18..8d7c4cc 100644 --- a/src/pages/loabby.tsx +++ b/src/pages/loabby.tsx @@ -7,8 +7,8 @@ import { } from "@huddle01/huddle01-iframe"; import { useAddress } from "@thirdweb-dev/react"; import { useEffect, useLayoutEffect, useState } from "react"; -import MeVideoElem from "@/components/MeVideoElem"; -import { Button } from "@chakra-ui/react"; +//import MeVideoElem from "@/components/MeVideoElem"; +//import { Button } from "@chakra-ui/react"; const Loabby = () => { const huddleClient = getHuddleClient("gfhhf"); @@ -42,7 +42,7 @@ const Loabby = () => { noBorder: false, // false by default }; return ( -
+
diff --git a/src/pages/video.tsx b/src/pages/video.tsx index 3dfcd99..cc2dde6 100644 --- a/src/pages/video.tsx +++ b/src/pages/video.tsx @@ -2,7 +2,7 @@ import React from "react"; const Video = () => { return ( -
+
josep
);