Lies
This commit is contained in:
parent
d87663d3d4
commit
9d028a40f1
244
enshi/package-lock.json
generated
244
enshi/package-lock.json
generated
@ -8,7 +8,7 @@
|
|||||||
"name": "enshi",
|
"name": "enshi",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/react-dialog": "^1.1.1",
|
"@radix-ui/react-dialog": "^1.1.2",
|
||||||
"@radix-ui/react-form": "^0.1.0",
|
"@radix-ui/react-form": "^0.1.0",
|
||||||
"@radix-ui/react-icons": "^1.3.2",
|
"@radix-ui/react-icons": "^1.3.2",
|
||||||
"@radix-ui/react-navigation-menu": "^1.2.1",
|
"@radix-ui/react-navigation-menu": "^1.2.1",
|
||||||
@ -1233,6 +1233,42 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-dialog": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-zysS+iU4YP3STKNS6USvFVqI4qqx8EpiwmT5TuCApVEBca+eRCbONi4EgzfNSuVnOXvC5UPHHMjs8RXO6DH9Bg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/primitive": "1.1.0",
|
||||||
|
"@radix-ui/react-compose-refs": "1.1.0",
|
||||||
|
"@radix-ui/react-context": "1.1.0",
|
||||||
|
"@radix-ui/react-dismissable-layer": "1.1.0",
|
||||||
|
"@radix-ui/react-focus-guards": "1.1.0",
|
||||||
|
"@radix-ui/react-focus-scope": "1.1.0",
|
||||||
|
"@radix-ui/react-id": "1.1.0",
|
||||||
|
"@radix-ui/react-portal": "1.1.1",
|
||||||
|
"@radix-ui/react-presence": "1.1.0",
|
||||||
|
"@radix-ui/react-primitive": "2.0.0",
|
||||||
|
"@radix-ui/react-slot": "1.1.0",
|
||||||
|
"@radix-ui/react-use-controllable-state": "1.1.0",
|
||||||
|
"aria-hidden": "^1.1.1",
|
||||||
|
"react-remove-scroll": "2.5.7"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/react-arrow": {
|
"node_modules/@radix-ui/react-arrow": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz",
|
||||||
@ -1420,25 +1456,25 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-dialog": {
|
"node_modules/@radix-ui/react-dialog": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.2.tgz",
|
||||||
"integrity": "sha512-zysS+iU4YP3STKNS6USvFVqI4qqx8EpiwmT5TuCApVEBca+eRCbONi4EgzfNSuVnOXvC5UPHHMjs8RXO6DH9Bg==",
|
"integrity": "sha512-Yj4dZtqa2o+kG61fzB0H2qUvmwBA2oyQroGLyNtBj1beo1khoQ3q1a2AO8rrQYjd8256CO9+N8L9tvsS+bnIyA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/primitive": "1.1.0",
|
"@radix-ui/primitive": "1.1.0",
|
||||||
"@radix-ui/react-compose-refs": "1.1.0",
|
"@radix-ui/react-compose-refs": "1.1.0",
|
||||||
"@radix-ui/react-context": "1.1.0",
|
"@radix-ui/react-context": "1.1.1",
|
||||||
"@radix-ui/react-dismissable-layer": "1.1.0",
|
"@radix-ui/react-dismissable-layer": "1.1.1",
|
||||||
"@radix-ui/react-focus-guards": "1.1.0",
|
"@radix-ui/react-focus-guards": "1.1.1",
|
||||||
"@radix-ui/react-focus-scope": "1.1.0",
|
"@radix-ui/react-focus-scope": "1.1.0",
|
||||||
"@radix-ui/react-id": "1.1.0",
|
"@radix-ui/react-id": "1.1.0",
|
||||||
"@radix-ui/react-portal": "1.1.1",
|
"@radix-ui/react-portal": "1.1.2",
|
||||||
"@radix-ui/react-presence": "1.1.0",
|
"@radix-ui/react-presence": "1.1.1",
|
||||||
"@radix-ui/react-primitive": "2.0.0",
|
"@radix-ui/react-primitive": "2.0.0",
|
||||||
"@radix-ui/react-slot": "1.1.0",
|
"@radix-ui/react-slot": "1.1.0",
|
||||||
"@radix-ui/react-use-controllable-state": "1.1.0",
|
"@radix-ui/react-use-controllable-state": "1.1.0",
|
||||||
"aria-hidden": "^1.1.1",
|
"aria-hidden": "^1.1.1",
|
||||||
"react-remove-scroll": "2.5.7"
|
"react-remove-scroll": "2.6.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "*",
|
"@types/react": "*",
|
||||||
@ -1455,6 +1491,158 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-context": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-dismissable-layer": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/primitive": "1.1.0",
|
||||||
|
"@radix-ui/react-compose-refs": "1.1.0",
|
||||||
|
"@radix-ui/react-primitive": "2.0.0",
|
||||||
|
"@radix-ui/react-use-callback-ref": "1.1.0",
|
||||||
|
"@radix-ui/react-use-escape-keydown": "1.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-focus-guards": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-portal": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/react-primitive": "2.0.0",
|
||||||
|
"@radix-ui/react-use-layout-effect": "1.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-presence": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/react-compose-refs": "1.1.0",
|
||||||
|
"@radix-ui/react-use-layout-effect": "1.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@radix-ui/react-dialog/node_modules/react-remove-scroll": {
|
||||||
|
"version": "2.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.0.tgz",
|
||||||
|
"integrity": "sha512-I2U4JVEsQenxDAKaVa3VZ/JeJZe0/2DxPWL8Tj8yLKctQJQiZM52pn/GWFpSp8dftjM3pSAHVJZscAnC/y+ySQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"react-remove-scroll-bar": "^2.3.6",
|
||||||
|
"react-style-singleton": "^2.2.1",
|
||||||
|
"tslib": "^2.1.0",
|
||||||
|
"use-callback-ref": "^1.3.0",
|
||||||
|
"use-sidecar": "^1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||||
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@radix-ui/react-dialog/node_modules/react-remove-scroll-bar": {
|
||||||
|
"version": "2.3.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz",
|
||||||
|
"integrity": "sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"react-style-singleton": "^2.2.1",
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||||
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/react-direction": {
|
"node_modules/@radix-ui/react-direction": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz",
|
||||||
@ -2682,6 +2870,42 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/themes/node_modules/@radix-ui/react-dialog": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-zysS+iU4YP3STKNS6USvFVqI4qqx8EpiwmT5TuCApVEBca+eRCbONi4EgzfNSuVnOXvC5UPHHMjs8RXO6DH9Bg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/primitive": "1.1.0",
|
||||||
|
"@radix-ui/react-compose-refs": "1.1.0",
|
||||||
|
"@radix-ui/react-context": "1.1.0",
|
||||||
|
"@radix-ui/react-dismissable-layer": "1.1.0",
|
||||||
|
"@radix-ui/react-focus-guards": "1.1.0",
|
||||||
|
"@radix-ui/react-focus-scope": "1.1.0",
|
||||||
|
"@radix-ui/react-id": "1.1.0",
|
||||||
|
"@radix-ui/react-portal": "1.1.1",
|
||||||
|
"@radix-ui/react-presence": "1.1.0",
|
||||||
|
"@radix-ui/react-primitive": "2.0.0",
|
||||||
|
"@radix-ui/react-slot": "1.1.0",
|
||||||
|
"@radix-ui/react-use-controllable-state": "1.1.0",
|
||||||
|
"aria-hidden": "^1.1.1",
|
||||||
|
"react-remove-scroll": "2.5.7"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/themes/node_modules/@radix-ui/react-navigation-menu": {
|
"node_modules/@radix-ui/themes/node_modules/@radix-ui/react-navigation-menu": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.2.0.tgz",
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/react-dialog": "^1.1.1",
|
"@radix-ui/react-dialog": "^1.1.2",
|
||||||
"@radix-ui/react-form": "^0.1.0",
|
"@radix-ui/react-form": "^0.1.0",
|
||||||
"@radix-ui/react-icons": "^1.3.2",
|
"@radix-ui/react-icons": "^1.3.2",
|
||||||
"@radix-ui/react-navigation-menu": "^1.2.1",
|
"@radix-ui/react-navigation-menu": "^1.2.1",
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Theme } from "@radix-ui/themes";
|
import { Theme, ThemePanel } from "@radix-ui/themes";
|
||||||
import "@radix-ui/themes/styles.css";
|
import "@radix-ui/themes/styles.css";
|
||||||
import { QueryClientProvider } from "@tanstack/react-query";
|
import { QueryClientProvider } from "@tanstack/react-query";
|
||||||
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
||||||
@ -17,7 +17,7 @@ export default function App() {
|
|||||||
<ToastProvider>
|
<ToastProvider>
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<RouterProvider router={router} />
|
<RouterProvider router={router} />
|
||||||
{/* <ThemePanel /> */}
|
<ThemePanel />
|
||||||
<ReactQueryDevtools/>
|
<ReactQueryDevtools/>
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
</ToastProvider>
|
</ToastProvider>
|
||||||
|
|||||||
@ -1,4 +1,14 @@
|
|||||||
import { Box, Container, Flex, Separator, Text } from "@radix-ui/themes";
|
import * as Dialog from "@radix-ui/react-dialog";
|
||||||
|
import { Cross2Icon } from "@radix-ui/react-icons";
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Container,
|
||||||
|
Flex,
|
||||||
|
Select,
|
||||||
|
Separator,
|
||||||
|
Text,
|
||||||
|
} from "@radix-ui/themes";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { Interweave } from "interweave";
|
import { Interweave } from "interweave";
|
||||||
import { useAtomValue } from "jotai";
|
import { useAtomValue } from "jotai";
|
||||||
@ -27,6 +37,8 @@ export default function ArticleViewer(props: TArticleViewer) {
|
|||||||
|
|
||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
|
gcTime: 0,
|
||||||
|
refetchOnMount: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isPending) return <SkeletonPostLoader />;
|
if (isPending) return <SkeletonPostLoader />;
|
||||||
@ -40,14 +52,19 @@ export default function ArticleViewer(props: TArticleViewer) {
|
|||||||
<Text className="mb-2" as="div" size={"9"}>
|
<Text className="mb-2" as="div" size={"9"}>
|
||||||
{data.title}
|
{data.title}
|
||||||
</Text>
|
</Text>
|
||||||
<Flex gap={"3"} className="mt-4 mb-2">
|
<Flex
|
||||||
|
gap={"3"}
|
||||||
|
className="items-center mt-4 mb-2 align-baseline"
|
||||||
|
>
|
||||||
<Flex gap={"1"}>
|
<Flex gap={"1"}>
|
||||||
<VoteButton
|
<VoteButton
|
||||||
vote={UPVOTE}
|
vote={UPVOTE}
|
||||||
postId={queryParams["postId"] || ""}
|
postId={queryParams["postId"] || ""}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<VoteCounter postId={queryParams["postId"] || ""} />
|
<VoteCounter
|
||||||
|
postId={queryParams["postId"] || ""}
|
||||||
|
/>
|
||||||
|
|
||||||
<VoteButton
|
<VoteButton
|
||||||
vote={DOWNVOTE}
|
vote={DOWNVOTE}
|
||||||
@ -60,6 +77,63 @@ export default function ArticleViewer(props: TArticleViewer) {
|
|||||||
postId={queryParams["postId"] || ""}
|
postId={queryParams["postId"] || ""}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
<Dialog.Root>
|
||||||
|
<Dialog.Trigger asChild>
|
||||||
|
<Button
|
||||||
|
variant="surface"
|
||||||
|
className="h-5"
|
||||||
|
>
|
||||||
|
Add to blog
|
||||||
|
</Button>
|
||||||
|
</Dialog.Trigger>
|
||||||
|
<Dialog.Portal>
|
||||||
|
<Dialog.Overlay className="fixed inset-0 bg-blackA6 data-[state=open]:animate-overlayShow" />
|
||||||
|
<Dialog.Content className="fixed left-1/2 top-1/2 max-h-[85vh] w-[90vw] max-w-[450px] -translate-x-1/2 -translate-y-1/2 rounded-md bg-white p-[25px] shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,_hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] focus:outline-none data-[state=open]:animate-contentShow">
|
||||||
|
<Dialog.Title className="m-0 text-[17px] font-medium text-mauve12">
|
||||||
|
Add this post to blog
|
||||||
|
</Dialog.Title>
|
||||||
|
<Dialog.Description className="mb-5 mt-2.5 text-[15px] leading-normal text-mauve11">
|
||||||
|
<Flex>
|
||||||
|
<Text>
|
||||||
|
{`Add "${data.title}" to blog...`}
|
||||||
|
</Text>
|
||||||
|
<Select.Root defaultValue="apple">
|
||||||
|
<Select.Trigger />
|
||||||
|
<Select.Content>
|
||||||
|
<Select.Group>
|
||||||
|
<Select.Item value="orange">
|
||||||
|
This
|
||||||
|
</Select.Item>
|
||||||
|
<Select.Item value="apple">
|
||||||
|
This is
|
||||||
|
updated blog
|
||||||
|
</Select.Item>
|
||||||
|
<Select.Item value="grape">
|
||||||
|
This another
|
||||||
|
</Select.Item>
|
||||||
|
</Select.Group>
|
||||||
|
</Select.Content>
|
||||||
|
</Select.Root>
|
||||||
|
</Flex>
|
||||||
|
</Dialog.Description>
|
||||||
|
|
||||||
|
<div className="mt-[25px] flex justify-end">
|
||||||
|
<Dialog.Close asChild>
|
||||||
|
<Button>Confirm</Button>
|
||||||
|
</Dialog.Close>
|
||||||
|
</div>
|
||||||
|
<Dialog.Close asChild>
|
||||||
|
<button
|
||||||
|
className="absolute right-2.5 top-2.5 inline-flex size-[25px] appearance-none items-center justify-center rounded-full text-violet11 hover:bg-violet4 focus:shadow-[0_0_0_2px] focus:shadow-violet7 focus:outline-none"
|
||||||
|
aria-label="Close"
|
||||||
|
>
|
||||||
|
<Cross2Icon />
|
||||||
|
</button>
|
||||||
|
</Dialog.Close>
|
||||||
|
</Dialog.Content>
|
||||||
|
</Dialog.Portal>
|
||||||
|
</Dialog.Root>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Separator size={"4"} className="mb-2" />
|
<Separator size={"4"} className="mb-2" />
|
||||||
|
|||||||
25
enshi/src/Components/BlogBox/BlogBox.tsx
Normal file
25
enshi/src/Components/BlogBox/BlogBox.tsx
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { Avatar, Card, Flex, Heading } from "@radix-ui/themes";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import UserNicknameLink from "../UserNicknameLink/UserNicknameLink";
|
||||||
|
|
||||||
|
type TBlogBox = {
|
||||||
|
title?: string;
|
||||||
|
blogId?: string;
|
||||||
|
userId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function BlogBox(props: TBlogBox) {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card className="w-full h-20" onClick={() => navigate(``)}>
|
||||||
|
<Flex direction={"column"}>
|
||||||
|
<Heading size={"4"}>{props?.title || "...No title..."}</Heading>
|
||||||
|
<Flex align={"center"} gap={"2"} mt={"1"}>
|
||||||
|
<Avatar size={"2"} className="rounded-full" fallback={"SI"} />
|
||||||
|
<UserNicknameLink userId={props.userId} />
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -1,15 +1,19 @@
|
|||||||
import * as NavigationMenu from "@radix-ui/react-navigation-menu";
|
import * as NavigationMenu from "@radix-ui/react-navigation-menu";
|
||||||
import { useThemeContext, Button, Heading } from "@radix-ui/themes";
|
import { Button, Heading, useThemeContext } from "@radix-ui/themes";
|
||||||
import { useNavigate, useLocation } from "react-router-dom";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
export default function CustomNavigationMenu() {
|
export default function CustomNavigationMenu() {
|
||||||
|
|
||||||
|
const {t} = useTranslation()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<NavigationMenu.Root orientation="horizontal">
|
<NavigationMenu.Root orientation="horizontal">
|
||||||
<NavigationMenu.List className="flex items-center justify-start gap-8">
|
<NavigationMenu.List className="flex items-center justify-start gap-8">
|
||||||
<NavItem text="Home" to="/" />
|
<NavItem text={t("home")} to="/" />
|
||||||
|
|
||||||
<NavItem text="Following" to="/c" />
|
<NavItem text={t("following")} to="/c" />
|
||||||
</NavigationMenu.List>
|
</NavigationMenu.List>
|
||||||
</NavigationMenu.Root>
|
</NavigationMenu.Root>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
33
enshi/src/Components/UserNicknameLink/UserNicknameLink.tsx
Normal file
33
enshi/src/Components/UserNicknameLink/UserNicknameLink.tsx
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { Skeleton, Text } from "@radix-ui/themes";
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
import { axiosLocalhost } from "../../api/axios/axios";
|
||||||
|
|
||||||
|
type TUserNicknameLink = {
|
||||||
|
userId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function UserNicknameLink(props: TUserNicknameLink) {
|
||||||
|
const { data, isPending } = useQuery({
|
||||||
|
queryKey: [`userLink${props.userId}`],
|
||||||
|
queryFn: async () => {
|
||||||
|
const response = await axiosLocalhost.get(
|
||||||
|
`/user/${props.userId || 0}`
|
||||||
|
);
|
||||||
|
return response.data as string;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isPending)
|
||||||
|
return (
|
||||||
|
<Skeleton>
|
||||||
|
<Text>@Nickname</Text>
|
||||||
|
</Skeleton>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link to={`/users/${data}`}>
|
||||||
|
<Text>@{data}</Text>
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -30,7 +30,8 @@ export default function PostRedactor() {
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
gcTime: Infinity,
|
gcTime: 0,
|
||||||
|
refetchOnMount: true
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { useState } from "react";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import { axiosLocalhost } from "../../../../api/axios/axios";
|
import { axiosLocalhost } from "../../../../api/axios/axios";
|
||||||
|
import useToast from "../../../../hooks/useToast";
|
||||||
|
|
||||||
type TSubmitChangesButton = {
|
type TSubmitChangesButton = {
|
||||||
className: string;
|
className: string;
|
||||||
@ -15,6 +16,7 @@ export default function SubmitChangesButton(props: TSubmitChangesButton) {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const [isDisabled, setIsDisabled] = useState(false);
|
const [isDisabled, setIsDisabled] = useState(false);
|
||||||
|
const createToast = useToast();
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const queryParams = useParams();
|
const queryParams = useParams();
|
||||||
@ -37,6 +39,7 @@ export default function SubmitChangesButton(props: TSubmitChangesButton) {
|
|||||||
setIsDisabled(false);
|
setIsDisabled(false);
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
|
createToast({title: "Post has been changed!"})
|
||||||
navigate("/");
|
navigate("/");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { useMutation } from "@tanstack/react-query";
|
|||||||
import { useSetAtom } from "jotai";
|
import { useSetAtom } from "jotai";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
import { axiosLocalhost } from "../../../api/axios/axios";
|
import { axiosLocalhost } from "../../../api/axios/axios";
|
||||||
import { userAtom } from "../../../AtomStore/AtomStore";
|
import { userAtom } from "../../../AtomStore/AtomStore";
|
||||||
import UseCapsLock from "../../../hooks/useCapsLock";
|
import UseCapsLock from "../../../hooks/useCapsLock";
|
||||||
@ -244,6 +244,21 @@ export default function RegisterPage() {
|
|||||||
<Text size={"3"}>{t("submit")}</Text>
|
<Text size={"3"}>{t("submit")}</Text>
|
||||||
</Button>
|
</Button>
|
||||||
</Form.Submit>
|
</Form.Submit>
|
||||||
|
|
||||||
|
<Text size={"1"} color="gray" className="block w-full text-center">
|
||||||
|
{t("alreadyRegistered")}{" "}
|
||||||
|
<Link to="/login">
|
||||||
|
<Text className="underline" weight={"bold"}>{t("logIn")}</Text>
|
||||||
|
</Link>{" "}
|
||||||
|
{t("now")}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Text size={"1"} color="gray" className="block w-full text-center">
|
||||||
|
{t("byPressingTheButton")}{" "}
|
||||||
|
<Link to="/register">
|
||||||
|
<Text className="underline" weight={"bold"}>{t("termsOfService")}</Text>.
|
||||||
|
</Link>
|
||||||
|
</Text>
|
||||||
</Form.Root>
|
</Form.Root>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import * as ScrollArea from "@radix-ui/react-scroll-area";
|
import * as ScrollArea from "@radix-ui/react-scroll-area";
|
||||||
import { Container } from "@radix-ui/themes";
|
import { Container, Flex, Heading, Separator } from "@radix-ui/themes";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
import { GetRandomPostsRow } from "../../@types/PostTypes";
|
import { GetRandomPostsRow } from "../../@types/PostTypes";
|
||||||
import { axiosLocalhost } from "../../api/axios/axios";
|
import { axiosLocalhost } from "../../api/axios/axios";
|
||||||
import PostCard from "./PostCard/PostCard";
|
import PostCard from "./PostCard/PostCard";
|
||||||
@ -8,6 +9,8 @@ import PostCard from "./PostCard/PostCard";
|
|||||||
const LIMIT = 10;
|
const LIMIT = 10;
|
||||||
|
|
||||||
export default function RandomPostsPage() {
|
export default function RandomPostsPage() {
|
||||||
|
const {t} = useTranslation()
|
||||||
|
|
||||||
const { data, refetch } = useQuery({
|
const { data, refetch } = useQuery({
|
||||||
queryKey: ["random_posts_key"],
|
queryKey: ["random_posts_key"],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
@ -27,8 +30,15 @@ export default function RandomPostsPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ScrollArea.Root className="w-full overflow-hidden grow-1">
|
<Flex direction={"column"} className="mx-auto">
|
||||||
<ScrollArea.Viewport className="rounded size-full">
|
<Heading size={"9"} weight={"regular"} className="text-center">
|
||||||
|
{t("discover")}
|
||||||
|
</Heading>
|
||||||
|
|
||||||
|
<Separator size={"4"} className="my-8" />
|
||||||
|
|
||||||
|
<ScrollArea.Root className="w-full h-full overflow-hidden">
|
||||||
|
<ScrollArea.Viewport className="overflow-scroll rounded size-full">
|
||||||
{data?.map((post, i) => {
|
{data?.map((post, i) => {
|
||||||
return (
|
return (
|
||||||
<Container size={"3"} key={`post${i}`}>
|
<Container size={"3"} key={`post${i}`}>
|
||||||
@ -38,19 +48,20 @@ export default function RandomPostsPage() {
|
|||||||
})}
|
})}
|
||||||
</ScrollArea.Viewport>
|
</ScrollArea.Viewport>
|
||||||
<ScrollArea.Scrollbar
|
<ScrollArea.Scrollbar
|
||||||
className="flex touch-none select-none bg-blackA3 p-0.5 transition-colors duration-[160ms] ease-out hover:bg-blackA5 data-[orientation=horizontal]:h-2.5 data-[orientation=vertical]:w-2.5 data-[orientation=horizontal]:flex-col"
|
className="z-50 flex touch-none select-none p-0.5 w-2"
|
||||||
orientation="vertical"
|
orientation="vertical"
|
||||||
>
|
>
|
||||||
<ScrollArea.Thumb className="relative flex-1 rounded-[10px] bg-mauve10 before:absolute before:left-1/2 before:top-1/2 before:size-full before:min-h-11 before:min-w-11 before:-translate-x-1/2 before:-translate-y-1/2" />
|
<ScrollArea.Thumb className="relative flex-1 rounded-[10px] bg-slate-200"/>
|
||||||
</ScrollArea.Scrollbar>
|
</ScrollArea.Scrollbar>
|
||||||
<ScrollArea.Scrollbar
|
{/* <ScrollArea.Scrollbar
|
||||||
className="flex touch-none select-none bg-blackA3 p-0.5 transition-colors duration-[160ms] ease-out hover:bg-blackA5 data-[orientation=horizontal]:h-2.5 data-[orientation=vertical]:w-2.5 data-[orientation=horizontal]:flex-col"
|
className="flex touch-none select-none bg-blackA3 p-0.5 transition-colors duration-[160ms] ease-out hover:bg-blackA5 data-[orientation=horizontal]:h-2.5 data-[orientation=vertical]:w-2.5 data-[orientation=horizontal]:flex-col"
|
||||||
orientation="horizontal"
|
orientation="horizontal"
|
||||||
>
|
>
|
||||||
<ScrollArea.Thumb className="relative flex-1 rounded-[10px] bg-mauve10 before:absolute before:left-1/2 before:top-1/2 before:size-full before:min-h-[44px] before:min-w-[44px] before:-translate-x-1/2 before:-translate-y-1/2" />
|
<ScrollArea.Thumb className="relative flex-1 rounded-[10px] bg-mauve10 before:absolute before:left-1/2 before:top-1/2 before:size-full before:min-h-[44px] before:min-w-[44px] before:-translate-x-1/2 before:-translate-y-1/2" />
|
||||||
</ScrollArea.Scrollbar>
|
</ScrollArea.Scrollbar> */}
|
||||||
<ScrollArea.Corner className="bg-blackA5" />
|
{/* <ScrollArea.Corner className="bg-blackA5" /> */}
|
||||||
</ScrollArea.Root>
|
</ScrollArea.Root>
|
||||||
|
</Flex>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,21 +0,0 @@
|
|||||||
import { Card } from '@radix-ui/themes';
|
|
||||||
import { useNavigate } from 'react-router-dom';
|
|
||||||
|
|
||||||
type TBlogBox = {
|
|
||||||
title?: string;
|
|
||||||
blogId?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function BlogBox(props: TBlogBox) {
|
|
||||||
|
|
||||||
const navigate = useNavigate()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Card className='w-full h-20'
|
|
||||||
onClick={() => navigate(``)}
|
|
||||||
>
|
|
||||||
{props?.title || "...No title..."}
|
|
||||||
{props?.blogId || "adqwwd"}
|
|
||||||
</Card>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,32 +1,20 @@
|
|||||||
import { Box, Container, Flex } from "@radix-ui/themes";
|
import * as Dialog from "@radix-ui/react-dialog";
|
||||||
|
import { Cross2Icon, PlusIcon } from "@radix-ui/react-icons";
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Container,
|
||||||
|
Flex,
|
||||||
|
Separator,
|
||||||
|
Text,
|
||||||
|
} from "@radix-ui/themes";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { useAtomValue } from "jotai";
|
|
||||||
import { userAtom } from "../../AtomStore/AtomStore";
|
|
||||||
import { axiosLocalhost } from "../../api/axios/axios";
|
import { axiosLocalhost } from "../../api/axios/axios";
|
||||||
import BlogBox from "./BlogBox/BlogBox";
|
import BlogBox from "../../Components/BlogBox/BlogBox";
|
||||||
|
import { JSONWithInt64 } from "../../utils/idnex";
|
||||||
import SkeletonBoxes from "./SkeletonBoxes/SkeletonBoxes";
|
import SkeletonBoxes from "./SkeletonBoxes/SkeletonBoxes";
|
||||||
|
|
||||||
export default function UserBlogsPage() {
|
export default function UserBlogsPage() {
|
||||||
const user = useAtomValue(userAtom);
|
|
||||||
|
|
||||||
const isBigNumber = (num: any) => !Number.isSafeInteger(+num);
|
|
||||||
|
|
||||||
const enquoteBigNumber = (jsonString: any, bigNumChecker: any) =>
|
|
||||||
jsonString.replaceAll(
|
|
||||||
/([:\s\[,]*)(\d+)([\s,\]]*)/g,
|
|
||||||
(matchingSubstr: any, prefix: any, bigNum: any, suffix: any) =>
|
|
||||||
bigNumChecker(bigNum)
|
|
||||||
? `${prefix}"${bigNum}"${suffix}`
|
|
||||||
: matchingSubstr
|
|
||||||
);
|
|
||||||
|
|
||||||
const parseWithBigInt = (jsonString: any, bigNumChecker: any) =>
|
|
||||||
JSON.parse(enquoteBigNumber(jsonString, bigNumChecker), (key, value) =>
|
|
||||||
!isNaN(value) && bigNumChecker(value)
|
|
||||||
? BigInt(value).toString()
|
|
||||||
: value
|
|
||||||
);
|
|
||||||
|
|
||||||
const { data, isPending, isFetching } = useQuery({
|
const { data, isPending, isFetching } = useQuery({
|
||||||
queryKey: ["userBlogs"],
|
queryKey: ["userBlogs"],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
@ -34,13 +22,13 @@ export default function UserBlogsPage() {
|
|||||||
transformResponse: [(data) => data],
|
transformResponse: [(data) => data],
|
||||||
});
|
});
|
||||||
|
|
||||||
let temp = parseWithBigInt(response.data, isBigNumber);
|
let temp = JSONWithInt64(response.data);
|
||||||
|
|
||||||
return temp as any[];
|
return temp as any[];
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isFetching)
|
if (isPending)
|
||||||
return (
|
return (
|
||||||
<Container size={"1"}>
|
<Container size={"1"}>
|
||||||
<SkeletonBoxes />
|
<SkeletonBoxes />
|
||||||
@ -51,17 +39,86 @@ export default function UserBlogsPage() {
|
|||||||
<Box className="size-full">
|
<Box className="size-full">
|
||||||
<Container size={"1"}>
|
<Container size={"1"}>
|
||||||
<Flex direction={"column"} gap={"2"}>
|
<Flex direction={"column"} gap={"2"}>
|
||||||
|
<Text size={"9"} className="text-center">
|
||||||
|
Your blogs
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Separator size={"4"} className="my-2" />
|
||||||
|
|
||||||
{data
|
{data
|
||||||
? data?.map((blog: any, b) => {
|
? data?.map((blog: any, b) => {
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<BlogBox
|
<BlogBox
|
||||||
key={b}
|
key={b}
|
||||||
title={blog.title}
|
title={blog.title}
|
||||||
blogId={blog.blog_id}
|
blogId={blog.blog_id}
|
||||||
|
userId={blog.user_id}
|
||||||
/>
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
: null}
|
: null}
|
||||||
|
|
||||||
|
<Dialog.Root>
|
||||||
|
<Dialog.Trigger asChild>
|
||||||
|
<Button onClick={() => {}}>
|
||||||
|
<PlusIcon />
|
||||||
|
</Button>
|
||||||
|
</Dialog.Trigger>
|
||||||
|
<Dialog.Portal>
|
||||||
|
<Dialog.Overlay className="fixed inset-0 bg-blackA6 data-[state=open]:animate-overlayShow" />
|
||||||
|
<Dialog.Content className="fixed left-1/2 top-1/2 max-h-[85vh] w-[90vw] max-w-[450px] -translate-x-1/2 -translate-y-1/2 rounded-md bg-white p-[25px] shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,_hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] focus:outline-none data-[state=open]:animate-contentShow">
|
||||||
|
<Dialog.Title className="m-0 text-[17px] font-medium text-mauve12">
|
||||||
|
Create blog
|
||||||
|
</Dialog.Title>
|
||||||
|
<Dialog.Description className="mb-5 mt-2.5 text-[15px] leading-normal text-mauve11">
|
||||||
|
Create your new blog.
|
||||||
|
</Dialog.Description>
|
||||||
|
<fieldset className="mb-[15px] flex items-center gap-5">
|
||||||
|
<label
|
||||||
|
className="w-[90px] text-right text-[15px] text-violet11"
|
||||||
|
htmlFor="title"
|
||||||
|
>
|
||||||
|
Blog title
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
className="inline-flex h-[35px] w-full flex-1 items-center justify-center rounded px-2.5 text-[15px] leading-none text-violet11 shadow-[0_0_0_1px] shadow-violet7 outline-none focus:shadow-[0_0_0_2px] focus:shadow-violet8"
|
||||||
|
id="title"
|
||||||
|
defaultValue="My blog"
|
||||||
|
/>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset className="mb-[15px] flex items-center gap-5">
|
||||||
|
<label
|
||||||
|
className="w-[90px] text-right text-[15px] text-violet11"
|
||||||
|
htmlFor="Description"
|
||||||
|
>
|
||||||
|
Description
|
||||||
|
</label>
|
||||||
|
<textarea
|
||||||
|
className="pt-2 inline-flex h-[35px] w-full flex-1 items-center justify-center rounded px-2.5 text-[15px] leading-none text-violet11 shadow-[0_0_0_1px] shadow-violet7 outline-none focus:shadow-[0_0_0_2px] focus:shadow-violet8"
|
||||||
|
id="Description"
|
||||||
|
placeholder="Your description..."
|
||||||
|
/>
|
||||||
|
</fieldset>
|
||||||
|
<div className="mt-[25px] flex justify-end">
|
||||||
|
<Dialog.Close asChild>
|
||||||
|
<Button>
|
||||||
|
Create blog
|
||||||
|
</Button>
|
||||||
|
</Dialog.Close>
|
||||||
|
</div>
|
||||||
|
<Dialog.Close asChild>
|
||||||
|
<button
|
||||||
|
className="absolute right-2.5 top-2.5 inline-flex size-[25px] appearance-none items-center justify-center rounded-full text-violet11 hover:bg-violet4 focus:shadow-[0_0_0_2px] focus:shadow-violet7 focus:outline-none"
|
||||||
|
aria-label="Close"
|
||||||
|
>
|
||||||
|
<Cross2Icon />
|
||||||
|
</button>
|
||||||
|
</Dialog.Close>
|
||||||
|
</Dialog.Content>
|
||||||
|
</Dialog.Portal>
|
||||||
|
</Dialog.Root>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Container>
|
</Container>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@ -20,10 +20,24 @@ const en = {
|
|||||||
registerForm: "Register",
|
registerForm: "Register",
|
||||||
loginForm: "Log in",
|
loginForm: "Log in",
|
||||||
|
|
||||||
|
alreadyRegistered: "Already registered?",
|
||||||
|
|
||||||
suggestRegister: "Don't have an account?",
|
suggestRegister: "Don't have an account?",
|
||||||
register: "Register",
|
register: "Register",
|
||||||
now: "now!",
|
now: "now!",
|
||||||
|
|
||||||
|
logIn: "Log in",
|
||||||
|
|
||||||
|
updatePost: "Update",
|
||||||
|
|
||||||
|
byPressingTheButton: "By pressing the submit button you agree with our",
|
||||||
|
termsOfService: "Terms Of Service",
|
||||||
|
|
||||||
|
discover: "Discover something new...",
|
||||||
|
|
||||||
|
home: "Home",
|
||||||
|
following: "Following",
|
||||||
|
|
||||||
errors: {
|
errors: {
|
||||||
enterUsername: "Please enter your username",
|
enterUsername: "Please enter your username",
|
||||||
enterEmail: "Please enter your email",
|
enterEmail: "Please enter your email",
|
||||||
|
|||||||
@ -21,10 +21,25 @@ const ru = {
|
|||||||
registerForm: "Регистрация",
|
registerForm: "Регистрация",
|
||||||
loginForm: "Вход",
|
loginForm: "Вход",
|
||||||
|
|
||||||
|
alreadyRegistered: "Уже есть аккаунт?",
|
||||||
|
|
||||||
suggestRegister: "Не зарегистрированы?",
|
suggestRegister: "Не зарегистрированы?",
|
||||||
register: "Создайте аккаунт",
|
register: "Создайте аккаунт",
|
||||||
now: "сейчас!",
|
now: "сейчас!",
|
||||||
|
|
||||||
|
logIn: "Войдите",
|
||||||
|
|
||||||
|
byPressingTheButton: "Нажимая `Подтвердить`, вы соглашаетесь с нашими",
|
||||||
|
termsOfService: "Условиями предоставления услуг.",
|
||||||
|
|
||||||
|
updatePost: "Изменить",
|
||||||
|
|
||||||
|
discover: "Найдите что-то новое",
|
||||||
|
|
||||||
|
home: "Главная",
|
||||||
|
following: "Отслеживаемые",
|
||||||
|
|
||||||
|
|
||||||
errors: {
|
errors: {
|
||||||
enterUsername: "Это обязательное поле",
|
enterUsername: "Это обязательное поле",
|
||||||
enterEmail: "Это обязательное поле",
|
enterEmail: "Это обязательное поле",
|
||||||
|
|||||||
19
enshi/src/utils/idnex.ts
Normal file
19
enshi/src/utils/idnex.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
const isBigNumber = (num: any) => !Number.isSafeInteger(+num);
|
||||||
|
|
||||||
|
const enquoteBigNumber = (jsonString: any, bigNumChecker: any) =>
|
||||||
|
jsonString.replaceAll(
|
||||||
|
/([:\s\[,]*)(\d+)([\s,\]]*)/g,
|
||||||
|
(matchingSubstr: any, prefix: any, bigNum: any, suffix: any) =>
|
||||||
|
bigNumChecker(bigNum)
|
||||||
|
? `${prefix}"${bigNum}"${suffix}`
|
||||||
|
: matchingSubstr
|
||||||
|
);
|
||||||
|
|
||||||
|
const parseWithBigInt = (jsonString: any, bigNumChecker: any) =>
|
||||||
|
JSON.parse(enquoteBigNumber(jsonString, bigNumChecker), (_key, value) =>
|
||||||
|
!isNaN(value) && bigNumChecker(value) ? BigInt(value).toString() : value
|
||||||
|
);
|
||||||
|
|
||||||
|
export const JSONWithInt64 = (jsonString: any) => {
|
||||||
|
return parseWithBigInt(jsonString, isBigNumber);
|
||||||
|
};
|
||||||
@ -152,6 +152,17 @@ func (q *Queries) GetUserByUsername(ctx context.Context, username string) (User,
|
|||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getUserUsernameById = `-- name: GetUserUsernameById :one
|
||||||
|
SELECT username FROM users WHERE user_id = $1
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) GetUserUsernameById(ctx context.Context, userID int64) (string, error) {
|
||||||
|
row := q.db.QueryRow(ctx, getUserUsernameById, userID)
|
||||||
|
var username string
|
||||||
|
err := row.Scan(&username)
|
||||||
|
return username, err
|
||||||
|
}
|
||||||
|
|
||||||
const updateUserPasswordHash = `-- name: UpdateUserPasswordHash :one
|
const updateUserPasswordHash = `-- name: UpdateUserPasswordHash :one
|
||||||
UPDATE public.users
|
UPDATE public.users
|
||||||
SET "password"=$1
|
SET "password"=$1
|
||||||
|
|||||||
@ -4,6 +4,9 @@ SELECT * FROM users;
|
|||||||
-- name: GetUserById :one
|
-- name: GetUserById :one
|
||||||
SELECT * FROM users WHERE user_id = $1;
|
SELECT * FROM users WHERE user_id = $1;
|
||||||
|
|
||||||
|
-- name: GetUserUsernameById :one
|
||||||
|
SELECT username FROM users WHERE user_id = $1;
|
||||||
|
|
||||||
-- name: GetUserByUsername :one
|
-- name: GetUserByUsername :one
|
||||||
SELECT * FROM users WHERE username = $1;
|
SELECT * FROM users WHERE username = $1;
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import (
|
|||||||
bookmarksroutes "enshi/routes/bookmarksRoutes"
|
bookmarksroutes "enshi/routes/bookmarksRoutes"
|
||||||
"enshi/routes/postsRoutes"
|
"enshi/routes/postsRoutes"
|
||||||
"enshi/routes/userProfileRoutes"
|
"enshi/routes/userProfileRoutes"
|
||||||
|
userroutes "enshi/routes/userRoutes"
|
||||||
voteroutes "enshi/routes/voteRoutes"
|
voteroutes "enshi/routes/voteRoutes"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
@ -176,10 +177,16 @@ func SetupRotes(g *gin.Engine) error {
|
|||||||
|
|
||||||
temporal := g.Group("/")
|
temporal := g.Group("/")
|
||||||
temporal.Use(middleware.AuthMiddleware())
|
temporal.Use(middleware.AuthMiddleware())
|
||||||
|
|
||||||
temporal.GET(
|
temporal.GET(
|
||||||
"/user/blogs",
|
"/user/blogs",
|
||||||
blogRoutes.GetUserBlogs,
|
blogRoutes.GetUserBlogs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
freeGroup.GET(
|
||||||
|
"/user/:user-id",
|
||||||
|
userroutes.GetUserUsername,
|
||||||
|
)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
30
enshi_back/routes/userRoutes/getUser.go
Normal file
30
enshi_back/routes/userRoutes/getUser.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package userroutes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
rest_api_stuff "enshi/REST_API_stuff"
|
||||||
|
db_repo "enshi/db/go_queries"
|
||||||
|
"enshi/db_connection"
|
||||||
|
"enshi/middleware/getters"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetUserUsername(c *gin.Context) {
|
||||||
|
userId, err := getters.GetInt64Param(c, "user-id")
|
||||||
|
if err != nil {
|
||||||
|
rest_api_stuff.BadRequestAnswer(c, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
userInfo, err := db_repo.New(db_connection.Dbx).GetUserUsernameById(
|
||||||
|
context.Background(),
|
||||||
|
userId,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
rest_api_stuff.InternalErrorAnswer(c, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.IndentedJSON(http.StatusOK, userInfo)
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user