Skip to content

Commit 5a7e06e

Browse files
committed
notes and code editor
1 parent 7370fd1 commit 5a7e06e

File tree

13 files changed

+24355
-1036
lines changed

13 files changed

+24355
-1036
lines changed

lazyweb/components/Notes/index.tsx

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import React, { useEffect } from 'react'
2+
import { Editor } from 'novel'
3+
import { MdOutlineAddToPhotos } from "react-icons/md";
4+
import { IoMdCloseCircleOutline } from "react-icons/io";
5+
import { FaChevronRight } from "react-icons/fa";
6+
7+
type Props = {}
8+
9+
const NoteComponent = (props: Props) => {
10+
const [keys, setKeys] = React.useState<string[]>([])
11+
const [sideBarOpen, setSideBarOpen] = React.useState<boolean>(false)
12+
const [selectedKey, setSelectedKey] = React.useState<string>('novel_content')
13+
14+
const generateKey = () => {
15+
const localkeys = localStorage.getItem('keys')
16+
const key = Math.random().toString(36).substring(7)
17+
//check if key exists
18+
if (localkeys) {
19+
const parsedKeys = JSON.parse(localkeys)
20+
if (parsedKeys.includes(key)) {
21+
generateKey()
22+
}
23+
else {
24+
setKeys([...parsedKeys, key])
25+
localStorage.setItem('keys', JSON.stringify([...parsedKeys, key]))
26+
setSelectedKey(key)
27+
localStorage.setItem('selectedKey', key)
28+
}
29+
}
30+
}
31+
32+
useEffect(() => {
33+
const localkeys = localStorage.getItem('keys')
34+
if (localkeys) {
35+
setKeys(JSON.parse(localkeys))
36+
}
37+
else {
38+
localStorage.setItem('keys', JSON.stringify(['novel_content']))
39+
}
40+
41+
const localSelectedKey = localStorage.getItem('selectedKey')
42+
if (localSelectedKey) {
43+
setSelectedKey(localSelectedKey)
44+
}
45+
else {
46+
localStorage.setItem('selectedKey', 'novel_content')
47+
}
48+
49+
}
50+
, [])
51+
52+
const selectKey = (key: string) => {
53+
setSelectedKey(key)
54+
localStorage.setItem('selectedKey', key)
55+
}
56+
57+
const handleRemove = (key: string) => {
58+
selectKey('novel_content')
59+
const localkeys = localStorage.getItem('keys')
60+
if (localkeys) {
61+
const parsedKeys = JSON.parse(localkeys)
62+
const filteredKeys = parsedKeys.filter((k: string) => k !== key)
63+
setKeys(filteredKeys)
64+
localStorage.removeItem(key)
65+
localStorage.setItem('keys', JSON.stringify(filteredKeys))
66+
}
67+
}
68+
69+
return (
70+
<div className='w-full relative min-h-[100vh] bg-gray'>
71+
{
72+
!sideBarOpen && (
73+
<button onClick={() => {
74+
setSideBarOpen(true)
75+
}} className='w-10 h-10 flex z-[99] justify-center items-center rounded-l-lg top-[10vh] right-0 fixed bg-white' >
76+
<MdOutlineAddToPhotos className='text-[20px]' />
77+
</button>
78+
)
79+
}
80+
<div className={`h-[100vh] p-[2%] w-[20vw] bg-gray border-l border-white/10 fixed top-0 transition-all duration-1000 ${sideBarOpen ? 'right-0' : '-right-full'
81+
} z-[100]`}>
82+
<div className='w-full flex mb-[1vh] justify-between items-center'>
83+
<h1 className='text-2xl text-gray font-bold'>Notes</h1>
84+
<div className='flex gap-[0.5rem]'>
85+
<button onClick={generateKey} className='w-10 h-10 flex justify-center items-center rounded-lg bg-gray/80 text-white'>
86+
<MdOutlineAddToPhotos className='text-[20px]' />
87+
</button>
88+
<button onClick={() => setSideBarOpen(false)} className='w-10 h-10 flex justify-center items-center rounded-lg bg-gray/80 text-white'>
89+
<FaChevronRight className='text-[20px]' />
90+
</button>
91+
</div>
92+
</div>
93+
<div className='flex flex-col gap-2'>
94+
95+
{keys.map((key, index) => {
96+
return (
97+
<div key={key} className={`p-3 transition-all flex justify-start px-[5%] duration-200 rounded-md ${selectedKey === key ? 'bg-gray text-white' : 'bg-gray text-white opacity-50'}`}>
98+
<p onClick={() => selectKey(key)} className='w-[90%] cursor-pointer text-start truncate'>
99+
{
100+
key === 'novel_content' ? 'Default Note' : `Note ${index}`
101+
}
102+
</p>
103+
{key !== 'novel_content' && <button onClick={
104+
() => handleRemove(key)
105+
} className='w-[10%] text-center'>
106+
<IoMdCloseCircleOutline className='text-[20px]' />
107+
</button>}
108+
109+
</div>
110+
)
111+
})}
112+
</div>
113+
</div>
114+
<Editor key={selectedKey} storageKey={selectedKey} defaultValue={{
115+
"type": "doc",
116+
"content": [
117+
{
118+
"type": "paragraph"
119+
}
120+
]
121+
}} onUpdate={(e) => {
122+
console.log(e)
123+
}} className='h-full text-white/80 w-full' />
124+
</div>
125+
)
126+
}
127+
128+
export default NoteComponent

