| @@ -1,16 +1,25 @@ | |||||
| class UsersController < ApplicationController | class UsersController < ApplicationController | ||||
| def index | |||||
| end | |||||
| def show | |||||
| end | |||||
| def create | def create | ||||
| user = User.create!(inheritance_code: SecureRandom.uuid, role: 'guest') | |||||
| render json: { code: user.inheritance_code, | |||||
| user: user.slice(:id, :name, :inheritance_code, :role) } | |||||
| end | end | ||||
| def update | |||||
| def verify | |||||
| user = User.find_by(inheritance_code: params[:code]) | |||||
| render json: if user | |||||
| { valid: true, user: user.slice(:id, :name, :inheritance_code, :role) } | |||||
| else | |||||
| { valid: false } | |||||
| end | |||||
| end | end | ||||
| def destroy | |||||
| def me | |||||
| user = User.find_by(inheritance_code: params[:code]) | |||||
| render(if user | |||||
| { json: user.slice(:id, :name, :inheritance_code, :role) } | |||||
| else | |||||
| { json: { error: 'not found' }, status: :not_found } | |||||
| end) | |||||
| end | end | ||||
| end | end | ||||
| @@ -61,7 +61,12 @@ Rails.application.routes.draw do | |||||
| resources :tags | resources :tags | ||||
| resources :user_ips | resources :user_ips | ||||
| resources :user_post_views | resources :user_post_views | ||||
| resources :users | |||||
| resources :users, only: [:create] do | |||||
| collection do | |||||
| post :verify | |||||
| get :me | |||||
| end | |||||
| end | |||||
| resources :wiki_pages | resources :wiki_pages | ||||
| # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html | # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html | ||||
| @@ -6,6 +6,8 @@ import TopNav from './components/TopNav' | |||||
| import TagSidebar from './components/TagSidebar' | import TagSidebar from './components/TagSidebar' | ||||
| import PostPage from './pages/PostPage' | import PostPage from './pages/PostPage' | ||||
| import PostDetailPage from './pages/PostDetailPage' | import PostDetailPage from './pages/PostDetailPage' | ||||
| import { API_BASE_URL } from './config' | |||||
| import axios from 'axios' | |||||
| type Tag = { id: number | type Tag = { id: number | ||||
| name: string | name: string | ||||
| @@ -17,18 +19,48 @@ type Post = { id: number | |||||
| thumbnail: string | thumbnail: string | ||||
| tags: Tag[] } | tags: Tag[] } | ||||
| type User = { id: number | |||||
| name: string | null | |||||
| inheritanceCode: string | |||||
| role: string } | |||||
| const App = () => { | const App = () => { | ||||
| const [posts, setPosts] = useState<Post[]> ([]) | const [posts, setPosts] = useState<Post[]> ([]) | ||||
| const [user, setUser] = useState<User | null> (null) | |||||
| useEffect (() => { | useEffect (() => { | ||||
| const createUser = () => ( | |||||
| axios.post (`${ API_BASE_URL }/users`) | |||||
| .then (res => { | |||||
| if (res.data.code) | |||||
| { | |||||
| localStorage.setItem ('user_code', res.data.code) | |||||
| setUser (res.data) | |||||
| } | |||||
| })) | |||||
| const code = localStorage.getItem ('user_code') | |||||
| if (code) | |||||
| { | |||||
| void (axios.post (`${ API_BASE_URL }/users/verify`, { code }) | |||||
| .then (res => { | |||||
| if (res.data.valid) | |||||
| setUser (res.data.user) | |||||
| else | |||||
| createUser () | |||||
| })) | |||||
| } | |||||
| else | |||||
| createUser () | |||||
| alert ('このサイトはまだ作りかけです!!!!\n出てけ!!!!!!!!!!!!!!!!!!!!') | alert ('このサイトはまだ作りかけです!!!!\n出てけ!!!!!!!!!!!!!!!!!!!!') | ||||
| }, []) | }, []) | ||||
| return ( | return ( | ||||
| <Router> | <Router> | ||||
| <div className="flex flex-col h-screen w-screen"> | <div className="flex flex-col h-screen w-screen"> | ||||
| <TopNav /> | |||||
| <TopNav user={user} /> | |||||
| <div className="flex flex-1"> | <div className="flex flex-1"> | ||||
| <TagSidebar posts={posts} setPosts={setPosts} /> | <TagSidebar posts={posts} setPosts={setPosts} /> | ||||
| <main className="flex-1 overflow-y-auto p-4"> | <main className="flex-1 overflow-y-auto p-4"> | ||||
| @@ -1,7 +1,15 @@ | |||||
| import React from "react" | import React from "react" | ||||
| import { Link } from 'react-router-dom' | import { Link } from 'react-router-dom' | ||||
| const TopNav: React.FC = () => ( | |||||
| type User = { id: number | |||||
| name: string | null | |||||
| inheritanceCode: string | |||||
| role: string } | |||||
| type Props = { user: User } | |||||
| const TopNav: React.FC = ({ user }: Props) => ( | |||||
| <nav className="bg-gray-800 text-white p-3 flex justify-between items-center w-full"> | <nav className="bg-gray-800 text-white p-3 flex justify-between items-center w-full"> | ||||
| <div className="flex items-center gap-4"> | <div className="flex items-center gap-4"> | ||||
| <Link to="/" className="text-xl font-bold text-orange-500">ぼざクリ タグ広場</Link> | <Link to="/" className="text-xl font-bold text-orange-500">ぼざクリ タグ広場</Link> | ||||
| @@ -11,8 +19,9 @@ const TopNav: React.FC = () => ( | |||||
| <Link to="/wiki" className="hover:text-orange-500">Wiki</Link> | <Link to="/wiki" className="hover:text-orange-500">Wiki</Link> | ||||
| </div> | </div> | ||||
| <div className="ml-auto pr-4"> | <div className="ml-auto pr-4"> | ||||
| <Link to="/login" className="hover:text-orange-500">ログイン</Link> | |||||
| <Link to="/setting" className="hover:text-orange-500">{user?.name || '名もなきニジラー'}</Link> | |||||
| </div> | </div> | ||||
| </nav>) | </nav>) | ||||
| export default TopNav | export default TopNav | ||||