diff --git a/app/match/page.tsx b/app/match/page.tsx new file mode 100644 index 0000000..42dac85 --- /dev/null +++ b/app/match/page.tsx @@ -0,0 +1,362 @@ +"use client" + +import { ReactNode, useEffect, useState } from "react" +import { useRouter } from "next/navigation" +import { useEncryptedStore } from "@/store/encrypted" +import { usePasswordStore } from "@/store/password" +import { MatchDocument } from "@/types" +import RequireAuth from "@/components/helper/RequireAuth" +import { Button } from "@/components/ui/button" + + +const onMarkCompletionButton = async(userId: string | null) => { + // make post request to markcompletion + try { + const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/markcompletion`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + userId, + }), + }); + + if (response.ok) { + // show alert and reload the page + window.alert("Success!"); + window.location.reload(); + } else { + // Handle error + window.alert("Error!"); + } + } catch (error) { + console.error("Error marking completion:", error); + } + }; + +const onCreateMatchButton = async(userId: string | null) => { + try { + const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/creatematch`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + userId, + }), + }); + + if (response.ok) { + window.location.reload(); + } else { + // show alert no match found + window.alert("No match found"); + } + } catch (error) { + console.error("Error creating match:", error); + } + }; + + +const handleVerificationSubmit = async (matchId, userId, token) => { + const verifiedURLs = JSON.parse(localStorage.getItem("valid_urls")) || []; + const invalidURLs = JSON.parse(localStorage.getItem("invalid_urls")) || []; + + try { + const response = await fetch( + `${process.env.NEXT_PUBLIC_API_URL}/updatematch`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${token}`, + }, + body: JSON.stringify({ + matchId, + userId, + verifiedURLs, + }), + } + ); + + if (response.ok) { + // Handle a successful response, e.g., show a success message + } else { + // Handle the error response, e.g., show an error message + } + } catch (error) { + console.error("Error submitting verification:", error); + } +}; + +const handleCheckboxChange = (event, url, storageKey) => { + const isChecked = event.target.checked; + + // Get the current state from local storage or initialize an empty array + let storedData = JSON.parse(localStorage.getItem(storageKey)) || []; + + // Check if the URL is in the other list (valid_urls or invalid_urls) and remove it + const otherStorageKey = storageKey === "valid_urls" ? "invalid_urls" : "valid_urls"; + storedData = storedData.filter((id) => !isInLocalStorage(id, otherStorageKey)); + + if (isChecked) { + // Add the URL ID to the array if checked + storedData.push(url); + } else { + // Remove the URL ID from the array if unchecked + const index = storedData.indexOf(url); + if (index !== -1) { + storedData.splice(index, 1); + } + } + + // Save the updated state to local storage + localStorage.setItem(storageKey, JSON.stringify(storedData)); +}; + +const isInLocalStorage = (urlId, storageKey) => { + const storedData = JSON.parse(localStorage.getItem(storageKey)) || []; + return storedData.includes(urlId); +}; + +const populateUrls = (urls, includeInputValue) => { + return urls.map((url, index) => ( +
  • + Title: {url.title} | URL: {url.url}
    + {includeInputValue && ( +
    + handleCheckboxChange(e, url.url, "valid_urls")} /> +
    + handleCheckboxChange(e, url.url, "invalid_urls")} /> +
    +
    + )} +
  • + )); +}; + + +const MatchDetails = ({ matchData, userId, token, onVerificationSubmit }: {matchData: MatchDocument, userId : string | null, token: string | null, onVerificationSubmit: (matchId: string, userId : string | null , token: string | null) => void }) => { + let urlsToValidate = null; + let loggedInUserUrls = null; + if(userId != matchData.user1.id) { + urlsToValidate = populateUrls(matchData.user1.urls, true); + loggedInUserUrls = populateUrls(matchData.user2.urls, false); + } + else { + urlsToValidate = populateUrls(matchData.user2.urls, true); + loggedInUserUrls = populateUrls(matchData.user1.urls, false); + } + + return ( +
    +

    Match Details

    + + +
    + ); +}; + +const MatchResult = ({ matchData, onAgree, onClose }) => { + return ( +
    +

    Match Results

    + +
    + + +
    +
    + ); +}; + +const handleAgree = async () => { + try { + const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/concur`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ agree: true }), + }); + + if (response.ok) { + // Handle success, e.g., show a success message + console.log('Agree successful'); + } else { + // Handle the error response, e.g., show an error message + console.error('Agree failed'); + } + } catch (error) { + console.error('Error agreeing:', error); + } +}; + +const handleClose = async () => { + try { + const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/concur`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ agree: false }), + }); + + if (response.ok) { + // Handle success, e.g., show a success message + console.log('Close successful'); + } else { + // Handle the error response, e.g., show an error message + console.error('Close failed'); + } + } catch (error) { + console.error('Error closing:', error); + } +}; + + + +const Match = () => { + const router = useRouter() + const [match, setMatch] = useState(null) + const [user1, setUser1] = useState(null); + const [user2, setUser2] = useState(null); + const { address } = useEncryptedStore() + const { userId, token } = usePasswordStore() + + useEffect(() => { + ;(async () => { + try { + const { match } = await fetch( + `${process.env.NEXT_PUBLIC_API_URL}/getmatch/${userId}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${token}`, + }, + } + ).then((res) => res.json()) + if (match) { + console.log("match : ", match); + if (match.user1.id === userId) { + console.log("inside match.user1.id : ", userId); + setUser1(match.user1); + setUser2(match.user2); + } else { + setUser1(match.user2); + setUser2(match.user1); + } + setMatch(match); // Set the match state + } + } catch (error) { + console.log(error); + } + })() + }, [address, userId, token, router]) + + + + return ( + +
    +

    My matches

    +
    +
    + +

    your match

    + {match ? ( + + ) : ( + + )} +
    + +

    are you done validating?

    +

    Mark as complete

    + {match && + + } +
    + + {match && } + +
    +
    +
    + ) +} + +const Row = ({ children }: { children: ReactNode }) => { + return ( +
    + {children} +
    + ) +} + +export default Match diff --git a/config/site.ts b/config/site.ts index 5e80ac6..c913f7f 100644 --- a/config/site.ts +++ b/config/site.ts @@ -17,6 +17,10 @@ export const siteConfig = { title: "Add tag", href: "/submit-tag", }, + { + title: "Match", + href: "/match", + }, { title: "Me", href: "/me", diff --git a/types/index.ts b/types/index.ts index 0ff6d8b..c2654ff 100644 --- a/types/index.ts +++ b/types/index.ts @@ -23,3 +23,21 @@ export interface NavItem { disabled?: boolean external?: boolean } + +export interface MatchDocument { + _id: string, + user1: { + id: string, + urls: Array, + completed: boolean, +}, +user2: { + id: string, + urls: Array, + completed: boolean, +}, +status: string; +threshold: number; // threshold is max limit of urls allowed to be validated, depnds on key in MatchGroup +createdAt: Date; +updatedAt: Date; +} \ No newline at end of file