lazyweb/components/desktop/ResourceCard/index.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ const ResourceCard = ({ url, title, description, image: res_image, resource:curr
285285
</p>
286286
</button>
287287
</div>
288-
<div className="my-2 flex flex-col gap-2 w-full">
288+
{/* <div className="my-2 flex flex-col gap-2 w-full">
289289
<button onClick={() => {
290290
event('edit-content', {
291291
category: 'edit-content-resource',
@@ -303,7 +303,7 @@ const ResourceCard = ({ url, title, description, image: res_image, resource:curr
303303
Edit Content
304304
</p>
305305
</button>
306-
</div>
306+
</div> */}
307307
</PopoverContent>
308308
</Popover>
309309
)

lazyweb/components/snippets/main.tsx

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
import React, { Suspense } from 'react'
1+
import React, { Suspense, useState } from 'react'
22
import NavBar from '../shared/NavBar/NavBar'
33
import Container from './micro/Container'
44
import dynamic from 'next/dynamic'
55
import { useRouter } from 'next/router'
66

7-
const Code = dynamic(() => import('./micro/Code'), { ssr: false })
87

98
type Props = {}
109

@@ -15,9 +14,14 @@ const FallBackUI = () => {
1514
</div>
1615
)
1716
}
17+
const Code = dynamic(() => import('./micro/Code'), {
18+
ssr: false,
19+
loading: () => <FallBackUI />
20+
})
1821

