✨ User login
This commit is contained in:
		
							
								
								
									
										57
									
								
								.idea/codeStyles/Project.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								.idea/codeStyles/Project.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
				
			|||||||
 | 
					<component name="ProjectCodeStyleConfiguration">
 | 
				
			||||||
 | 
					  <code_scheme name="Project" version="173">
 | 
				
			||||||
 | 
					    <HTMLCodeStyleSettings>
 | 
				
			||||||
 | 
					      <option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" />
 | 
				
			||||||
 | 
					    </HTMLCodeStyleSettings>
 | 
				
			||||||
 | 
					    <JSCodeStyleSettings version="0">
 | 
				
			||||||
 | 
					      <option name="FORCE_SEMICOLON_STYLE" value="true" />
 | 
				
			||||||
 | 
					      <option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
 | 
				
			||||||
 | 
					      <option name="FORCE_QUOTE_STYlE" value="true" />
 | 
				
			||||||
 | 
					      <option name="ENFORCE_TRAILING_COMMA" value="Remove" />
 | 
				
			||||||
 | 
					      <option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
 | 
				
			||||||
 | 
					      <option name="SPACES_WITHIN_IMPORTS" value="true" />
 | 
				
			||||||
 | 
					    </JSCodeStyleSettings>
 | 
				
			||||||
 | 
					    <TypeScriptCodeStyleSettings version="0">
 | 
				
			||||||
 | 
					      <option name="FORCE_SEMICOLON_STYLE" value="true" />
 | 
				
			||||||
 | 
					      <option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
 | 
				
			||||||
 | 
					      <option name="FORCE_QUOTE_STYlE" value="true" />
 | 
				
			||||||
 | 
					      <option name="ENFORCE_TRAILING_COMMA" value="Remove" />
 | 
				
			||||||
 | 
					      <option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
 | 
				
			||||||
 | 
					      <option name="SPACES_WITHIN_IMPORTS" value="true" />
 | 
				
			||||||
 | 
					    </TypeScriptCodeStyleSettings>
 | 
				
			||||||
 | 
					    <VueCodeStyleSettings>
 | 
				
			||||||
 | 
					      <option name="INTERPOLATION_NEW_LINE_AFTER_START_DELIMITER" value="false" />
 | 
				
			||||||
 | 
					      <option name="INTERPOLATION_NEW_LINE_BEFORE_END_DELIMITER" value="false" />
 | 
				
			||||||
 | 
					    </VueCodeStyleSettings>
 | 
				
			||||||
 | 
					    <codeStyleSettings language="HTML">
 | 
				
			||||||
 | 
					      <option name="SOFT_MARGINS" value="120" />
 | 
				
			||||||
 | 
					      <indentOptions>
 | 
				
			||||||
 | 
					        <option name="INDENT_SIZE" value="2" />
 | 
				
			||||||
 | 
					        <option name="CONTINUATION_INDENT_SIZE" value="2" />
 | 
				
			||||||
 | 
					        <option name="TAB_SIZE" value="2" />
 | 
				
			||||||
 | 
					      </indentOptions>
 | 
				
			||||||
 | 
					    </codeStyleSettings>
 | 
				
			||||||
 | 
					    <codeStyleSettings language="JavaScript">
 | 
				
			||||||
 | 
					      <option name="SOFT_MARGINS" value="120" />
 | 
				
			||||||
 | 
					      <indentOptions>
 | 
				
			||||||
 | 
					        <option name="INDENT_SIZE" value="2" />
 | 
				
			||||||
 | 
					        <option name="CONTINUATION_INDENT_SIZE" value="2" />
 | 
				
			||||||
 | 
					        <option name="TAB_SIZE" value="2" />
 | 
				
			||||||
 | 
					      </indentOptions>
 | 
				
			||||||
 | 
					    </codeStyleSettings>
 | 
				
			||||||
 | 
					    <codeStyleSettings language="TypeScript">
 | 
				
			||||||
 | 
					      <option name="SOFT_MARGINS" value="120" />
 | 
				
			||||||
 | 
					      <indentOptions>
 | 
				
			||||||
 | 
					        <option name="INDENT_SIZE" value="2" />
 | 
				
			||||||
 | 
					        <option name="CONTINUATION_INDENT_SIZE" value="2" />
 | 
				
			||||||
 | 
					        <option name="TAB_SIZE" value="2" />
 | 
				
			||||||
 | 
					      </indentOptions>
 | 
				
			||||||
 | 
					    </codeStyleSettings>
 | 
				
			||||||
 | 
					    <codeStyleSettings language="Vue">
 | 
				
			||||||
 | 
					      <option name="SOFT_MARGINS" value="120" />
 | 
				
			||||||
 | 
					      <indentOptions>
 | 
				
			||||||
 | 
					        <option name="CONTINUATION_INDENT_SIZE" value="2" />
 | 
				
			||||||
 | 
					      </indentOptions>
 | 
				
			||||||
 | 
					    </codeStyleSettings>
 | 
				
			||||||
 | 
					  </code_scheme>
 | 
				
			||||||
 | 
					</component>
 | 
				
			||||||
							
								
								
									
										5
									
								
								.idea/codeStyles/codeStyleConfig.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.idea/codeStyles/codeStyleConfig.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					<component name="ProjectCodeStyleConfiguration">
 | 
				
			||||||
 | 
					  <state>
 | 
				
			||||||
 | 
					    <option name="USE_PER_PROJECT_SETTINGS" value="true" />
 | 
				
			||||||
 | 
					  </state>
 | 
				
			||||||
 | 
					</component>
 | 
				
			||||||
							
								
								
									
										6
									
								
								.idea/vcs.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.idea/vcs.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<project version="4">
 | 
				
			||||||
 | 
					  <component name="VcsDirectoryMappings">
 | 
				
			||||||
 | 
					    <mapping directory="" vcs="Git" />
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					</project>
 | 
				
			||||||
