#22 完了
This commit is contained in:
@@ -1,2 +1,16 @@
|
|||||||
class ApplicationController < ActionController::API
|
class ApplicationController < ActionController::API
|
||||||
|
before_action :authenticate_user
|
||||||
|
|
||||||
|
def current_user
|
||||||
|
@current_user
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def authenticate_user
|
||||||
|
code = request.headers['X-Transfer-Code'] || request.headers['HTTP_X_TRANSFER_CODE']
|
||||||
|
@current_user = User.find_by inheritance_code: code
|
||||||
|
Rails.logger.info("X-Transfer-Code: #{request.headers['X-Transfer-Code']}")
|
||||||
|
Rails.logger.info("current_user: #{@current_user&.id}")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -24,7 +24,10 @@ class PostsController < ApplicationController
|
|||||||
# GET /posts/1
|
# GET /posts/1
|
||||||
def show
|
def show
|
||||||
@post = Post.includes(:tags).find(params[:id])
|
@post = Post.includes(:tags).find(params[:id])
|
||||||
render json: @post.as_json(include: { tags: { only: [:id, :name, :category] } })
|
viewed = current_user&.viewed?(@post)
|
||||||
|
render json: (@post
|
||||||
|
.as_json(include: { tags: { only: [:id, :name, :category] } })
|
||||||
|
.merge(viewed: viewed))
|
||||||
end
|
end
|
||||||
|
|
||||||
# POST /posts
|
# POST /posts
|
||||||
@@ -38,6 +41,20 @@ class PostsController < ApplicationController
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def viewed
|
||||||
|
return head :unauthorized unless current_user
|
||||||
|
|
||||||
|
current_user.viewed_posts << Post.find(params[:id])
|
||||||
|
head :no_content
|
||||||
|
end
|
||||||
|
|
||||||
|
def unviewed
|
||||||
|
return head :unauthorized unless current_user
|
||||||
|
|
||||||
|
current_user.viewed_posts.delete(Post.find(params[:id]))
|
||||||
|
head :no_content
|
||||||
|
end
|
||||||
|
|
||||||
# PATCH/PUT /posts/1
|
# PATCH/PUT /posts/1
|
||||||
def update
|
def update
|
||||||
if @post.update(post_params)
|
if @post.update(post_params)
|
||||||
|
|||||||
@@ -17,6 +17,6 @@ class User < ApplicationRecord
|
|||||||
has_many :updated_wiki_pages, class_name: 'WikiPage', foreign_key: 'updated_user_id', dependent: :nullify
|
has_many :updated_wiki_pages, class_name: 'WikiPage', foreign_key: 'updated_user_id', dependent: :nullify
|
||||||
|
|
||||||
def viewed? post
|
def viewed? post
|
||||||
user_post_views.exists? post_id: post.id, viewed: true
|
user_post_views.exists? post_id: post.id
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ Rails.application.routes.draw do
|
|||||||
get "post_tags/create"
|
get "post_tags/create"
|
||||||
get "post_tags/update"
|
get "post_tags/update"
|
||||||
get "post_tags/destroy"
|
get "post_tags/destroy"
|
||||||
|
post 'posts/:id/viewed', to: 'posts#viewed'
|
||||||
|
delete 'posts/:id/viewed', to: 'posts#unviewed'
|
||||||
get "nico_tag_relation/index"
|
get "nico_tag_relation/index"
|
||||||
get "nico_tag_relation/show"
|
get "nico_tag_relation/show"
|
||||||
get "nico_tag_relation/create"
|
get "nico_tag_relation/create"
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class RemoveColumnFromUserPostView < ActiveRecord::Migration[8.0]
|
||||||
|
def change
|
||||||
|
remove_column :user_post_views, :viewed
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -19,7 +19,8 @@ type Post = { id: number
|
|||||||
url: string
|
url: string
|
||||||
title: string
|
title: string
|
||||||
thumbnail: string
|
thumbnail: string
|
||||||
tags: Tag[] }
|
tags: Tag[]
|
||||||
|
viewed: boolean }
|
||||||
|
|
||||||
type User = { id: number
|
type User = { id: number
|
||||||
name: string | null
|
name: string | null
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ import { Link, useLocation, useParams } from 'react-router-dom'
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { API_BASE_URL, SITE_TITLE } from '../config'
|
import { API_BASE_URL, SITE_TITLE } from '../config'
|
||||||
import NicoViewer from '../components/NicoViewer'
|
import NicoViewer from '../components/NicoViewer'
|
||||||
|
import { Button } from '@/components/ui/button'
|
||||||
|
import { toast } from '@/components/ui/use-toast'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
type Tag = { id: number
|
type Tag = { id: number
|
||||||
name: string
|
name: string
|
||||||
@@ -12,22 +15,51 @@ type Post = { id: number
|
|||||||
url: string
|
url: string
|
||||||
title: string
|
title: string
|
||||||
thumbnail: string
|
thumbnail: string
|
||||||
tags: Tag[] }
|
tags: Tag[]
|
||||||
|
viewed: boolean }
|
||||||
|
|
||||||
type Props = { posts: Post[]
|
type Props = { posts: Post[]
|
||||||
setPosts: (posts: Post[]) => void }
|
setPosts: (posts: Post[]) => void }
|
||||||
|
|
||||||
|
|
||||||
const PostDetailPage = (props: Props) => {
|
const PostDetailPage = ({ posts, setPosts }: Props) => {
|
||||||
const { posts, setPosts } = props
|
|
||||||
const { id } = useParams ()
|
const { id } = useParams ()
|
||||||
|
|
||||||
const location = useLocation ()
|
const location = useLocation ()
|
||||||
|
|
||||||
|
const changeViewedFlg = () => {
|
||||||
|
if (posts[0]?.viewed)
|
||||||
|
{
|
||||||
|
void (axios.delete (
|
||||||
|
`${ API_BASE_URL }/posts/${ id }/viewed`,
|
||||||
|
{ headers: { 'X-Transfer-Code': localStorage.getItem ('user_code') || '' } })
|
||||||
|
.then (res => setPosts (([post]) => {
|
||||||
|
post.viewed = false
|
||||||
|
return [post]
|
||||||
|
}))
|
||||||
|
.catch (err => toast ({ title: '失敗……',
|
||||||
|
description: '通信に失敗しました……' })))
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
void (axios.post (
|
||||||
|
`${ API_BASE_URL }/posts/${ id }/viewed`,
|
||||||
|
{ },
|
||||||
|
{ headers: { 'X-Transfer-Code': localStorage.getItem ('user_code') || '' } })
|
||||||
|
.then (res => setPosts (([post]) => {
|
||||||
|
post.viewed = true
|
||||||
|
return [post]
|
||||||
|
}))
|
||||||
|
.catch (err => toast ({ title: '失敗……',
|
||||||
|
description: '通信に失敗しました……' })))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
useEffect (() => {
|
useEffect (() => {
|
||||||
if (!(id))
|
if (!(id))
|
||||||
return
|
return
|
||||||
void (axios.get (`/api/posts/${ id }`)
|
void (axios.get (`${ API_BASE_URL }/posts/${ id }`, { headers: {
|
||||||
|
'X-Transfer-Code': localStorage.getItem ('user_code') || '' } })
|
||||||
.then (res => setPosts ([res.data]))
|
.then (res => setPosts ([res.data]))
|
||||||
.catch (err => console.error ('うんち!', err)))
|
.catch (err => console.error ('うんち!', err)))
|
||||||
}, [id])
|
}, [id])
|
||||||
@@ -56,6 +88,11 @@ const PostDetailPage = (props: Props) => {
|
|||||||
else
|
else
|
||||||
return <img src={post.thumbnail} alt={post.url} className="mb-4 w-full" />
|
return <img src={post.thumbnail} alt={post.url} className="mb-4 w-full" />
|
||||||
}) ()}
|
}) ()}
|
||||||
|
<Button onClick={changeViewedFlg}
|
||||||
|
className={cn ('text-white',
|
||||||
|
posts[0]?.viewed ? 'bg-blue-600 hover:bg-blue-700' : 'bg-gray-500 hover:bg-gray-600')}>
|
||||||
|
{posts[0]?.viewed ? '閲覧済' : '未閲覧'}
|
||||||
|
</Button>
|
||||||
</div>)
|
</div>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ type Post = { id: number
|
|||||||
url: string
|
url: string
|
||||||
title: string
|
title: string
|
||||||
thumbnail: string
|
thumbnail: string
|
||||||
tags: Tag[] }
|
tags: Tag[]
|
||||||
|
viewed: boolean }
|
||||||
|
|
||||||
type Props = { posts: Post[]
|
type Props = { posts: Post[]
|
||||||
setPosts: (posts: Post[]) => void }
|
setPosts: (posts: Post[]) => void }
|
||||||
|
|||||||
Reference in New Issue
Block a user