-
+ <>
+
+
+
+
+
+
+
+ {utilityTitle}
+
+ {launchpadCollectionLiveUtilities ? (
+ <>>
+ ) : (
+ <>
+
+
+
+ {utilityStatus}
+
+
+ >
+ )}
-
- {utilitiesTitle}
+
+ {utilityDescription}
+
+
+ Date de l'utilité: {utilityDate}{" "}
+
+ {isUtilityClaimed ? "Réclamé" : ""}
+
- {launchpadCollectionLiveUtilities ? (
- <>>
- ) : (
- <>
-
-
-
- {utilitiesStatus}
-
-
- >
- )}
-
-
- {utilitiesDescription}
-
-
- Date de l'utilité: {utilitiesDate}
-
+ {isUtiliyClicked && (
+
+
+
+ )}
+ >
);
}
diff --git a/client/src/Components/UtilitiesComponent/UtilityClaimPopUp/UtilityClaimModal.css b/client/src/Components/UtilitiesComponent/UtilityClaimPopUp/UtilityClaimModal.css
new file mode 100644
index 00000000..53b31a59
--- /dev/null
+++ b/client/src/Components/UtilitiesComponent/UtilityClaimPopUp/UtilityClaimModal.css
@@ -0,0 +1,43 @@
+.utility-pop-up-container {
+ width: 400px;
+ box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.1);
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ /* justify-content: center; */
+ position: relative;
+ background-color: white;
+ border-radius: 20px;
+ padding: 20px;
+}
+
+.utility-pop-up-title {
+ font-family: "Britanica-Heavy";
+ font-style: normal;
+ font-weight: 400;
+ font-size: 25px;
+ line-height: 30px;
+}
+
+.utility-info-data {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.utility-info-header {
+ margin: 10px;
+}
+
+.utility-info-header img {
+ width: 20px;
+ margin-right: 10px;
+}
+
+.utility-info-title {
+ font-family: "Britanica-Heavy";
+ font-style: normal;
+ font-weight: 400;
+ font-size: 19px;
+ line-height: 30px;
+}
diff --git a/client/src/Components/UtilitiesComponent/UtilityClaimPopUp/UtilityClaimModal.js b/client/src/Components/UtilitiesComponent/UtilityClaimPopUp/UtilityClaimModal.js
new file mode 100644
index 00000000..f5e9fc9b
--- /dev/null
+++ b/client/src/Components/UtilitiesComponent/UtilityClaimPopUp/UtilityClaimModal.js
@@ -0,0 +1,110 @@
+import React from "react";
+import "./UtilityClaimModal.css";
+import meetingsLogo from "../../../Assets/Image/meetings-logo.svg";
+import Button from "../../Button/Button";
+import validationLogo from "../../../Assets/Image/greencross-offers.svg";
+
+function UtilityClaimModal({
+ isUtiliyClicked,
+ utility,
+ loggedInUser,
+ handleClaimClick,
+ isloggedUserNftHolder,
+ setIsloggedUserNftHolder,
+ isClaimConfirmed,
+ isUtilityClaimed, // New prop added here
+ claimedUserEmail, // New prop: the email of the user who claimed the utility
+}) {
+ const isClaimedByLoggedInUser =
+ isUtilityClaimed && loggedInUser?.email === claimedUserEmail;
+ return (
+ <>
+ {!isClaimConfirmed ? (
+
+
+ {
+ isClaimedByLoggedInUser
+ ? "Déjà réclamé" // If the logged-in user claimed the utility
+ : isUtilityClaimed
+ ? "Utilité déjà réclamée" // If some other user claimed the utility
+ : "Réclamer l'utilité" // If the utility is not claimed
+ }
+
+
+
+
+
+
{utility?.title}
+
+
{utility?.description}
+
+ Date de l'utilité:{" "}
+ {utility?.date
+ ? new Date(utility.date.seconds * 1000).toDateString()
+ : "N/A"}
+
+ {
+ // If isloggedUserNftHolder is true, the user is logged in, and the utility is not claimed by the logged-in user
+ isloggedUserNftHolder &&
+ loggedInUser &&
+ !isClaimedByLoggedInUser ? (
+
+ ) : (
+ // If isloggedUserNftHolder is false or the user is not logged in, show the error message
+ (!isloggedUserNftHolder || !loggedInUser) && (
+
+ Achetez un NFT de la collection pour réclamer cette
+ utilité
+
+ )
+ )
+ }
+
+
+ ) : (
+
+
+
+
+
+ L'utilité a bien été réclamé ! Veuillez vérifier vos mails !
+
+
+ )}
+ >
+ );
+}
+
+const ClaimButtonStyle = {
+ inlineStyle: {
+ backgroundColor: "#F6D463",
+ border: "transparent",
+ borderRadius: "10px",
+ width: "284px",
+ minHeight: "54px",
+ fontFamily: "Britanica-Heavy",
+ fontSize: "20px",
+ marginTop: 15,
+ },
+ customMediaQueries:
+ "@media (max-width: 950px) { .button-component { max-width: 250px; }}@media (max-width: 900px) {.button-component {max-width: 220px; } } @media (max-width: 860px){.button-component {max-width: 200px;}}@media (max-width: 840px){.button-component {max-width: 183px;}}",
+};
+
+export default UtilityClaimModal;
diff --git a/client/src/Pages/Home/Home.js b/client/src/Pages/Home/Home.js
index 80e37a1b..61664474 100644
--- a/client/src/Pages/Home/Home.js
+++ b/client/src/Pages/Home/Home.js
@@ -160,8 +160,8 @@ function Home({
const [isUserFanArray, setIsUserFanArray] = useState([]);
useEffect(() => {
// Désactiver le scroll au chargement
- window.scrollTo(0, 0);
- // Réactiver le scroll
+ window.scrollTo(0, 0);
+ // Réactiver le scroll
}, []);
useEffect(() => {
// console.log("Hello");
@@ -169,7 +169,7 @@ function Home({
// console.log(loggedInUser);
if (
dataPost &&
- loggedInUser
+ loggedInUser
// && (loggedInUser?.metamask || loggedInUser?.web3auth)
) {
// 1 for loop de data post
@@ -198,10 +198,8 @@ function Home({
querySnapshot.forEach((doc) => {
const tempNftcollectionInfo = doc.data();
tempAllAthleteCollection.push(tempNftcollectionInfo);
- // console.log("Collection found");
});
} else {
- // console.log("No collection found");
}
let currentUserWallet;
@@ -232,7 +230,6 @@ function Home({
}
if (balanceOf > 0) {
- // console.log("balance of nft from user");
isUserFan = true;
break;
}
@@ -258,28 +255,25 @@ function Home({
// console.log("appel de la fontion feedDataFrom")
feedDataFromAlchemyAndFirebase();
- // if (loggedInUser.metamask) {
- // const temp = loggedInUser.metamask.toLowerCase();
- // fansCounterApi.includes(temp) === true
- // ? setIsUserFan(true)
- // : setIsUserFan(false);
- // } else if (loggedInUser.web3auth) {
- // const temp = loggedInUser.web3auth.toLowerCase();
- // fansCounterApi.includes(temp) === true
- // ? setIsUserFan(true)
- // : setIsUserFan(false);
- // }
+
}
}, [dataPost, loggedInUser]);
- const getCommentCount = async (postId) => {
+ const getCommentCount = (postId) => {
const commentsRef = collection(db, `feed_post/${postId}/post_comments`);
const q = query(commentsRef, where("status", "==", true));
- const querySnapshot = await getDocs(q);
- const commentCount = querySnapshot.size;
-
- setCommentCounts((prevState) => ({ ...prevState, [postId]: commentCount }));
+ // Real-time listener for comments
+ const unsubscribe = onSnapshot(q, (querySnapshot) => {
+ const commentCount = querySnapshot.size;
+ setCommentCounts((prevState) => ({
+ ...prevState,
+ [postId]: commentCount,
+ }));
+ });
+
+ // Save this unsubscribe somewhere so you can call it when you don't need it anymore.
+ return unsubscribe;
};
useEffect(() => {
@@ -325,6 +319,8 @@ function Home({
}
setAthletesFollowing(foundAthletes);
+ const unsubscribes = []; // To keep track of all unsubscribe functions for comments
+
const feedPostCollectionRef = collection(db, "feed_post");
const q2 = query(
feedPostCollectionRef,
@@ -332,24 +328,42 @@ function Home({
orderBy("createdAt", "desc")
);
- const querySnapshot2 = await getDocs(q2);
- const feedData = [];
- querySnapshot2.forEach((doc) => {
- feedData.push({ ...doc.data(), id: doc.id, isDropdownClicked: false });
- });
- setPostData(feedData);
- setIsLoading(false);
- feedData.forEach((post) => {
- getCommentCount(post.id);
+ // Real-time listener for feed posts
+ const unsubscribePosts = onSnapshot(q2, (querySnapshot) => {
+ const feedData = [];
+ querySnapshot.forEach((doc) => {
+ feedData.push({
+ ...doc.data(),
+ id: doc.id,
+ isDropdownClicked: false,
+ });
+ });
+ setPostData(feedData);
+ setIsLoading(false);
+
+ unsubscribes.forEach((unsub) => unsub()); // Unsubscribe previous comment listeners
+ unsubscribes.length = 0; // Reset unsubscribe array
+
+ feedData.forEach((post) => {
+ const unsubscribeComments = getCommentCount(post.id);
+ unsubscribes.push(unsubscribeComments);
+ });
});
+
+ return () => {
+ unsubscribePosts(); // Cleanup: unsubscribe from real-time posts listener
+ unsubscribes.forEach((unsub) => unsub()); // Cleanup: unsubscribe from all real-time comment listeners
+ };
};
fetchData();
+ // Cleanup could also go here if needed for other async operations
return () => {
- // Cleanup code here if needed
+ // ...
};
- }, [loggedInUser]);
+ }, [loggedInUser]); // or whatever dependency array makes sense here
+
// retrouver les athlete supportés
const handleDropdownPostFeedClick = useCallback(
@@ -359,8 +373,6 @@ function Home({
e.currentTarget.id === dataPost[i].id &&
dataPost[i].isDropdownClicked === false
) {
- // console.log(e.currentTarget.id);
- // console.log(dataPost[i].id);
const newData = [...dataPost];
newData[i].isDropdownClicked = true;
setPostData(newData);
@@ -374,7 +386,6 @@ function Home({
setIsCreatePostButtonClicked(true);
};
- // console.log(isLogged?.account_type);
useEffect(() => {
async function getSuggestionsAthletes() {
// Create a query against the collection
@@ -399,22 +410,16 @@ function Home({
}
getSuggestionsAthletes();
}, []);
- // console.log(isLogged)
function handleClickCopyPostLink(postId) {
navigator.clipboard.writeText(`https://staging.sofan.app/post/${postId}`);
- // console.log(postId);
setIsCopyPostLinkClicked(true);
- // const timeOutAnimationCopyClicked =
setTimeout(() => {
setCopyPostAnimationHide(true);
}, 5000);
- // clearTimeout(timeOutAnimationCopyClicked);
- // const timeOutHideCopyClicked =
setTimeout(() => {
setIsCopyPostLinkClicked(false);
setCopyPostAnimationHide(false);
}, 5700);
- // clearTimeout(timeOutHideCopyClicked);
}
useEffect(() => {
// get Nfts from Owner and Contracts
@@ -457,7 +462,6 @@ function Home({
currentProfileWalletAddresses = isLogged.web3auth;
setCurrentProfileUserWallet(isLogged.web3auth);
}
- // console.log(currentProfileWalletAddresses);
try {
const nftsFromOwner = await alchemy.nft.getNftsForOwner(
@@ -466,7 +470,6 @@ function Home({
contractAddresses: arraySofanCollection,
}
);
- // console.log("nftsFromOwner --> ", nftsFromOwner);
let athletesSupportingArray = [];
for (let i = 0; i < nftsFromOwner.ownedNfts.length; i++) {
const elementFromAlchemy = nftsFromOwner.ownedNfts[i];
@@ -515,9 +518,7 @@ function Home({
athletesSupportingArray
);
setAthletesSupportingData(uniqueAthleteSupportingArray);
- // setAthletesSupportingData(athletesSupportingArray);
setNftsFromOwner(nftsFromOwner?.ownedNfts);
- // console.log("yess", nftsFromOwner);
} catch (error) {
console.error(error);
}
@@ -526,8 +527,6 @@ function Home({
getNftsForOwner();
}
}, [isLogged, alchemy]);
- // console.log("nftsFromOwner --> ",nftsFromOwner, "athletesSupportingData --> ",athletesSupportingData)
- // console.log(athletesSupportingData);
useEffect(() => {
const handleResize = () => {
setWindowWidth(window.innerWidth);
@@ -540,83 +539,38 @@ function Home({
};
}, []);
- // useMemo
- // console.log(athletesFollowing)
const modalStyle = useMemo(() => ({ top: "24px", right: "20px" }), []);
+ const year = new Date().getFullYear();
return (
<>
- {/* {isLogged?.account_type === "admin" ? <>>: <>>} */}
+
{
- if (
- isLogged?.account_type === "admin" ||
- isLogged?.account_type === "athlete"
- ) {
- if (windowWidth < 950) {
- return { height: "500px" };
- } else {
- return { height: "726px", maxHeight: "726px" };
- }
- } else if (
- athletesFollowing.length === 0 &&
- athletesSupportingData.length === 0
- ) {
- return { height: "398px" };
+ style={(() => {
+ if (
+ isLogged?.account_type === "admin" ||
+ isLogged?.account_type === "athlete"
+ ) {
+ if (windowWidth < 950) {
+ return { height: "500px" };
} else {
- return { maxHeight: "580px" };
+ return { height: "726px", maxHeight: "726px" };
}
- })()
- // isLogged?.account_type === "athlete"
- // ? windowWidth < 950
- // ? { height: "500px" }
- // : { height: "726px", maxHeight: "726px" }
- // : athletesFollowing.length === 0 &&
- // athletesSupportingData.length === 0
- // ? { height: "398px" }
- // : { maxHeight: "580px" }
- }
+ } else if (
+ athletesFollowing.length === 0 &&
+ athletesSupportingData.length === 0
+ ) {
+ return { height: "398px" };
+ } else {
+ return { maxHeight: "580px" };
+ }
+ })()}
>
- {/*
-
-
-
*/}
- {/* {isLogged?.account_type === "athlete" && (
-
- )} */}
{(() => {
if (
isLogged?.account_type === "admin" ||
@@ -664,7 +618,7 @@ function Home({
className="home-legals-mentions-container"
>
- © 2023 Sofan
+ © {year} Sofan
{" "}
Tout droits réservés
diff --git a/client/src/Pages/LaunchpadAll/LaunchpadAll.css b/client/src/Pages/LaunchpadAll/LaunchpadAll.css
index 9218971b..c3cb53b8 100644
--- a/client/src/Pages/LaunchpadAll/LaunchpadAll.css
+++ b/client/src/Pages/LaunchpadAll/LaunchpadAll.css
@@ -5,7 +5,7 @@
margin-top: 95px;
max-width: 1285px;
}
-.launchpadall-wrap{
+.launchpadall-wrap {
width: 100%;
max-width: 97%;
display: flex;
@@ -35,7 +35,7 @@
}
}
@media (max-width: 1300px) {
- .launchpadall-page {
- /* width: 94%; */
+ .launchpadall-wrap {
+ max-width: 95vw;
}
}
diff --git a/client/src/Pages/LaunchpadAll/LaunchpadAll.js b/client/src/Pages/LaunchpadAll/LaunchpadAll.js
index 9fb4c7da..a2832aed 100644
--- a/client/src/Pages/LaunchpadAll/LaunchpadAll.js
+++ b/client/src/Pages/LaunchpadAll/LaunchpadAll.js
@@ -65,9 +65,9 @@ function LaunchpadAll({
resolvedData.forEach(async (item) => {
console.log(
"Current collection_address:",
- item.nftCollection.collection_address
+ item.nftCollection?.collection_address
);
- if (item.nftCollection.collection_address === "") {
+ if (item.nftCollection?.collection_address === "") {
const docRef = doc(db, "nft_collections", item.nftCollection.id); // Assurez-vous que item.launchpad.id est correct
await updateDoc(docRef, {
collection_address: "0xeD8263C7E0df64bc1E9D69C5A72734DfB85Ba32c",
@@ -82,7 +82,6 @@ function LaunchpadAll({
fetchData();
}, []);
-
return (
diff --git a/client/src/Pages/LaunchpadCollectionLive/LaunchpadCollectionLive.js b/client/src/Pages/LaunchpadCollectionLive/LaunchpadCollectionLive.js
index 3fe75620..8044b340 100644
--- a/client/src/Pages/LaunchpadCollectionLive/LaunchpadCollectionLive.js
+++ b/client/src/Pages/LaunchpadCollectionLive/LaunchpadCollectionLive.js
@@ -70,12 +70,13 @@ function LaunchpadCollectionLive(isLogged) {
setContractAddress,
} = useEth();
const location = useLocation();
- const segments = location.pathname.split("/");
- const athleteId = segments[2];
- const collectionAddress = segments[3];
+ // const segments = location.pathname.split("/");
+ // const athleteId = segments[2];
+ // const collectionAddress = segments[3];
const loggedInUserInfo = useUserCollection();
const [crossmintPayLoadLocalStorage, setCrossmintPayLoadLocalStorage] =
useState(null);
+ const { athleteId, collectionAddress } = useParams();
useEffect(() => {
window.addEventListener(
@@ -215,8 +216,6 @@ function LaunchpadCollectionLive(isLogged) {
// ----------------------- Shajeed -------------------------
- const { collectionAddressurl } = useParams();
-
useEffect(() => {
const q = query(
collection(db, "nft_collections"),
@@ -230,7 +229,10 @@ function LaunchpadCollectionLive(isLogged) {
const unsub = onSnapshot(
collection(db, "nft_collections", docId, "utilities"),
(snapshot) => {
- const utilitiesData = snapshot.docs.map((doc) => doc.data());
+ const utilitiesData = snapshot.docs.map((doc) => ({
+ id: doc.id, // include the id here
+ ...doc.data(),
+ }));
setUtilities(utilitiesData);
}
);
@@ -577,7 +579,10 @@ function LaunchpadCollectionLive(isLogged) {
nftCollectionMaxItems={nftCollectionMaxItems}
/>
-
+
{
+const NftSingle = ({ isLogged }) => {
// functionnal states
const [isSubMenuClicked, setIsSubMenuClicked] = useState([
true,
@@ -70,6 +70,13 @@ const NftSingle = () => {
const [displayPopUpAddFundToWallet, setDisplayPopUpAddFundToWallet] =
useState();
const [currentBalance, setCurrentBalance] = useState(null);
+
+ // --------------- Shajeed -----------------------
+
+ const [utilities, setUtilities] = useState([]);
+
+ // -----------------------------------------------
+
const [
currentNftCollectionInfoFromBackend,
setCurrentNftCollectionInfoFromBackend,
@@ -174,6 +181,41 @@ const NftSingle = () => {
setNftIdApi(nftsFromContract?.tokenId);
}
+
+ // ----------------------- Shajeed -------------------------
+
+ useEffect(() => {
+ const q = query(
+ collection(db, "nft_collections"),
+ where("collection_address", "==", collectionAddress)
+ );
+
+ getDocs(q).then((querySnapshot) => {
+ const docData = querySnapshot.docs[0];
+ if (docData) {
+ const docId = docData.id;
+ const unsub = onSnapshot(
+ collection(db, "nft_collections", docId, "utilities"),
+ (snapshot) => {
+ const utilitiesData = snapshot.docs.map((doc) => ({
+ id: doc.id, // include the id here
+ ...doc.data(),
+ }));
+ setUtilities(utilitiesData);
+ }
+ );
+
+ return () => {
+ unsub();
+ };
+ }
+ });
+}, [collectionAddress]);
+
+// ---------------------------------------------------------
+
+
+
useEffect(() => {
if (alchemy) {
getCurrentOwnerInfo();
@@ -285,7 +327,7 @@ const NftSingle = () => {
// }, []);
// retirer le scroll lock lorsque le modal n'est plus la
- document.querySelector("body").classList.remove("scroll-lock");
+ //document.querySelector("body").classList.remove("scroll-lock");
//
function handleClickSubMenuButton(e) {
@@ -884,6 +926,7 @@ const NftSingle = () => {
// Call blockchain si c'est bon alors setIsListed(true) sinon false
};
+
const handleListClosed = () => {
setIsListed(false);
setIsListClicked(false);
@@ -1132,9 +1175,11 @@ const NftSingle = () => {
{isSubMenuClicked[0] && (
{
// dataSinglePageNftCollection.overviewData[0].latestBids
// }
ethPrice={ethPrice}
+ currentAthleteCollectionCreator={currentAthleteCollectionCreator}
+ collectionNameApi={
+ currentNftCollectionInfoFromBackend?.collection_title
+ }
+ currentTokenIdOwner={currentTokenIdOwner}
/>
)}
{/* {isSubMenuClicked[1] && (
diff --git a/emailtest.html b/emailtest.html
new file mode 100644
index 00000000..89eae864
--- /dev/null
+++ b/emailtest.html
@@ -0,0 +1,32 @@
+
+
+
+
+
+ Confirmation de Réclamation NFT
+
+
+
+
+
+
+
+ Bonjour [User's Name],
+
+ Nous sommes heureux de vous confirmer que vous avez réussi à réclamer une utilité NFT pour [NFT Collection Name].
+
+ Détails de l'utilité réclamée:
+
+ ID de NFT: [NFT ID]
+ Nom de l'athlète: [Athlete Name]
+ Date de réclamation: [Claim Date]
+
+ Vous pouvez vérifier l'état de votre utilité NFT à tout moment dans votre tableau de bord utilisateur.
+
+
Voir Mon Profile
+
+ Si vous avez des questions ou besoin d'assistance, n'hésitez pas à nous contacter à
contact@sofan.app .
+
+
+
+