1922
const SnippetsContainer = (props: Props) => {
2023
const router = useRouter()
24+
const [show, setShow] = useState(false)
2125

2226
return (
2327
<div className='w-full md:block hidden'>
@@ -29,9 +33,7 @@ const SnippetsContainer = (props: Props) => {
2933

3034
<Code />
3135

32-
{router?.query?.style === 'stack' && <div className='w-full h-full absolute top-[10px] left-[10px] z-[0]'>
33-
<Code noHeading />
34-
</div>}
36+
3537

3638
</div>
3739
</Suspense>

lazyweb/components/snippets/micro/Code.tsx

+35-35
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import React, { useEffect, useState, lazy, Suspense } from 'react';
22
import { languages, themes, useSelectLanguage, useSelectTheme, useUIStore } from '@/hooks/Zustand';
33
import { useRouter } from 'next/router';
4-
import AceEditor from "react-ace";
54
import dynamic from 'next/dynamic';
5+
import AceEditor from 'react-ace';
66
import "ace-builds/src-noconflict/ext-language_tools";
77

88
//import theme dynamically
@@ -27,7 +27,7 @@ import "ace-builds/src-noconflict/theme-gob";
2727
import "ace-builds/src-noconflict/theme-gruvbox";
2828
import "ace-builds/src-noconflict/theme-idle_fingers";
2929

30-
//languages
30+
// //languages
3131
import "ace-builds/src-noconflict/mode-c_cpp";
3232
import "ace-builds/src-noconflict/mode-csharp";
3333
import "ace-builds/src-noconflict/mode-css";
@@ -116,39 +116,39 @@ const Code = ({ noHeading }: Props) => {
116116
} />
117117
<div />
118118
</div>}
119-
<Suspense fallback={<div>Loading Editor...</div>}>
120-
<AceEditor
121-
placeholder=""
122-
mode={selectedLanguage}
123-
theme={selectedTheme}
124-
className=''
125-
style={{ borderRadius: `${borderRadius}px`, width: '100%' }}
126-
onLoad={editor => {
127-
editor.renderer.setPadding(20);
128-
editor.renderer.setScrollMargin(50, 20, 0, 0);
129-
}}
130-
name="blah2"
131-
onChange={onChange}
132-
fontSize={16}
133-
showPrintMargin={false}
134-
minLines={5}
135-
maxLines={Infinity}
136-
showGutter={false}
137-
wrapEnabled={true}
138-
highlightActiveLine={false}
139-
value={value}
140-
setOptions={{
141-
enableBasicAutocompletion: false,
142-
enableLiveAutocompletion: false,
143-
enableSnippets: false,
144-
showLineNumbers: false,
145-
tabSize: 2,
146-
displayIndentGuides: false,
147-
cursorStyle: 'slim',
148-
wrap: true,
149-
}}
150-
/>
151-
</Suspense>
119+
120+
<AceEditor
121+
placeholder=""
122+
mode={selectedLanguage}
123+
theme={selectedTheme}
124+
className=''
125+
style={{ borderRadius: `${borderRadius}px`, width: '100%' }}
126+
onLoad={editor => {
127+
editor.renderer.setPadding(20);
128+
editor.renderer.setScrollMargin(50, 20, 0, 0);
129+
}}
130+
name="blah2"
131+
onChange={onChange}
132+
fontSize={16}
133+
showPrintMargin={false}
134+
minLines={5}
135+
maxLines={Infinity}
136+
showGutter={false}
137+
wrapEnabled={true}
138+
highlightActiveLine={false}
139+
value={value}
140+
setOptions={{
141+
enableBasicAutocompletion: false,
142+
enableLiveAutocompletion: false,
143+
enableSnippets: false,
144+
showLineNumbers: false,
145+
tabSize: 2,
146+
displayIndentGuides: false,
147+
cursorStyle: 'slim',
148+
wrap: true,
149+
}}
150+
/>
151+
152152
</div>
153153
);
154154
};

lazyweb/components/snippets/micro/Selector.tsx

+37-8
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ import ReactTooltip from 'react-tooltip';
1515
import { BiSolidColor } from "react-icons/bi";
1616
import { MdOutlineFileUpload } from "react-icons/md";
1717
import { FaRegClipboard } from "react-icons/fa6";
18-
/*
19-
20-
*/
18+
2119

2220

