mirror of
https://github.com/AustinKelsay/plebdevs.git
synced 2025-06-06 18:31:00 +00:00
Removed local storage and using next-auth with session for login and authentication
This commit is contained in:
parent
658cfe31a9
commit
d1eaae6fa1
10
package-lock.json
generated
10
package-lock.json
generated
@ -21,6 +21,7 @@
|
|||||||
"next": "14.2.5",
|
"next": "14.2.5",
|
||||||
"next-auth": "^4.24.7",
|
"next-auth": "^4.24.7",
|
||||||
"next-remove-imports": "^1.0.12",
|
"next-remove-imports": "^1.0.12",
|
||||||
|
"nodemailer": "^6.9.14",
|
||||||
"nostr-tools": "^2.7.1",
|
"nostr-tools": "^2.7.1",
|
||||||
"primeicons": "^7.0.0",
|
"primeicons": "^7.0.0",
|
||||||
"primereact": "^10.7.0",
|
"primereact": "^10.7.0",
|
||||||
@ -8595,6 +8596,15 @@
|
|||||||
"integrity": "sha512-Ww6ZlOiEQfPfXM45v17oabk77Z7mg5bOt7AjDyzy7RjK9OrLrLC8dyZQoAPEOtFX9SaNf1Tdvr5gRJWdTJj7GA==",
|
"integrity": "sha512-Ww6ZlOiEQfPfXM45v17oabk77Z7mg5bOt7AjDyzy7RjK9OrLrLC8dyZQoAPEOtFX9SaNf1Tdvr5gRJWdTJj7GA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/nodemailer": {
|
||||||
|
"version": "6.9.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.14.tgz",
|
||||||
|
"integrity": "sha512-Dobp/ebDKBvz91sbtRKhcznLThrKxKt97GI2FAlAyy+fk19j73Uz3sBXolVtmcXjaorivqsbbbjDY+Jkt4/bQA==",
|
||||||
|
"license": "MIT-0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/normalize-path": {
|
"node_modules/normalize-path": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
"next": "14.2.5",
|
"next": "14.2.5",
|
||||||
"next-auth": "^4.24.7",
|
"next-auth": "^4.24.7",
|
||||||
"next-remove-imports": "^1.0.12",
|
"next-remove-imports": "^1.0.12",
|
||||||
|
"nodemailer": "^6.9.14",
|
||||||
"nostr-tools": "^2.7.1",
|
"nostr-tools": "^2.7.1",
|
||||||
"primeicons": "^7.0.0",
|
"primeicons": "^7.0.0",
|
||||||
"primereact": "^10.7.0",
|
"primereact": "^10.7.0",
|
||||||
|
@ -5,7 +5,7 @@ import ZapDisplay from '@/components/zaps/ZapDisplay';
|
|||||||
import { getSatAmountFromInvoice } from '@/utils/lightning';
|
import { getSatAmountFromInvoice } from '@/utils/lightning';
|
||||||
import { Tag } from 'primereact/tag';
|
import { Tag } from 'primereact/tag';
|
||||||
import { nip19 } from 'nostr-tools';
|
import { nip19 } from 'nostr-tools';
|
||||||
import { useLocalStorageWithEffect } from '@/hooks/useLocalStorage';
|
import { useSession } from 'next-auth/react';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import ZapThreadsWrapper from '@/components/ZapThreadsWrapper';
|
import ZapThreadsWrapper from '@/components/ZapThreadsWrapper';
|
||||||
@ -33,13 +33,19 @@ export default function CourseDetails({ processedEvent }) {
|
|||||||
const [bitcoinConnect, setBitcoinConnect] = useState(false);
|
const [bitcoinConnect, setBitcoinConnect] = useState(false);
|
||||||
const [nAddress, setNAddress] = useState(null);
|
const [nAddress, setNAddress] = useState(null);
|
||||||
const [zapAmount, setZapAmount] = useState(0);
|
const [zapAmount, setZapAmount] = useState(0);
|
||||||
|
const [user, setUser] = useState(null);
|
||||||
const [user] = useLocalStorageWithEffect('user', {});
|
|
||||||
const { zaps, zapsLoading, zapsError } = useZapsSubscription({ event: processedEvent });
|
const { zaps, zapsLoading, zapsError } = useZapsSubscription({ event: processedEvent });
|
||||||
const { returnImageProxy } = useImageProxy();
|
const { returnImageProxy } = useImageProxy();
|
||||||
|
const { data: session, status } = useSession();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const ndk = useNDKContext();
|
const ndk = useNDKContext();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (session) {
|
||||||
|
setUser(session.user);
|
||||||
|
}
|
||||||
|
}, [session]);
|
||||||
|
|
||||||
const handleZapEvent = async () => {
|
const handleZapEvent = async () => {
|
||||||
if (!processedEvent) return;
|
if (!processedEvent) return;
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { InputText } from "primereact/inputtext";
|
import { InputText } from "primereact/inputtext";
|
||||||
import { InputNumber } from "primereact/inputnumber";
|
import { InputNumber } from "primereact/inputnumber";
|
||||||
@ -7,7 +7,7 @@ import { Button } from "primereact/button";
|
|||||||
import { Dropdown } from "primereact/dropdown";
|
import { Dropdown } from "primereact/dropdown";
|
||||||
import { ProgressSpinner } from "primereact/progressspinner";
|
import { ProgressSpinner } from "primereact/progressspinner";
|
||||||
import { v4 as uuidv4, v4 } from 'uuid';
|
import { v4 as uuidv4, v4 } from 'uuid';
|
||||||
import { useLocalStorageWithEffect } from "@/hooks/useLocalStorage";
|
import { useSession } from 'next-auth/react';
|
||||||
import { useNDKContext } from "@/context/NDKContext";
|
import { useNDKContext } from "@/context/NDKContext";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { useToast } from "@/hooks/useToast";
|
import { useToast } from "@/hooks/useToast";
|
||||||
@ -32,11 +32,18 @@ const CourseForm = () => {
|
|||||||
const { resources, resourcesLoading, resourcesError } = useResourcesQuery();
|
const { resources, resourcesLoading, resourcesError } = useResourcesQuery();
|
||||||
const { workshops, workshopsLoading, workshopsError } = useWorkshopsQuery();
|
const { workshops, workshopsLoading, workshopsError } = useWorkshopsQuery();
|
||||||
const { drafts, draftsLoading, draftsError } = useDraftsQuery();
|
const { drafts, draftsLoading, draftsError } = useDraftsQuery();
|
||||||
const [user, setUser] = useLocalStorageWithEffect('user', {});
|
const { data: session, status } = useSession();
|
||||||
|
const [user, setUser] = useState(null);
|
||||||
const ndk = useNDKContext();
|
const ndk = useNDKContext();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { showToast } = useToast();
|
const { showToast } = useToast();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (session) {
|
||||||
|
setUser(session.user);
|
||||||
|
}
|
||||||
|
}, [session]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Course Creation Flow:
|
* Course Creation Flow:
|
||||||
* 1. Generate a new course ID
|
* 1. Generate a new course ID
|
||||||
|
@ -5,7 +5,7 @@ import { InputNumber } from "primereact/inputnumber";
|
|||||||
import { InputSwitch } from "primereact/inputswitch";
|
import { InputSwitch } from "primereact/inputswitch";
|
||||||
import { Button } from "primereact/button";
|
import { Button } from "primereact/button";
|
||||||
import { useRouter } from "next/router";;
|
import { useRouter } from "next/router";;
|
||||||
import { useLocalStorageWithEffect } from "@/hooks/useLocalStorage";
|
import { useSession } from "next-auth/react";
|
||||||
import { useToast } from "@/hooks/useToast";
|
import { useToast } from "@/hooks/useToast";
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
const MDEditor = dynamic(
|
const MDEditor = dynamic(
|
||||||
@ -24,11 +24,18 @@ const ResourceForm = ({ draft = null }) => {
|
|||||||
const [coverImage, setCoverImage] = useState(draft?.image || '');
|
const [coverImage, setCoverImage] = useState(draft?.image || '');
|
||||||
const [topics, setTopics] = useState(draft?.topics || ['']);
|
const [topics, setTopics] = useState(draft?.topics || ['']);
|
||||||
const [content, setContent] = useState(draft?.content || '');
|
const [content, setContent] = useState(draft?.content || '');
|
||||||
|
const [user, setUser] = useState(null);
|
||||||
|
|
||||||
const [user] = useLocalStorageWithEffect('user', {});
|
const { data: session, status } = useSession();
|
||||||
const { showToast } = useToast();
|
const { showToast } = useToast();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (session) {
|
||||||
|
setUser(session.user);
|
||||||
|
}
|
||||||
|
}, [session]);
|
||||||
|
|
||||||
const handleContentChange = useCallback((value) => {
|
const handleContentChange = useCallback((value) => {
|
||||||
setContent(value || '');
|
setContent(value || '');
|
||||||
}, []);
|
}, []);
|
||||||
|
@ -6,7 +6,7 @@ import { InputNumber } from 'primereact/inputnumber';
|
|||||||
import { InputSwitch } from 'primereact/inputswitch';
|
import { InputSwitch } from 'primereact/inputswitch';
|
||||||
import { Button } from 'primereact/button';
|
import { Button } from 'primereact/button';
|
||||||
import { useToast } from '@/hooks/useToast';
|
import { useToast } from '@/hooks/useToast';
|
||||||
import { useLocalStorageWithEffect } from '@/hooks/useLocalStorage';
|
import { useSession } from 'next-auth/react';
|
||||||
import 'primeicons/primeicons.css';
|
import 'primeicons/primeicons.css';
|
||||||
|
|
||||||
const WorkshopForm = ({ draft = null }) => {
|
const WorkshopForm = ({ draft = null }) => {
|
||||||
@ -19,9 +19,16 @@ const WorkshopForm = ({ draft = null }) => {
|
|||||||
const [topics, setTopics] = useState(draft?.topics || ['']);
|
const [topics, setTopics] = useState(draft?.topics || ['']);
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [user] = useLocalStorageWithEffect('user', {});
|
const { data: session, status } = useSession();
|
||||||
|
const [user, setUser] = useState(null);
|
||||||
const { showToast } = useToast();
|
const { showToast } = useToast();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (session) {
|
||||||
|
setUser(session.user);
|
||||||
|
}
|
||||||
|
}, [session]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (draft) {
|
if (draft) {
|
||||||
setTitle(draft.title);
|
setTitle(draft.title);
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
"use client";
|
|
||||||
import React, { useRef, useState, useEffect } from 'react';
|
import React, { useRef, useState, useEffect } from 'react';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
@ -6,22 +5,31 @@ import { useImageProxy } from '@/hooks/useImageProxy';
|
|||||||
import { Button } from 'primereact/button';
|
import { Button } from 'primereact/button';
|
||||||
import { Menu } from 'primereact/menu';
|
import { Menu } from 'primereact/menu';
|
||||||
import useWindowWidth from '@/hooks/useWindowWidth';
|
import useWindowWidth from '@/hooks/useWindowWidth';
|
||||||
import {useLocalStorageWithEffect} from '@/hooks/useLocalStorage';
|
import {useSession, signOut} from 'next-auth/react';
|
||||||
import 'primereact/resources/primereact.min.css';
|
import 'primereact/resources/primereact.min.css';
|
||||||
import 'primeicons/primeicons.css';
|
import 'primeicons/primeicons.css';
|
||||||
import styles from '../navbar.module.css';
|
import styles from '../navbar.module.css';
|
||||||
|
|
||||||
const UserAvatar = () => {
|
const UserAvatar = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [user, setUser] = useLocalStorageWithEffect('user', {});
|
|
||||||
const [isClient, setIsClient] = useState(false);
|
const [isClient, setIsClient] = useState(false);
|
||||||
|
const [user, setUser] = useState(null);
|
||||||
const { returnImageProxy } = useImageProxy();
|
const { returnImageProxy } = useImageProxy();
|
||||||
const windowWidth = useWindowWidth();
|
const windowWidth = useWindowWidth();
|
||||||
|
|
||||||
|
const { data: session, status } = useSession();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (session) {
|
||||||
|
console.log(session);
|
||||||
|
setUser(session.user);
|
||||||
|
}
|
||||||
|
}, [session]);
|
||||||
|
|
||||||
const menu = useRef(null);
|
const menu = useRef(null);
|
||||||
|
|
||||||
const handleLogout = () => {
|
const handleLogout = () => {
|
||||||
window.localStorage.removeItem('user');
|
signOut();
|
||||||
router.push('/').then(() => window.location.reload());
|
router.push('/').then(() => window.location.reload());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,12 +2,12 @@ import React, { useState, useEffect } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { Button } from "primereact/button";
|
import { Button } from "primereact/button";
|
||||||
import MenuTab from "@/components/menutab/MenuTab";
|
import MenuTab from "@/components/menutab/MenuTab";
|
||||||
import { useLocalStorageWithEffect } from "@/hooks/useLocalStorage";
|
|
||||||
import { useCoursesQuery } from "@/hooks/nostrQueries/content/useCoursesQuery";
|
import { useCoursesQuery } from "@/hooks/nostrQueries/content/useCoursesQuery";
|
||||||
import { useResourcesQuery } from "@/hooks/nostrQueries/content/useResourcesQuery";
|
import { useResourcesQuery } from "@/hooks/nostrQueries/content/useResourcesQuery";
|
||||||
import { useWorkshopsQuery } from "@/hooks/nostrQueries/content/useWorkshopsQuery";
|
import { useWorkshopsQuery } from "@/hooks/nostrQueries/content/useWorkshopsQuery";
|
||||||
import { useDraftsQuery } from "@/hooks/apiQueries/useDraftsQuery";
|
import { useDraftsQuery } from "@/hooks/apiQueries/useDraftsQuery";
|
||||||
import { useContentIdsQuery } from "@/hooks/apiQueries/useContentIdsQuery";
|
import { useContentIdsQuery } from "@/hooks/apiQueries/useContentIdsQuery";
|
||||||
|
import { useSession } from "next-auth/react";
|
||||||
import { useToast } from "@/hooks/useToast";
|
import { useToast } from "@/hooks/useToast";
|
||||||
import ContentList from "@/components/content/lists/ContentList";
|
import ContentList from "@/components/content/lists/ContentList";
|
||||||
import { parseEvent } from "@/utils/nostr";
|
import { parseEvent } from "@/utils/nostr";
|
||||||
@ -21,7 +21,8 @@ const UserContent = () => {
|
|||||||
const [content, setContent] = useState([]);
|
const [content, setContent] = useState([]);
|
||||||
const [publishedContent, setPublishedContent] = useState([]);
|
const [publishedContent, setPublishedContent] = useState([]);
|
||||||
|
|
||||||
const [user] = useLocalStorageWithEffect("user", {});
|
const { data: session, status } = useSession();
|
||||||
|
const [user, setUser] = useState(null);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { showToast } = useToast();
|
const { showToast } = useToast();
|
||||||
const ndk = useNDKContext();
|
const ndk = useNDKContext();
|
||||||
@ -31,6 +32,12 @@ const UserContent = () => {
|
|||||||
const { drafts, draftsLoading, draftsError } = useDraftsQuery();
|
const { drafts, draftsLoading, draftsError } = useDraftsQuery();
|
||||||
const { contentIds, contentIdsLoading, contentIdsError, refetchContentIds } = useContentIdsQuery();
|
const { contentIds, contentIdsLoading, contentIdsError, refetchContentIds } = useContentIdsQuery();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (session) {
|
||||||
|
setUser(session.user);
|
||||||
|
}
|
||||||
|
}, [session]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIsClient(true);
|
setIsClient(true);
|
||||||
}, []);
|
}, []);
|
||||||
|
@ -18,7 +18,7 @@ const ZapDisplay = ({ zapAmount, event, zapsLoading }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<span className="text-xs cursor-pointer flex items-center relative shadow-md cursor-pointer hover:opacity-80" onClick={(e) => op.current.toggle(e)}>
|
<span className="text-xs cursor-pointer flex items-center relative hover:opacity-80" onClick={(e) => op.current.toggle(e)}>
|
||||||
<i className="pi pi-bolt text-yellow-300"></i>
|
<i className="pi pi-bolt text-yellow-300"></i>
|
||||||
<span className="relative flex items-center min-w-[20px] min-h-[20px]">
|
<span className="relative flex items-center min-w-[20px] min-h-[20px]">
|
||||||
{zapsLoading || zapAmount === null || extraLoading ? (
|
{zapsLoading || zapAmount === null || extraLoading ? (
|
||||||
|
@ -1,11 +1,18 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useLocalStorageWithEffect } from '@/hooks/useLocalStorage';
|
import { useSession } from 'next-auth/react';
|
||||||
|
|
||||||
export function useDraftsQuery() {
|
export function useDraftsQuery() {
|
||||||
const [isClient, setIsClient] = useState(false);
|
const [isClient, setIsClient] = useState(false);
|
||||||
const [user] = useLocalStorageWithEffect('user', {});
|
const { data: session, status } = useSession();
|
||||||
|
const [user, setUser] = useState(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (session) {
|
||||||
|
setUser(session.user);
|
||||||
|
}
|
||||||
|
}, [session]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIsClient(true);
|
setIsClient(true);
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
"use client";
|
|
||||||
import { useState, useEffect } from 'react';
|
|
||||||
|
|
||||||
// This version of the hook initializes state without immediately attempting to read from localStorage
|
|
||||||
function useLocalStorage(key, initialValue) {
|
|
||||||
const [storedValue, setStoredValue] = useState(initialValue);
|
|
||||||
|
|
||||||
// Function to update localStorage and state
|
|
||||||
const setValue = value => {
|
|
||||||
try {
|
|
||||||
const valueToStore = value instanceof Function ? value(storedValue) : value;
|
|
||||||
setStoredValue(valueToStore); // Update state
|
|
||||||
if (typeof window !== 'undefined') {
|
|
||||||
window.localStorage.setItem(key, JSON.stringify(valueToStore)); // Update localStorage
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return [storedValue, setValue];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom hook to handle fetching and setting data from localStorage
|
|
||||||
export function useLocalStorageWithEffect(key, initialValue) {
|
|
||||||
const [storedValue, setStoredValue] = useLocalStorage(key, initialValue);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (typeof window === 'undefined') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const item = window.localStorage.getItem(key);
|
|
||||||
// Only update if the item exists to prevent overwriting the initial value with null
|
|
||||||
if (item !== null) {
|
|
||||||
setStoredValue(JSON.parse(item));
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
}, [key]); // Dependencies array ensures this runs once on mount
|
|
||||||
|
|
||||||
return [storedValue, setStoredValue];
|
|
||||||
}
|
|
||||||
|
|
||||||
export default useLocalStorage;
|
|
@ -2,6 +2,7 @@ import { PrimeReactProvider } from 'primereact/api';
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import Navbar from '@/components/navbar/Navbar';
|
import Navbar from '@/components/navbar/Navbar';
|
||||||
import { ToastProvider } from '@/hooks/useToast';
|
import { ToastProvider } from '@/hooks/useToast';
|
||||||
|
import { SessionProvider } from "next-auth/react"
|
||||||
import Layout from '@/components/Layout';
|
import Layout from '@/components/Layout';
|
||||||
import '@/styles/globals.css'
|
import '@/styles/globals.css'
|
||||||
import 'primereact/resources/themes/lara-dark-indigo/theme.css';
|
import 'primereact/resources/themes/lara-dark-indigo/theme.css';
|
||||||
@ -17,10 +18,11 @@ import {
|
|||||||
const queryClient = new QueryClient()
|
const queryClient = new QueryClient()
|
||||||
|
|
||||||
export default function MyApp({
|
export default function MyApp({
|
||||||
Component, pageProps: { ...pageProps }
|
Component, pageProps: { session, ...pageProps }
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<PrimeReactProvider>
|
<PrimeReactProvider>
|
||||||
|
<SessionProvider session={session}>
|
||||||
<NDKProvider>
|
<NDKProvider>
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<ToastProvider>
|
<ToastProvider>
|
||||||
@ -39,6 +41,7 @@ export default function MyApp({
|
|||||||
</ToastProvider>
|
</ToastProvider>
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
</NDKProvider>
|
</NDKProvider>
|
||||||
|
</SessionProvider>
|
||||||
</PrimeReactProvider>
|
</PrimeReactProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
86
src/pages/api/auth/[...nextauth].js
Normal file
86
src/pages/api/auth/[...nextauth].js
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
import NextAuth from "next-auth";
|
||||||
|
import CredentialsProvider from "next-auth/providers/credentials";
|
||||||
|
import NDK from "@nostr-dev-kit/ndk";
|
||||||
|
import axios from "axios";
|
||||||
|
import { findKind0Fields } from "@/utils/nostr";
|
||||||
|
|
||||||
|
const relayUrls = [
|
||||||
|
"wss://nos.lol/",
|
||||||
|
"wss://relay.damus.io/",
|
||||||
|
"wss://relay.snort.social/",
|
||||||
|
"wss://relay.nostr.band/",
|
||||||
|
"wss://nostr.mutinywallet.com/",
|
||||||
|
"wss://relay.mutinywallet.com/",
|
||||||
|
"wss://relay.primal.net/"
|
||||||
|
];
|
||||||
|
|
||||||
|
const BASE_URL = process.env.BASE_URL;
|
||||||
|
|
||||||
|
// Initialize NDK
|
||||||
|
const ndk = new NDK({
|
||||||
|
explicitRelayUrls: relayUrls,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default NextAuth({
|
||||||
|
providers: [
|
||||||
|
CredentialsProvider({
|
||||||
|
id: "nostr",
|
||||||
|
name: "Nostr",
|
||||||
|
credentials: {
|
||||||
|
pubkey: { label: "Public Key", type: "text" },
|
||||||
|
},
|
||||||
|
authorize: async (credentials) => {
|
||||||
|
if (credentials?.pubkey) {
|
||||||
|
await ndk.connect();
|
||||||
|
|
||||||
|
const user = ndk.getUser({ pubkey: credentials.pubkey });
|
||||||
|
|
||||||
|
try {
|
||||||
|
const profile = await user.fetchProfile();
|
||||||
|
|
||||||
|
// Check if user exists, create if not
|
||||||
|
const response = await axios.get(`${BASE_URL}/api/users/${credentials.pubkey}`);
|
||||||
|
if (response.status === 200 && response.data) {
|
||||||
|
return response.data;
|
||||||
|
} else if (response.status === 204) {
|
||||||
|
// Create user
|
||||||
|
if (profile) {
|
||||||
|
const fields = await findKind0Fields(profile);
|
||||||
|
const payload = { pubkey: credentials.pubkey, ...fields };
|
||||||
|
|
||||||
|
const createUserResponse = await axios.post(`${BASE_URL}/api/users`, payload);
|
||||||
|
return createUserResponse.data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Nostr login error:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
callbacks: {
|
||||||
|
async jwt({ token, user }) {
|
||||||
|
if (user) {
|
||||||
|
token.user = user; // Add user to token
|
||||||
|
}
|
||||||
|
return token;
|
||||||
|
},
|
||||||
|
async session({ session, token }) {
|
||||||
|
session.user = token.user; // Add user to session
|
||||||
|
return session;
|
||||||
|
},
|
||||||
|
async redirect({ url, baseUrl }) {
|
||||||
|
return url.split("/signin");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
secret: process.env.NEXTAUTH_SECRET,
|
||||||
|
session: { jwt: true },
|
||||||
|
jwt: {
|
||||||
|
signingKey: process.env.JWT_SECRET,
|
||||||
|
},
|
||||||
|
pages: {
|
||||||
|
signIn: "/auth/signin",
|
||||||
|
},
|
||||||
|
});
|
75
src/pages/auth/signin.js
Normal file
75
src/pages/auth/signin.js
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import { signIn, useSession } from "next-auth/react"
|
||||||
|
import { useState, useEffect } from "react"
|
||||||
|
import { useNDKContext } from "@/context/NDKContext";
|
||||||
|
import { Button } from 'primereact/button';
|
||||||
|
import NDK, { NDKEvent, NDKNip07Signer } from "@nostr-dev-kit/ndk";
|
||||||
|
|
||||||
|
export default function SignIn() {
|
||||||
|
const [email, setEmail] = useState("")
|
||||||
|
const [nostrPubkey, setNostrPubkey] = useState("")
|
||||||
|
const [nostrPrivkey, setNostrPrivkey] = useState("")
|
||||||
|
|
||||||
|
const { data: session, status } = useSession(); // Get the current session's data and status
|
||||||
|
|
||||||
|
// const ndk = useNDKContext()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("session", session)
|
||||||
|
}, [session])
|
||||||
|
|
||||||
|
const handleEmailSignIn = (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
signIn("email", { email })
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleNostrSignIn = async (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
const nip07signer = new NDKNip07Signer();
|
||||||
|
const ndk = new NDK({ signer: nip07signer });
|
||||||
|
|
||||||
|
await ndk.connect()
|
||||||
|
|
||||||
|
try {
|
||||||
|
const user = await nip07signer.user()
|
||||||
|
|
||||||
|
console.log("user in signin", user)
|
||||||
|
const pubkey = user?._pubkey
|
||||||
|
signIn("nostr", { pubkey })
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error signing Nostr event:", error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAnonymousSignIn = (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
signIn("anonymous")
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="w-fit mx-auto mt-24 flex flex-col justify-center">
|
||||||
|
<h1 className="text-center mb-8">Sign In</h1>
|
||||||
|
<Button
|
||||||
|
label={"login with nostr"}
|
||||||
|
icon="pi pi-user"
|
||||||
|
className="text-[#f8f8ff] w-[250px] my-4"
|
||||||
|
rounded
|
||||||
|
onClick={handleNostrSignIn}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
label={"login anonymously"}
|
||||||
|
icon="pi pi-user"
|
||||||
|
className="text-[#f8f8ff] w-[250px] my-4"
|
||||||
|
rounded
|
||||||
|
onClick={handleAnonymousSignIn}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
label={"login with email"}
|
||||||
|
icon="pi pi-envelope"
|
||||||
|
className="text-[#f8f8ff] w-[250px] my-4"
|
||||||
|
rounded
|
||||||
|
onClick={handleEmailSignIn}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
@ -6,7 +6,7 @@ import { getSatAmountFromInvoice } from '@/utils/lightning';
|
|||||||
import ZapDisplay from '@/components/zaps/ZapDisplay';
|
import ZapDisplay from '@/components/zaps/ZapDisplay';
|
||||||
import { Tag } from 'primereact/tag';
|
import { Tag } from 'primereact/tag';
|
||||||
import { nip19, nip04 } from 'nostr-tools';
|
import { nip19, nip04 } from 'nostr-tools';
|
||||||
import { useLocalStorageWithEffect } from '@/hooks/useLocalStorage';
|
import { useSession } from 'next-auth/react';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import ZapThreadsWrapper from '@/components/ZapThreadsWrapper';
|
import ZapThreadsWrapper from '@/components/ZapThreadsWrapper';
|
||||||
@ -40,12 +40,19 @@ export default function Details() {
|
|||||||
const [decryptedContent, setDecryptedContent] = useState(null);
|
const [decryptedContent, setDecryptedContent] = useState(null);
|
||||||
|
|
||||||
const ndk = useNDKContext();
|
const ndk = useNDKContext();
|
||||||
const [user] = useLocalStorageWithEffect('user', {});
|
const { data: session, status } = useSession();
|
||||||
|
const [user, setUser] = useState(null);
|
||||||
const { returnImageProxy } = useImageProxy();
|
const { returnImageProxy } = useImageProxy();
|
||||||
const { zaps, zapsLoading, zapsError } = useZapsSubscription({ event: processedEvent });
|
const { zaps, zapsLoading, zapsError } = useZapsSubscription({ event: processedEvent });
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (session) {
|
||||||
|
setUser(session.user);
|
||||||
|
}
|
||||||
|
}, [session]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (processedEvent.price) {
|
if (processedEvent.price) {
|
||||||
setPaidResource(true);
|
setPaidResource(true);
|
||||||
|
@ -4,7 +4,7 @@ import { useRouter } from 'next/router';
|
|||||||
import { hexToNpub } from '@/utils/nostr';
|
import { hexToNpub } from '@/utils/nostr';
|
||||||
import { nip19, nip04 } from 'nostr-tools';
|
import { nip19, nip04 } from 'nostr-tools';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
import { useLocalStorageWithEffect } from '@/hooks/useLocalStorage';
|
import { useSession } from 'next-auth/react';
|
||||||
import { useImageProxy } from '@/hooks/useImageProxy';
|
import { useImageProxy } from '@/hooks/useImageProxy';
|
||||||
import { Button } from 'primereact/button';
|
import { Button } from 'primereact/button';
|
||||||
import { useToast } from '@/hooks/useToast';
|
import { useToast } from '@/hooks/useToast';
|
||||||
@ -44,12 +44,19 @@ function validateEvent(event) {
|
|||||||
export default function Draft() {
|
export default function Draft() {
|
||||||
const [draft, setDraft] = useState(null);
|
const [draft, setDraft] = useState(null);
|
||||||
const { returnImageProxy } = useImageProxy();
|
const { returnImageProxy } = useImageProxy();
|
||||||
const [user] = useLocalStorageWithEffect('user', {});
|
const { data: session, status } = useSession();
|
||||||
|
const [user, setUser] = useState(null);
|
||||||
const { width, height } = useResponsiveImageDimensions();
|
const { width, height } = useResponsiveImageDimensions();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { showToast } = useToast();
|
const { showToast } = useToast();
|
||||||
const ndk = useNDKContext();
|
const ndk = useNDKContext();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (session) {
|
||||||
|
setUser(session.user);
|
||||||
|
}
|
||||||
|
}, [session]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (router.isReady) {
|
if (router.isReady) {
|
||||||
const { slug } = router.query;
|
const { slug } = router.query;
|
||||||
@ -117,7 +124,6 @@ export default function Draft() {
|
|||||||
try {
|
try {
|
||||||
price = resource.tags.find(tag => tag[0] === 'price')[1];
|
price = resource.tags.find(tag => tag[0] === 'price')[1];
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
|
||||||
price = 0;
|
price = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import { Button } from 'primereact/button';
|
|
||||||
import { useLogin } from "@/hooks/useLogin";
|
|
||||||
|
|
||||||
const Login = () => {
|
|
||||||
const { nostrLogin, anonymousLogin } = useLogin();
|
|
||||||
return (
|
|
||||||
<div className="w-fit mx-auto mt-24 flex flex-col justify-center">
|
|
||||||
<h1 className="text-center mb-8">Login</h1>
|
|
||||||
<Button
|
|
||||||
label={"login with nostr"}
|
|
||||||
icon="pi pi-user"
|
|
||||||
className="text-[#f8f8ff] w-[250px] my-4"
|
|
||||||
rounded
|
|
||||||
onClick={nostrLogin}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
label={"login anonymously"}
|
|
||||||
icon="pi pi-user"
|
|
||||||
className="text-[#f8f8ff] w-[250px] my-4"
|
|
||||||
rounded
|
|
||||||
onClick={anonymousLogin}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
label={"login with email"}
|
|
||||||
icon="pi pi-envelope"
|
|
||||||
className="text-[#f8f8ff] w-[250px] my-4"
|
|
||||||
rounded
|
|
||||||
onClick={anonymousLogin}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Login;
|
|
@ -1,21 +1,26 @@
|
|||||||
import React, { useRef, useState, useEffect } from "react";
|
import React, { useRef, useState, useEffect, use } from "react";
|
||||||
import { Button } from "primereact/button";
|
import { Button } from "primereact/button";
|
||||||
import { DataTable } from "primereact/datatable";
|
import { DataTable } from "primereact/datatable";
|
||||||
import { Menu } from "primereact/menu";
|
import { Menu } from "primereact/menu";
|
||||||
import { Column } from "primereact/column";
|
import { Column } from "primereact/column";
|
||||||
import { useImageProxy } from "@/hooks/useImageProxy";
|
import { useImageProxy } from "@/hooks/useImageProxy";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { useLocalStorageWithEffect } from "@/hooks/useLocalStorage";
|
import { useSession } from 'next-auth/react';
|
||||||
import UserContent from "@/components/profile/UserContent";
|
import UserContent from "@/components/profile/UserContent";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import BitcoinConnectButton from "@/components/profile/BitcoinConnect";
|
import BitcoinConnectButton from "@/components/profile/BitcoinConnect";
|
||||||
|
|
||||||
const Profile = () => {
|
const Profile = () => {
|
||||||
const [user] = useLocalStorageWithEffect("user", {});
|
const { data: session, status } = useSession();
|
||||||
|
const [user, setUser] = useState(null);
|
||||||
const { returnImageProxy } = useImageProxy();
|
const { returnImageProxy } = useImageProxy();
|
||||||
const menu = useRef(null);
|
const menu = useRef(null);
|
||||||
|
|
||||||
console.log('user:', user);
|
useEffect(() => {
|
||||||
|
if (session) {
|
||||||
|
setUser(session.user);
|
||||||
|
}
|
||||||
|
}, [session]);
|
||||||
|
|
||||||
const purchases = [];
|
const purchases = [];
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user