@@ -52,6 +52,7 @@ type AuthChallengeState = int8
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	ActiveChallengeState = AuthChallengeState(iota)
 | 
						ActiveChallengeState = AuthChallengeState(iota)
 | 
				
			||||||
 | 
						ExpiredChallengeState
 | 
				
			||||||
	FinishChallengeState
 | 
						FinishChallengeState
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -56,6 +56,8 @@ func NewChallenge(account models.Account, factors []models.AuthFactor, ip, ua st
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func DoChallenge(challenge models.AuthChallenge, factor models.AuthFactor, code string) error {
 | 
					func DoChallenge(challenge models.AuthChallenge, factor models.AuthFactor, code string) error {
 | 
				
			||||||
	if err := challenge.IsAvailable(); err != nil {
 | 
						if err := challenge.IsAvailable(); err != nil {
 | 
				
			||||||
 | 
							challenge.State = models.ExpiredChallengeState
 | 
				
			||||||
 | 
							database.C.Save(&challenge)
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if challenge.Progress >= challenge.Requirements {
 | 
						if challenge.Progress >= challenge.Requirements {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,13 +7,13 @@ import (
 | 
				
			|||||||
	"github.com/samber/lo"
 | 
						"github.com/samber/lo"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func GetFactorCode(factor models.AuthFactor) error {
 | 
					func GetFactorCode(factor models.AuthFactor) (bool, error) {
 | 
				
			||||||
	switch factor.Type {
 | 
						switch factor.Type {
 | 
				
			||||||
	case models.EmailPasswordFactor:
 | 
						case models.EmailPasswordFactor:
 | 
				
			||||||
		// TODO
 | 
							// TODO
 | 
				
			||||||
		return nil
 | 
							return true, nil
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return fmt.Errorf("unsupported factor to get code")
 | 
							return false, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -89,7 +89,7 @@ func doChallenge(c *fiber.Ctx) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func exchangeToken(c *fiber.Ctx) error {
 | 
					func exchangeToken(c *fiber.Ctx) error {
 | 
				
			||||||
	var data struct {
 | 
						var data struct {
 | 
				
			||||||
		Token     string `json:"token"`
 | 
							Code      string `json:"code"`
 | 
				
			||||||
		GrantType string `json:"grant_type"`
 | 
							GrantType string `json:"grant_type"`
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -99,7 +99,7 @@ func exchangeToken(c *fiber.Ctx) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	switch data.GrantType {
 | 
						switch data.GrantType {
 | 
				
			||||||
	case "authorization_code":
 | 
						case "authorization_code":
 | 
				
			||||||
		access, refresh, err := security.ExchangeToken(data.Token)
 | 
							access, refresh, err := security.ExchangeToken(data.Code)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return fiber.NewError(fiber.StatusBadRequest, err.Error())
 | 
								return fiber.NewError(fiber.StatusBadRequest, err.Error())
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -109,7 +109,7 @@ func exchangeToken(c *fiber.Ctx) error {
 | 
				
			|||||||
			"refresh_token": refresh,
 | 
								"refresh_token": refresh,
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	case "refresh_token":
 | 
						case "refresh_token":
 | 
				
			||||||
		access, refresh, err := security.RefreshToken(data.Token)
 | 
							access, refresh, err := security.RefreshToken(data.Code)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return fiber.NewError(fiber.StatusBadRequest, err.Error())
 | 
								return fiber.NewError(fiber.StatusBadRequest, err.Error())
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,9 +14,11 @@ func requestFactorToken(c *fiber.Ctx) error {
 | 
				
			|||||||
		return fiber.NewError(fiber.StatusNotFound, err.Error())
 | 
							return fiber.NewError(fiber.StatusNotFound, err.Error())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := security.GetFactorCode(factor); err != nil {
 | 
						if sent, err := security.GetFactorCode(factor); err != nil {
 | 
				
			||||||
		return fiber.NewError(fiber.StatusNotFound, err.Error())
 | 
							return fiber.NewError(fiber.StatusNotFound, err.Error())
 | 
				
			||||||
	}
 | 
						} else if !sent {
 | 
				
			||||||
 | 
							return c.SendStatus(fiber.StatusNoContent)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
		return c.SendStatus(fiber.StatusOK)
 | 
							return c.SendStatus(fiber.StatusOK)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,7 +29,7 @@ func LookupAccount(id string) (models.Account, error) {
 | 
				
			|||||||
		if err := database.C.
 | 
							if err := database.C.
 | 
				
			||||||
			Where(models.Account{
 | 
								Where(models.Account{
 | 
				
			||||||
				BaseModel: models.BaseModel{ID: contact.AccountID},
 | 
									BaseModel: models.BaseModel{ID: contact.AccountID},
 | 
				
			||||||
			}).First(&contact).Error; err == nil {
 | 
								}).First(&account).Error; err == nil {
 | 
				
			||||||
			return account, err
 | 
								return account, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										24
									
								
								view/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								view/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					# Logs
 | 
				
			||||||
 | 
					logs
 | 
				
			||||||
 | 
					*.log
 | 
				
			||||||
 | 
					npm-debug.log*
 | 
				
			||||||
 | 
					yarn-debug.log*
 | 
				
			||||||
 | 
					yarn-error.log*
 | 
				
			||||||
 | 
					pnpm-debug.log*
 | 
				
			||||||
 | 
					lerna-debug.log*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					node_modules
 | 
				
			||||||
 | 
					dist
 | 
				
			||||||
 | 
					dist-ssr
 | 
				
			||||||
 | 
					*.local
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Editor directories and files
 | 
				
			||||||
 | 
					.vscode/*
 | 
				
			||||||
 | 
					!.vscode/extensions.json
 | 
				
			||||||
 | 
					.idea
 | 
				
			||||||
 | 
					.DS_Store
 | 
				
			||||||
 | 
					*.suo
 | 
				
			||||||
 | 
					*.ntvs*
 | 
				
			||||||
 | 
					*.njsproj
 | 
				
			||||||
 | 
					*.sln
 | 
				
			||||||
 | 
					*.sw?
 | 
				
			||||||
							
								
								
									
										28
									
								
								view/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								view/README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					## Usage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```bash
 | 
				
			||||||
 | 
					$ npm install # or pnpm install or yarn install
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Learn more on the [Solid Website](https://solidjs.com) and come chat with us on our [Discord](https://discord.com/invite/solidjs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Available Scripts
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In the project directory, you can run:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### `npm run dev`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Runs the app in the development mode.<br>
 | 
				
			||||||
 | 
					Open [http://localhost:5173](http://localhost:5173) to view it in the browser.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### `npm run build`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Builds the app for production to the `dist` folder.<br>
 | 
				
			||||||
 | 
					It correctly bundles Solid in production mode and optimizes the build for the best performance.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The build is minified and the filenames include the hashes.<br>
 | 
				
			||||||
 | 
					Your app is ready to be deployed!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Deployment
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Learn more about deploying your application with the [documentations](https://vitejs.dev/guide/static-deploy.html)
 | 
				
			||||||
							
								
								
									
										13
									
								
								view/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								view/index.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					<!doctype html>
 | 
				
			||||||
 | 
					<html lang="en">
 | 
				
			||||||
 | 
					  <head>
 | 
				
			||||||
 | 
					    <meta charset="UTF-8" />
 | 
				
			||||||
 | 
					    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
 | 
				
			||||||
 | 
					    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
 | 
				
			||||||
 | 
					    <title>Goatpass</title>
 | 
				
			||||||
 | 
					  </head>
 | 
				
			||||||
 | 
					  <body>
 | 
				
			||||||
 | 
					    <div id="root"></div>
 | 
				
			||||||
 | 
					    <script type="module" src="/src/index.tsx"></script>
 | 
				
			||||||
 | 
					  </body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
							
								
								
									
										25
									
								
								view/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								view/package.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "name": "@hydrogen/passport-web",
 | 
				
			||||||
 | 
					  "private": true,
 | 
				
			||||||
 | 
					  "version": "0.0.0",
 | 
				
			||||||
 | 
					  "type": "module",
 | 
				
			||||||
 | 
					  "scripts": {
 | 
				
			||||||
 | 
					    "dev": "vite",
 | 
				
			||||||
 | 
					    "build": "tsc && vite build",
 | 
				
			||||||
 | 
					    "preview": "vite preview"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "dependencies": {
 | 
				
			||||||
 | 
					    "@solidjs/router": "^0.10.10",
 | 
				
			||||||
 | 
					    "solid-js": "^1.8.7",
 | 
				
			||||||
 | 
					    "universal-cookie": "^7.0.2"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "devDependencies": {
 | 
				
			||||||
 | 
					    "autoprefixer": "^10.4.17",
 | 
				
			||||||
 | 
					    "daisyui": "^4.6.0",
 | 
				
			||||||
 | 
					    "postcss": "^8.4.33",
 | 
				
			||||||
 | 
					    "tailwindcss": "^3.4.1",
 | 
				
			||||||
 | 
					    "typescript": "^5.2.2",
 | 
				
			||||||
 | 
					    "vite": "^5.0.8",
 | 
				
			||||||
 | 
					    "vite-plugin-solid": "^2.8.0"
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										6
									
								
								view/postcss.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								view/postcss.config.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					export default {
 | 
				
			||||||
 | 
					  plugins: {
 | 
				
			||||||
 | 
					    tailwindcss: {},
 | 
				
			||||||
 | 
					    autoprefixer: {},
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										5
									
								
								view/src/.prettierrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								view/src/.prettierrc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "printWidth": 120,
 | 
				
			||||||
 | 
					  "tabWidth": 2,
 | 
				
			||||||
 | 
					  "singleQuote": false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										197
									
								
								view/src/assets/fonts/fonts.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								view/src/assets/fonts/fonts.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,197 @@
 | 
				
			|||||||
 | 
					:root {
 | 
				
			||||||
 | 
					  --bs-body-font-family: "IBM Plex Serif", "Noto Serif SC", sans-serif !important;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					html,
 | 
				
			||||||
 | 
					body {
 | 
				
			||||||
 | 
					  font-family: var(--bs-body-font-family);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ibm-plex-serif-100 - latin */
 | 
				
			||||||
 | 
					@font-face {
 | 
				
			||||||
 | 
					  font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
 | 
				
			||||||
 | 
					  font-family: "IBM Plex Serif";
 | 
				
			||||||
 | 
					  font-style: normal;
 | 
				
			||||||
 | 
					  font-weight: 100;
 | 
				
			||||||
 | 
					  src: url("./ibm-plex-serif-v19-latin-100.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ibm-plex-serif-100italic - latin */
 | 
				
			||||||
 | 
					@font-face {
 | 
				
			||||||
 | 
					  font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
 | 
				
			||||||
 | 
					  font-family: "IBM Plex Serif";
 | 
				
			||||||
 | 
					  font-style: italic;
 | 
				
			||||||
 | 
					  font-weight: 100;
 | 
				
			||||||
 | 
					  src: url("./ibm-plex-serif-v19-latin-100italic.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ibm-plex-serif-200 - latin */
 | 
				
			||||||
 | 
					@font-face {
 | 
				
			||||||
 | 
					  font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
 | 
				
			||||||
 | 
					  font-family: "IBM Plex Serif";
 | 
				
			||||||
 | 
					  font-style: normal;
 | 
				
			||||||
 | 
					  font-weight: 200;
 | 
				
			||||||
 | 
					  src: url("./ibm-plex-serif-v19-latin-200.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ibm-plex-serif-200italic - latin */
 | 
				
			||||||
 | 
					@font-face {
 | 
				
			||||||
 | 
					  font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
 | 
				
			||||||
 | 
					  font-family: "IBM Plex Serif";
 | 
				
			||||||
 | 
					  font-style: italic;
 | 
				
			||||||
 | 
					  font-weight: 200;
 | 
				
			||||||
 | 
					  src: url("./ibm-plex-serif-v19-latin-200italic.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ibm-plex-serif-300 - latin */
 | 
				
			||||||
 | 
					@font-face {
 | 
				
			||||||
 | 
					  font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
 | 
				
			||||||
 | 
					  font-family: "IBM Plex Serif";
 | 
				
			||||||
 | 
					  font-style: normal;
 | 
				
			||||||
 | 
					  font-weight: 300;
 | 
				
			||||||
 | 
					  src: url("./ibm-plex-serif-v19-latin-300.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ibm-plex-serif-300italic - latin */
 | 
				
			||||||
 | 
					@font-face {
 | 
				
			||||||
 | 
					  font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
 | 
				
			||||||
 | 
					  font-family: "IBM Plex Serif";
 | 
				
			||||||
 | 
					  font-style: italic;
 | 
				
			||||||
 | 
					  font-weight: 300;
 | 
				
			||||||
 | 
					  src: url("./ibm-plex-serif-v19-latin-300italic.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ibm-plex-serif-regular - latin */
 | 
				
			||||||
 | 
					@font-face {
 | 
				
			||||||
 | 
					  font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
 | 
				
			||||||
 | 
					  font-family: "IBM Plex Serif";
 | 
				
			||||||
 | 
					  font-style: normal;
 | 
				
			||||||
 | 
					  font-weight: 400;
 | 
				
			||||||
 | 
					  src: url("./ibm-plex-serif-v19-latin-regular.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ibm-plex-serif-italic - latin */
 | 
				
			||||||
 | 
					@font-face {
 | 
				
			||||||
 | 
					  font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
 | 
				
			||||||
 | 
					  font-family: "IBM Plex Serif";
 | 
				
			||||||
 | 
					  font-style: italic;
 | 
				
			||||||
 | 
					  font-weight: 400;
 | 
				
			||||||
 | 
					  src: url("./ibm-plex-serif-v19-latin-italic.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ibm-plex-serif-500 - latin */
 | 
				
			||||||
 | 
					@font-face {
 | 
				
			||||||
 | 
					  font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
 | 
				
			||||||
 | 
					  font-family: "IBM Plex Serif";
 | 
				
			||||||
 | 
					  font-style: normal;
 | 
				
			||||||
 | 
					  font-weight: 500;
 | 
				
			||||||
 | 
					  src: url("./ibm-plex-serif-v19-latin-500.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ibm-plex-serif-500italic - latin */
 | 
				
			||||||
 | 
					@font-face {
 | 
				
			||||||
 | 
					  font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
 | 
				
			||||||
 | 
					  font-family: "IBM Plex Serif";
 | 
				
			||||||
 | 
					  font-style: italic;
 | 
				
			||||||
 | 
					  font-weight: 500;
 | 
				
			||||||
 | 
					  src: url("./ibm-plex-serif-v19-latin-500italic.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ibm-plex-serif-600 - latin */
 | 
				
			||||||
 | 
					@font-face {
 | 
				
			||||||
 | 
					  font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
 | 
				
			||||||
 | 
					  font-family: "IBM Plex Serif";
 | 
				
			||||||
 | 
					  font-style: normal;
 | 
				
			||||||
 | 
					  font-weight: 600;
 | 
				
			||||||
 | 
					  src: url("./ibm-plex-serif-v19-latin-600.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ibm-plex-serif-600italic - latin */
 | 
				
			||||||
 | 
					@font-face {
 | 
				
			||||||
 | 
					  font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
 | 
				
			||||||
 | 
					  font-family: "IBM Plex Serif";
 | 
				
			||||||
 | 
					  font-style: italic;
 | 
				
			||||||
 | 
					  font-weight: 600;
 | 
				
			||||||
 | 
					  src: url("./ibm-plex-serif-v19-latin-600italic.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ibm-plex-serif-700 - latin */
 | 
				
			||||||
 | 
					@font-face {
 | 
				
			||||||
 | 
					  font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
 | 
				
			||||||
 | 
					  font-family: "IBM Plex Serif";
 | 
				
			||||||
 | 
					  font-style: normal;
 | 
				
			||||||
 | 
					  font-weight: 700;
 | 
				
			||||||
 | 
					  src: url("./ibm-plex-serif-v19-latin-700.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ibm-plex-serif-700italic - latin */
 | 
				
			||||||
 | 
					@font-face {
 | 
				
			||||||
 | 
					  font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
 | 
				
			||||||
 | 
					  font-family: "IBM Plex Serif";
 | 
				
			||||||
 | 
					  font-style: italic;
 | 
				
			||||||
 | 
					  font-weight: 700;
 | 
				
			||||||
 | 
					  src: url("./ibm-plex-serif-v19-latin-700italic.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* noto-serif-sc-200 - chinese-simplified */
 | 
				
			||||||
 | 
					@font-face {
 | 
				
			||||||
 | 
					  font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
 | 
				
			||||||
 | 
					  font-family: "Noto Serif SC";
 | 
				
			||||||
 | 
					  font-style: normal;
 | 
				
			||||||
 | 
					  font-weight: 200;
 | 
				
			||||||
 | 
					  src: url("./noto-serif-sc-v22-chinese-simplified-200.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* noto-serif-sc-300 - chinese-simplified */
 | 
				
			||||||
 | 
					@font-face {
 | 
				
			||||||
 | 
					  font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
 | 
				
			||||||
 | 
					  font-family: "Noto Serif SC";
 | 
				
			||||||
 | 
					  font-style: normal;
 | 
				
			||||||
 | 
					  font-weight: 300;
 | 
				
			||||||
 | 
					  src: url("./noto-serif-sc-v22-chinese-simplified-300.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* noto-serif-sc-regular - chinese-simplified */
 | 
				
			||||||
 | 
					@font-face {
 | 
				
			||||||
 | 
					  font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
 | 
				
			||||||
 | 
					  font-family: "Noto Serif SC";
 | 
				
			||||||
 | 
					  font-style: normal;
 | 
				
			||||||
 | 
					  font-weight: 400;
 | 
				
			||||||
 | 
					  src: url("./noto-serif-sc-v22-chinese-simplified-regular.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* noto-serif-sc-500 - chinese-simplified */
 | 
				
			||||||
 | 
					@font-face {
 | 
				
			||||||
 | 
					  font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
 | 
				
			||||||
 | 
					  font-family: "Noto Serif SC";
 | 
				
			||||||
 | 
					  font-style: normal;
 | 
				
			||||||
 | 
					  font-weight: 500;
 | 
				
			||||||
 | 
					  src: url("./noto-serif-sc-v22-chinese-simplified-500.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* noto-serif-sc-600 - chinese-simplified */
 | 
				
			||||||
 | 
					@font-face {
 | 
				
			||||||
 | 
					  font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
 | 
				
			||||||
 | 
					  font-family: "Noto Serif SC";
 | 
				
			||||||
 | 
					  font-style: normal;
 | 
				
			||||||
 | 
					  font-weight: 600;
 | 
				
			||||||
 | 
					  src: url("./noto-serif-sc-v22-chinese-simplified-600.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* noto-serif-sc-700 - chinese-simplified */
 | 
				
			||||||
 | 
					@font-face {
 | 
				
			||||||
 | 
					  font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
 | 
				
			||||||
 | 
					  font-family: "Noto Serif SC";
 | 
				
			||||||
 | 
					  font-style: normal;
 | 
				
			||||||
 | 
					  font-weight: 700;
 | 
				
			||||||
 | 
					  src: url("./noto-serif-sc-v22-chinese-simplified-700.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* noto-serif-sc-900 - chinese-simplified */
 | 
				
			||||||
 | 
					@font-face {
 | 
				
			||||||
 | 
					  font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
 | 
				
			||||||
 | 
					  font-family: "Noto Serif SC";
 | 
				
			||||||
 | 
					  font-style: normal;
 | 
				
			||||||
 | 
					  font-weight: 900;
 | 
				
			||||||
 | 
					  src: url("./noto-serif-sc-v22-chinese-simplified-900.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-100.woff2
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-100.woff2
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-100italic.woff2
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-100italic.woff2
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-200.woff2
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-200.woff2
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-200italic.woff2
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-200italic.woff2
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-300.woff2
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-300.woff2
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-300italic.woff2
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-300italic.woff2
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-500.woff2
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-500.woff2
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-500italic.woff2
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-500italic.woff2
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-600.woff2
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-600.woff2
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-600italic.woff2
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-600italic.woff2
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-700.woff2
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-700.woff2
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-700italic.woff2
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-700italic.woff2
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-italic.woff2
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-italic.woff2
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-regular.woff2
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								view/src/assets/fonts/ibm-plex-serif-v19-latin-regular.woff2
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								view/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-200.woff2
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								view/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-200.woff2
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								view/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-300.woff2
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								view/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-300.woff2
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								view/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-500.woff2
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								view/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-500.woff2
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								view/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-600.woff2
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								view/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-600.woff2
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								view/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-700.woff2
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								view/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-700.woff2
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								view/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-900.woff2
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								view/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-900.woff2
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								view/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-regular.woff2
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								view/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-regular.woff2
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										9
									
								
								view/src/index.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								view/src/index.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					@tailwind base;
 | 
				
			||||||
 | 
					@tailwind components;
 | 
				
			||||||
 | 
					@tailwind utilities;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					html, body {
 | 
				
			||||||
 | 
					    padding: 0;
 | 
				
			||||||
 | 
					    margin: 0;
 | 
				
			||||||
 | 
					    height: 100vh;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										19
									
								
								view/src/index.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								view/src/index.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					/* @refresh reload */
 | 
				
			||||||
 | 
					import { render } from "solid-js/web";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "./index.css";
 | 
				
			||||||
 | 
					import "./assets/fonts/fonts.css";
 | 
				
			||||||
 | 
					import { Route, Router } from "@solidjs/router";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import RootLayout from "./layouts/RootLayout.tsx";
 | 
				
			||||||
 | 
					import Dashboard from "./pages/dashboard.tsx";
 | 
				
			||||||
 | 
					import Login from "./pages/auth/login.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const root = document.getElementById("root");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					render(() => (
 | 
				
			||||||
 | 
					  <Router root={RootLayout}>
 | 
				
			||||||
 | 
					    <Route path="/" component={Dashboard} />
 | 
				
			||||||
 | 
					    <Route path="/auth/login" component={Login} />
 | 
				
			||||||
 | 
					  </Router>
 | 
				
			||||||
 | 
					), root!);
 | 
				
			||||||
							
								
								
									
										11
									
								
								view/src/layouts/RootLayout.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								view/src/layouts/RootLayout.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					import Navbar from "./shared/Navbar.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function RootLayout(props: any) {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div>
 | 
				
			||||||
 | 
					      <Navbar />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <main class="h-[calc(100vh-68px)]">{props.children}</main>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										64
									
								
								view/src/layouts/shared/Navbar.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								view/src/layouts/shared/Navbar.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,64 @@
 | 
				
			|||||||
 | 
					import { For } from "solid-js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface MenuItem {
 | 
				
			||||||
 | 
					  label: string;
 | 
				
			||||||
 | 
					  href: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function Navbar() {
 | 
				
			||||||
 | 
					  const nav: MenuItem[] = [{ label: "Dashboard", href: "/" }];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div class="navbar bg-base-100 shadow-md px-5">
 | 
				
			||||||
 | 
					      <div class="navbar-start">
 | 
				
			||||||
 | 
					        <div class="dropdown">
 | 
				
			||||||
 | 
					          <div tabIndex={0} role="button" class="btn btn-ghost lg:hidden">
 | 
				
			||||||
 | 
					            <svg
 | 
				
			||||||
 | 
					              xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
					              class="h-5 w-5"
 | 
				
			||||||
 | 
					              fill="none"
 | 
				
			||||||
 | 
					              viewBox="0 0 24 24"
 | 
				
			||||||
 | 
					              stroke="currentColor"
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              <path
 | 
				
			||||||
 | 
					                stroke-linecap="round"
 | 
				
			||||||
 | 
					                stroke-linejoin="round"
 | 
				
			||||||
 | 
					                stroke-width="2"
 | 
				
			||||||
 | 
					                d="M4 6h16M4 12h8m-8 6h16"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </svg>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					          <ul
 | 
				
			||||||
 | 
					            tabIndex={0}
 | 
				
			||||||
 | 
					            class="menu menu-sm dropdown-content mt-3 z-[1] p-2 shadow bg-base-100 rounded-box w-52"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            <For each={nav}>
 | 
				
			||||||
 | 
					              {(item) => (
 | 
				
			||||||
 | 
					                <li>
 | 
				
			||||||
 | 
					                  <a href={item.href}>{item.label}</a>
 | 
				
			||||||
 | 
					                </li>
 | 
				
			||||||
 | 
					              )}
 | 
				
			||||||
 | 
					            </For>
 | 
				
			||||||
 | 
					          </ul>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <a href="/" class="btn btn-ghost text-xl">
 | 
				
			||||||
 | 
					          Goatpass
 | 
				
			||||||
 | 
					        </a>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <div class="navbar-center hidden lg:flex">
 | 
				
			||||||
 | 
					        <ul class="menu menu-horizontal px-1">
 | 
				
			||||||
 | 
					          <For each={nav}>
 | 
				
			||||||
 | 
					            {(item) => (
 | 
				
			||||||
 | 
					              <li>
 | 
				
			||||||
 | 
					                <a href={item.href}>{item.label}</a>
 | 
				
			||||||
 | 
					              </li>
 | 
				
			||||||
 | 
					            )}
 | 
				
			||||||
 | 
					          </For>
 | 
				
			||||||
 | 
					        </ul>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <div class="navbar-end pe-5">
 | 
				
			||||||
 | 
					        <a href="/auth/login" class="btn btn-sm btn-primary">Login</a>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										202
									
								
								view/src/pages/auth/login.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								view/src/pages/auth/login.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,202 @@
 | 
				
			|||||||
 | 
					import { useNavigate } from "@solidjs/router";
 | 
				
			||||||
 | 
					import { createSignal, For, Match, Show, Switch } from "solid-js";
 | 
				
			||||||
 | 
					import Cookie from "universal-cookie";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function Login() {
 | 
				
			||||||
 | 
					  const [title, setTitle] = createSignal("Sign in");
 | 
				
			||||||
 | 
					  const [subtitle, setSubtitle] = createSignal("Via your Goatpass account");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const [error, setError] = createSignal<null | string>(null);
 | 
				
			||||||
 | 
					  const [loading, setLoading] = createSignal(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const [factor, setFactor] = createSignal<number>();
 | 
				
			||||||
 | 
					  const [factors, setFactors] = createSignal<any[]>([]);
 | 
				
			||||||
 | 
					  const [challenge, setChallenge] = createSignal<any>();
 | 
				
			||||||
 | 
					  const [stage, setStage] = createSignal("starting");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const navigate = useNavigate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const handlers: { [id: string]: any } = {
 | 
				
			||||||
 | 
					    "starting": async (evt: SubmitEvent) => {
 | 
				
			||||||
 | 
					      evt.preventDefault();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const data = Object.fromEntries(new FormData(evt.target as HTMLFormElement));
 | 
				
			||||||
 | 
					      if (!data.id) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      setLoading(true);
 | 
				
			||||||
 | 
					      const res = await fetch("/api/auth", {
 | 
				
			||||||
 | 
					        method: "PUT",
 | 
				
			||||||
 | 
					        headers: { "Content-Type": "application/json" },
 | 
				
			||||||
 | 
					        body: JSON.stringify(data)
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      if (res.status !== 200) {
 | 
				
			||||||
 | 
					        setError(await res.text());
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        const data = await res.json();
 | 
				
			||||||
 | 
					        setTitle(`Welcome, ${data["display_name"]}`);
 | 
				
			||||||
 | 
					        setSubtitle("Before continue, we need verify that's you");
 | 
				
			||||||
 | 
					        setFactors(data["factors"]);
 | 
				
			||||||
 | 
					        setChallenge(data["challenge"]);
 | 
				
			||||||
 | 
					        setError(null);
 | 
				
			||||||
 | 
					        setStage("choosing");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      setLoading(false);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "choosing": async (evt: SubmitEvent) => {
 | 
				
			||||||
 | 
					      evt.preventDefault();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const data = Object.fromEntries(new FormData(evt.target as HTMLFormElement));
 | 
				
			||||||
 | 
					      if (!data.factor) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      setLoading(true);
 | 
				
			||||||
 | 
					      const res = await fetch(`/api/auth/factors/${data.id}`, {
 | 
				
			||||||
 | 
					        method: "POST"
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      if (res.status !== 200 && res.status !== 204) {
 | 
				
			||||||
 | 
					        setError(await res.text());
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        setTitle(`Enter the code`);
 | 
				
			||||||
 | 
					        setSubtitle(res.status === 204 ? "Enter your credentials" : "Code has been sent to your inbox");
 | 
				
			||||||
 | 
					        setError(null);
 | 
				
			||||||
 | 
					        setFactor(parseInt(data.factor as string));
 | 
				
			||||||
 | 
					        setStage("verifying");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      setLoading(false);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "verifying": async (evt: SubmitEvent) => {
 | 
				
			||||||
 | 
					      evt.preventDefault();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const data = Object.fromEntries(new FormData(evt.target as HTMLFormElement));
 | 
				
			||||||
 | 
					      if (!data.credentials) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      setLoading(true);
 | 
				
			||||||
 | 
					      const res = await fetch(`/api/auth`, {
 | 
				
			||||||
 | 
					        method: "POST",
 | 
				
			||||||
 | 
					        headers: { "Content-Type": "application/json" },
 | 
				
			||||||
 | 
					        body: JSON.stringify({
 | 
				
			||||||
 | 
					          challenge_id: challenge().id,
 | 
				
			||||||
 | 
					          factor_id: factor(),
 | 
				
			||||||
 | 
					          secret: data.credentials
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      if (res.status !== 200) {
 | 
				
			||||||
 | 
					        setError(await res.text());
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        const data = await res.json();
 | 
				
			||||||
 | 
					        if (data["is_finished"]) {
 | 
				
			||||||
 | 
					          await grantToken(data["session"]["grant_token"]);
 | 
				
			||||||
 | 
					          navigate("/");
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          setError(null);
 | 
				
			||||||
 | 
					          setStage("choosing");
 | 
				
			||||||
 | 
					          setTitle("Continue verifying");
 | 
				
			||||||
 | 
					          setSubtitle("You passed one check, but that's not enough.");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      setLoading(false);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  async function grantToken(tk: string) {
 | 
				
			||||||
 | 
					    const res = await fetch("/api/auth/token", {
 | 
				
			||||||
 | 
					      method: "POST",
 | 
				
			||||||
 | 
					      headers: { "Content-Type": "application/json" },
 | 
				
			||||||
 | 
					      body: JSON.stringify({
 | 
				
			||||||
 | 
					        code: tk,
 | 
				
			||||||
 | 
					        grant_type: "authorization_code"
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    if (res.status !== 200) {
 | 
				
			||||||
 | 
					      const err = await res.text();
 | 
				
			||||||
 | 
					      setError(err);
 | 
				
			||||||
 | 
					      throw new Error(err);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      const data = await res.json();
 | 
				
			||||||
 | 
					      new Cookie().set("access_token", data["access_token"], { path: "/" });
 | 
				
			||||||
 | 
					      new Cookie().set("refresh_token", data["refresh_token"], { path: "/" });
 | 
				
			||||||
 | 
					      setError(null);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function getFactorName(factor: any) {
 | 
				
			||||||
 | 
					    switch (factor.type) {
 | 
				
			||||||
 | 
					      case 0:
 | 
				
			||||||
 | 
					        return "Password Verification";
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
 | 
					        return "Unknown";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div class="w-full h-full flex justify-center items-center">
 | 
				
			||||||
 | 
					      <div class="card w-[480px] max-w-screen shadow-xl">
 | 
				
			||||||
 | 
					        <div class="card-body">
 | 
				
			||||||
 | 
					          <div id="header" class="text-center mb-5">
 | 
				
			||||||
 | 
					            <h1 class="text-xl font-bold">{title()}</h1>
 | 
				
			||||||
 | 
					            <p>{subtitle()}</p>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          <Show when={error()}>
 | 
				
			||||||
 | 
					            <div id="alerts" class="mt-1">
 | 
				
			||||||
 | 
					              <div role="alert" class="alert alert-error">
 | 
				
			||||||
 | 
					                <svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none"
 | 
				
			||||||
 | 
					                     viewBox="0 0 24 24">
 | 
				
			||||||
 | 
					                  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
 | 
				
			||||||
 | 
					                        d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" />
 | 
				
			||||||
 | 
					                </svg>
 | 
				
			||||||
 | 
					                <span class="capitalize">{error()}</span>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </Show>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          <form id="form" onSubmit={(e) => handlers[stage()](e)}>
 | 
				
			||||||
 | 
					            <Switch>
 | 
				
			||||||
 | 
					              <Match when={stage() === "starting"}>
 | 
				
			||||||
 | 
					                <label class="form-control w-full">
 | 
				
			||||||
 | 
					                  <div class="label">
 | 
				
			||||||
 | 
					                    <span class="label-text">Account ID</span>
 | 
				
			||||||
 | 
					                  </div>
 | 
				
			||||||
 | 
					                  <input name="id" type="text" placeholder="Type here" class="input input-bordered w-full" />
 | 
				
			||||||
 | 
					                  <div class="label">
 | 
				
			||||||
 | 
					                    <span class="label-text-alt">Your username, email or phone number.</span>
 | 
				
			||||||
 | 
					                  </div>
 | 
				
			||||||
 | 
					                </label>
 | 
				
			||||||
 | 
					              </Match>
 | 
				
			||||||
 | 
					              <Match when={stage() === "choosing"}>
 | 
				
			||||||
 | 
					                <div class="join join-vertical w-full">
 | 
				
			||||||
 | 
					                  <For each={factors()}>
 | 
				
			||||||
 | 
					                    {item =>
 | 
				
			||||||
 | 
					                      <input class="join-item btn" type="radio" name="factor"
 | 
				
			||||||
 | 
					                             value={item.id}
 | 
				
			||||||
 | 
					                             aria-label={getFactorName(item)}
 | 
				
			||||||
 | 
					                      />
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                  </For>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                <p class="text-center text-sm mt-2">Choose a way to verify that's you</p>
 | 
				
			||||||
 | 
					              </Match>
 | 
				
			||||||
 | 
					              <Match when={stage() === "verifying"}>
 | 
				
			||||||
 | 
					                <label class="form-control w-full">
 | 
				
			||||||
 | 
					                  <div class="label">
 | 
				
			||||||
 | 
					                    <span class="label-text">Credentials</span>
 | 
				
			||||||
 | 
					                  </div>
 | 
				
			||||||
 | 
					                  <input name="credentials" type="password" placeholder="Type here"
 | 
				
			||||||
 | 
					                         class="input input-bordered w-full" />
 | 
				
			||||||
 | 
					                  <div class="label">
 | 
				
			||||||
 | 
					                    <span class="label-text-alt">Password or one time password.</span>
 | 
				
			||||||
 | 
					                  </div>
 | 
				
			||||||
 | 
					                </label>
 | 
				
			||||||
 | 
					              </Match>
 | 
				
			||||||
 | 
					            </Switch>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <button type="submit" class="btn btn-primary btn-block mt-3" disabled={loading()}>
 | 
				
			||||||
 | 
					              <Show when={loading()} fallback={"Next"}>
 | 
				
			||||||
 | 
					                <span class="loading loading-spinner"></span>
 | 
				
			||||||
 | 
					              </Show>
 | 
				
			||||||
 | 
					            </button>
 | 
				
			||||||
 | 
					          </form>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										8
									
								
								view/src/pages/dashboard.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								view/src/pages/dashboard.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					export default function Dashboard() {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div class="container mx-auto pt-12">
 | 
				
			||||||
 | 
					      <h1 class="text-2xl font-bold">Welcome, undefined</h1>
 | 
				
			||||||
 | 
					      <p>What's a nice day!</p>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										1
									
								
								view/src/vite-env.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								view/src/vite-env.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					/// <reference types="vite/client" />
 | 
				
			||||||
							
								
								
									
										44
									
								
								view/tailwind.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								view/tailwind.config.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					/** @type {import("tailwindcss").Config} */
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					  content: [
 | 
				
			||||||
 | 
					    "./src/**/*.{js,jsx,ts,tsx}"
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  daisyui: {
 | 
				
			||||||
 | 
					    themes: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        light: {
 | 
				
			||||||
 | 
					          ...require("daisyui/src/theming/themes")["light"],
 | 
				
			||||||
 | 
					          primary: "#4750a3",
 | 
				
			||||||
 | 
					          secondary: "#93c5fd",
 | 
				
			||||||
 | 
					          accent: "#0f766e",
 | 
				
			||||||
 | 
					          info: "#67e8f9",
 | 
				
			||||||
 | 
					          success: "#15803d",
 | 
				
			||||||
 | 
					          warning: "#f97316",
 | 
				
			||||||
 | 
					          error: "#dc2626",
 | 
				
			||||||
 | 
					          "--rounded-box": "0",
 | 
				
			||||||
 | 
					          "--rounded-btn": "0",
 | 
				
			||||||
 | 
					          "--rounded-badge": "0",
 | 
				
			||||||
 | 
					          "--tab-radius": "0"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        dark: {
 | 
				
			||||||
 | 
					          ...require("daisyui/src/theming/themes")["dark"],
 | 
				
			||||||
 | 
					          primary: "#4750a3",
 | 
				
			||||||
 | 
					          secondary: "#93c5fd",
 | 
				
			||||||
 | 
					          accent: "#0f766e",
 | 
				
			||||||
 | 
					          info: "#67e8f9",
 | 
				
			||||||
 | 
					          success: "#15803d",
 | 
				
			||||||
 | 
					          warning: "#f97316",
 | 
				
			||||||
 | 
					          error: "#dc2626",
 | 
				
			||||||
 | 
					          "--rounded-box": "0",
 | 
				
			||||||
 | 
					          "--rounded-btn": "0",
 | 
				
			||||||
 | 
					          "--rounded-badge": "0",
 | 
				
			||||||
 | 
					          "--tab-radius": "0"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  plugins: [require("daisyui")]
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										26
									
								
								view/tsconfig.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								view/tsconfig.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "compilerOptions": {
 | 
				
			||||||
 | 
					    "target": "ES2020",
 | 
				
			||||||
 | 
					    "useDefineForClassFields": true,
 | 
				
			||||||
 | 
					    "module": "ESNext",
 | 
				
			||||||
 | 
					    "lib": ["ES2020", "DOM", "DOM.Iterable"],
 | 
				
			||||||
 | 
					    "skipLibCheck": true,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Bundler mode */
 | 
				
			||||||
 | 
					    "moduleResolution": "bundler",
 | 
				
			||||||
 | 
					    "allowImportingTsExtensions": true,
 | 
				
			||||||
 | 
					    "resolveJsonModule": true,
 | 
				
			||||||
 | 
					    "isolatedModules": true,
 | 
				
			||||||
 | 
					    "noEmit": true,
 | 
				
			||||||
 | 
					    "jsx": "preserve",
 | 
				
			||||||
 | 
					    "jsxImportSource": "solid-js",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Linting */
 | 
				
			||||||
 | 
					    "strict": true,
 | 
				
			||||||
 | 
					    "noUnusedLocals": true,
 | 
				
			||||||
 | 
					    "noUnusedParameters": true,
 | 
				
			||||||
 | 
					    "noFallthroughCasesInSwitch": true
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "include": ["src"],
 | 
				
			||||||
 | 
					  "references": [{ "path": "./tsconfig.node.json" }]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										10
									
								
								view/tsconfig.node.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								view/tsconfig.node.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "compilerOptions": {
 | 
				
			||||||
 | 
					    "composite": true,
 | 
				
			||||||
 | 
					    "skipLibCheck": true,
 | 
				
			||||||
 | 
					    "module": "ESNext",
 | 
				
			||||||
 | 
					    "moduleResolution": "bundler",
 | 
				
			||||||
 | 
					    "allowSyntheticDefaultImports": true
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "include": ["vite.config.ts"]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										11
									
								
								view/vite.config.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								view/vite.config.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					import { defineConfig } from 'vite'
 | 
				
			||||||
 | 
					import solid from 'vite-plugin-solid'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default defineConfig({
 | 
				
			||||||
 | 
					  plugins: [solid()],
 | 
				
			||||||
 | 
					  server: {
 | 
				
			||||||
 | 
					    proxy: {
 | 
				
			||||||
 | 
					      "/api": "http://localhost:8444"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
							
								
								
									
										1517
									
								
								view/yarn.lock
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1517
									
								
								view/yarn.lock
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user