2321
type Props = {
@@ -38,7 +36,24 @@ const Selector = ({ save, saveSVG, savePDF, uploadImage, saveClip }: Props) => {
3836
let borderWidth = router.query.borderWidth as string || '1'
3937
let borderColor = router.query.borderColor as string || 'rgba(255,255,255,0.5)'
4038

41-
const setSelectedTheme = (theme: string) => {
39+
const loadTheme = async (themeName: any) => {
40+
await import(`ace-builds/src-noconflict/${themeName}.js`).catch((e) =>
41+
console.error(`Could not load theme: ${themeName}`, e)
42+
);
43+
};
44+
45+
const loadMode = async (modeName: any) => {
46+
await import(`ace-builds/src-noconflict/${modeName}.js`).catch((e) =>
47+
console.error(`Could not load mode: ${modeName}`, e)
48+
);
49+
};
50+
51+
52+
const setSelectedTheme = async (theme: string) => {
53+
// const selectedtheme = themes.find(t => t.name === theme)
54+
// if (selectedtheme) {
55+
// await loadTheme(selectedtheme.importName)
56+
// }
4257
router.replace({
4358
pathname: router.pathname,
4459
query: {
@@ -49,7 +64,11 @@ const Selector = ({ save, saveSVG, savePDF, uploadImage, saveClip }: Props) => {
4964

5065
}
5166

52-
const setSelectedLanguage = (language: string) => {
67+
const setSelectedLanguage = async (language: string) => {
68+
// const selectedlanguage = languages.find(t => t.value === language)
69+
// if (selectedlanguage) {
70+
// loadMode(selectedlanguage.importName)
71+
// }
5372
router.replace({
5473
pathname: router.pathname,
5574
query: {
@@ -71,9 +90,19 @@ const Selector = ({ save, saveSVG, savePDF, uploadImage, saveClip }: Props) => {
7190
}
7291

7392

74-
useEffect(() => {
75-
console.log(router.query, 'router.query')
76-
}, [router.query])
93+
// useEffect(() => {
94+
// const load = async () => {
95+
// const selectedtheme = themes.find(t => t.name === selectedTheme)
96+
// if (selectedtheme) {
97+
// await loadTheme(selectedtheme.importName)
98+
// }
99+
// const selectedlanguage = languages.find(t => t.value === selectedLanguage)
100+
// if (selectedlanguage) {
101+
// loadMode(selectedlanguage.importName)
102+
// }
103+
// }
104+
// load()
105+
// }, [selectedTheme, selectedLanguage])
77106

78107

79108

lazyweb/components/utility/Modals/LoginModal/LoginModal.tsx

+17-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ import axios from 'axios';
88
import { useUserData } from '@/hooks';
99
import { event } from 'nextjs-google-analytics';
1010

11+
const divWrapper = ({children}:any) => {
12+
return <div>{children}</div>
13+
}
14+
15+
1116
type Props = {
1217
isOpen: boolean,
1318
setIsOpen: (argo: boolean) => void
@@ -32,7 +37,9 @@ type DataGithub = {
3237
const LoginModal = ({ isOpen, setIsOpen }: Props) => {
3338
const [email, setEmail] = useState('')
3439
const [loading, setLoading] = useState(false)
35-
const [error, setError] = useState<AuthError | null>(null)
40+
const [error, setError] = useState<AuthError | null | {
41+
message: string
42+
}>(null)
3643
const [data, setData] = useState<Data | DataGithub | null>(null)
3744
const { setSession } = useUserData()
3845

@@ -51,12 +58,21 @@ const LoginModal = ({ isOpen, setIsOpen }: Props) => {
5158
}
5259

5360
const handleLogin = async () => {
61+
if(!email) return
62+
63+
//match regex email
64+
if(!email.match(/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/)) return setError({
65+
message: 'Invalid Email'
66+
})
67+
5468
setLoading(true)
5569
setData(null)
5670
setError(null)
5771
// const {data, error} = await supabaseClient.auth.signInWithOtp({
5872
// email,
5973
// })
74+
75+
6076
const {data} = await axios.post(`${process.env.NEXT_PUBLIC_LAZYWEB_BACKEND_URL}/api/auth/login`, {
6177
email
6278
})

0 commit comments

Comments
 (0)