feature(settingsPage): add input fields dynamically
0
package.json
Executable file → Normal file
0
pnpm-lock.yaml
Executable file → Normal file
0
public/icon-with-shadow.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
0
public/icon/128.png
Executable file → Normal file
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
0
public/icon/16.png
Executable file → Normal file
Before Width: | Height: | Size: 698 B After Width: | Height: | Size: 698 B |
0
public/icon/32.png
Executable file → Normal file
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
0
public/icon/48.png
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
public/icon/96.png
Executable file → Normal file
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 7.9 KiB |
0
src/background.ts
Executable file → Normal file
|
@ -1,25 +0,0 @@
|
|||
import { Grid, styled, TextField, Typography } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
|
||||
const FormGrid = styled(Grid)(() => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column'
|
||||
}))
|
||||
|
||||
export default function SettingsPage() {
|
||||
const [data, setData] = useState([{title: '', subtitle: '', hyperlink: ''}])
|
||||
|
||||
return (
|
||||
<Grid container spacing={3} sx={{mt: 4, mb: 4}}>
|
||||
<FormGrid item xs={12} md={6}>
|
||||
<TextField
|
||||
required
|
||||
id='text'
|
||||
label='text'
|
||||
name='text'
|
||||
onChange={e => console.log(e.target.name)}
|
||||
/>
|
||||
</FormGrid>
|
||||
</Grid>
|
||||
)
|
||||
}
|
0
src/index.html
Executable file → Normal file
10
src/index.tsx
Executable file → Normal file
|
@ -1,7 +1,6 @@
|
|||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import App from './site/App'
|
||||
import MenuBar from './components/MenuBar';
|
||||
import '@fontsource/roboto/300.css';
|
||||
import '@fontsource/roboto/400.css';
|
||||
import '@fontsource/roboto/500.css';
|
||||
|
@ -9,8 +8,9 @@ import '@fontsource/roboto/700.css';
|
|||
import { ThemeProvider } from '@mui/material/styles';
|
||||
import { CssBaseline } from '@mui/material';
|
||||
import theme from './theme';
|
||||
import { DrawerOpenContextProvider } from './contexts/DrawerOpenContext';
|
||||
import { CurrentPageContextProvider } from './contexts/CurrentPageContext';
|
||||
import { DrawerOpenContextProvider } from './shared/contexts/DrawerOpenContext';
|
||||
import { CurrentPageContextProvider } from './shared/contexts/CurrentPageContext';
|
||||
import { ConfigurableLinksContextProvider } from './shared/contexts/ConfiguarableLinksContext';
|
||||
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
|
@ -18,7 +18,9 @@ ReactDOM.createRoot(document.getElementById('root')!).render(
|
|||
<CssBaseline>
|
||||
<DrawerOpenContextProvider>
|
||||
<CurrentPageContextProvider>
|
||||
<App />
|
||||
<ConfigurableLinksContextProvider>
|
||||
<App />
|
||||
</ConfigurableLinksContextProvider>
|
||||
</CurrentPageContextProvider>
|
||||
</DrawerOpenContextProvider>
|
||||
</CssBaseline>
|
||||
|
|
0
src/manifest.json
Executable file → Normal file
0
src/popup.tsx
Executable file → Normal file
0
src/popup/Popup.css
Executable file → Normal file
2
src/popup/Popup.tsx
Executable file → Normal file
|
@ -1,6 +1,6 @@
|
|||
import { useEffect } from 'react';
|
||||
import "./Popup.css";
|
||||
import Sites from "@Data/sites.json"
|
||||
import Sites from '@Data/sites.json'
|
||||
import React from 'react';
|
||||
|
||||
export default function() {
|
||||
|
|
0
src/components/MenuBar.tsx → src/shared/components/MenuBar.tsx
Executable file → Normal file
0
src/components/linkcard.tsx → src/shared/components/linkcard.tsx
Executable file → Normal file
70
src/shared/components/settingsPage.tsx
Normal file
|
@ -0,0 +1,70 @@
|
|||
import { Button, Grid, styled, TextField, Typography } from "@mui/material";
|
||||
import { useContext, useState } from "react";
|
||||
import { HomepageLink } from "../interfaces/HomepageLink.interface";
|
||||
import { ConfigurableLinksContext } from "../contexts/ConfiguarableLinksContext";
|
||||
|
||||
const FormGrid = styled(Grid)(() => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column'
|
||||
}))
|
||||
|
||||
interface FormRowProps {
|
||||
index: number
|
||||
link: HomepageLink
|
||||
}
|
||||
|
||||
export default function SettingsPage() {
|
||||
const {configurableLinks, setConfigurableLinks} = useContext(ConfigurableLinksContext)
|
||||
|
||||
const handleChange = (index: number, event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
||||
let newconfigurableLinks = [...configurableLinks]
|
||||
newconfigurableLinks[index][event.target.name as keyof HomepageLink] = event.target.value
|
||||
setConfigurableLinks(newconfigurableLinks)
|
||||
}
|
||||
|
||||
const addFields = () => {
|
||||
setConfigurableLinks([...configurableLinks, {} as HomepageLink])
|
||||
}
|
||||
|
||||
return (
|
||||
<Grid container spacing={1} sx={{mt: 4, mb: 4}}>
|
||||
{configurableLinks.map((link, index) =>(
|
||||
<>
|
||||
<Grid item xs={4}>
|
||||
<TextField
|
||||
fullWidth
|
||||
required
|
||||
label='Title'
|
||||
name='title'
|
||||
value={link.title}
|
||||
onChange={e => handleChange(index, e)}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
<TextField
|
||||
fullWidth
|
||||
required
|
||||
label='Subtitle'
|
||||
name='subtitle'
|
||||
value={link.subtitle}
|
||||
onChange={e => handleChange(index, e)}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
<TextField
|
||||
fullWidth
|
||||
required
|
||||
label='Hyperlink'
|
||||
name='hyperlink'
|
||||
value={link.hyperlink}
|
||||
onChange={e => handleChange(index, e)}
|
||||
/>
|
||||
</Grid>
|
||||
</>
|
||||
))}
|
||||
<Grid>
|
||||
<Button onClick={addFields}>Add field</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
)
|
||||
}
|
25
src/shared/contexts/ConfiguarableLinksContext.tsx
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { createContext, Dispatch, SetStateAction, useState } from "react"
|
||||
import { HomepageLink } from "../interfaces/HomepageLink.interface"
|
||||
import { ContainerProps } from "@mui/material"
|
||||
|
||||
type ConfigurableLinksContextType = {
|
||||
configurableLinks: Array<HomepageLink>,
|
||||
setConfigurableLinks: Dispatch<SetStateAction<Array<HomepageLink>>>
|
||||
}
|
||||
|
||||
const ConfigurableLinksContext = createContext<ConfigurableLinksContextType>({
|
||||
configurableLinks: new Array<HomepageLink>,
|
||||
setConfigurableLinks: () => {}
|
||||
})
|
||||
|
||||
const ConfigurableLinksContextProvider = (props: ContainerProps) => {
|
||||
const [configurableLinks, setConfigurableLinks] = useState(new Array<HomepageLink>)
|
||||
|
||||
return (
|
||||
<ConfigurableLinksContext.Provider value={{configurableLinks, setConfigurableLinks}}>
|
||||
{props.children}
|
||||
</ConfigurableLinksContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export {ConfigurableLinksContext, ConfigurableLinksContextProvider}
|
0
src/data/sites.json → src/shared/data/sites.json
Executable file → Normal file
5
src/shared/interfaces/HomepageLink.interface.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
export interface HomepageLink {
|
||||
title: string
|
||||
subtitle: string,
|
||||
hyperlink: string
|
||||
}
|
10
src/site/App.tsx
Executable file → Normal file
|
@ -1,12 +1,12 @@
|
|||
import Sites from '@Data/sites.json'
|
||||
import { Box, Button, debounce, FormLabel, Grid, OutlinedInput, styled, TextField, Typography } from '@mui/material'
|
||||
import React, { useContext, useState } from 'react'
|
||||
import MenuBar from '../components/MenuBar'
|
||||
import LinkCard from '../components/linkcard'
|
||||
import MenuBar from '../shared/components/MenuBar'
|
||||
import LinkCard from '../shared/components/linkcard'
|
||||
import { Link, Route } from 'wouter'
|
||||
import MenuDrawer from '../components/menudrawer'
|
||||
import { CurrentPageContext } from '../contexts/CurrentPageContext'
|
||||
import SettingsPage from '../components/settingsPage'
|
||||
import MenuDrawer from '../shared/components/menudrawer'
|
||||
import { CurrentPageContext } from '../shared/contexts/CurrentPageContext'
|
||||
import SettingsPage from '../shared/components/settingsPage'
|
||||
|
||||
const useLocalStorage = (storageKey: string, fallbackState: any) => {
|
||||
const [value, setValue] = React.useState(
|
||||
|
|
0
src/theme.ts
Executable file → Normal file
0
src/vite-env.d.ts
vendored
Executable file → Normal file
2
tsconfig.json
Executable file → Normal file
|
@ -17,7 +17,7 @@
|
|||
"jsx": "react-jsx",
|
||||
"paths": {
|
||||
"@Data/*": [
|
||||
"./src/data/*"
|
||||
"./src/shared/data/*"
|
||||
],
|
||||
}
|
||||
},
|
||||
|
|
0
tsconfig.node.json
Executable file → Normal file
2
vite.config.ts
Executable file → Normal file
|
@ -25,7 +25,7 @@ export default defineConfig({
|
|||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
"@Data": path.resolve(__dirname, './src/data')
|
||||
"@Data": path.resolve(__dirname, './src/shared/data')
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|