Browse Source

#22 完了

#23
みてるぞ 1 month ago
parent
commit
f93cea4e51
8 changed files with 85 additions and 8 deletions
  1. +14
    -0
      backend/app/controllers/application_controller.rb
  2. +18
    -1
      backend/app/controllers/posts_controller.rb
  3. +1
    -1
      backend/app/models/user.rb
  4. +2
    -0
      backend/config/routes.rb
  5. +5
    -0
      backend/db/migrate/20250529135850_remove_column_from_user_post_view.rb
  6. +2
    -1
      frontend/src/App.tsx
  7. +41
    -4
      frontend/src/pages/PostDetailPage.tsx
  8. +2
    -1
      frontend/src/pages/PostPage.tsx

+ 14
- 0
backend/app/controllers/application_controller.rb View File

@@ -1,2 +1,16 @@
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

+ 18
- 1
backend/app/controllers/posts_controller.rb View File

@@ -24,7 +24,10 @@ class PostsController < ApplicationController
# GET /posts/1
def show
@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

# POST /posts
@@ -38,6 +41,20 @@ class PostsController < ApplicationController
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
def update
if @post.update(post_params)


+ 1
- 1
backend/app/models/user.rb View File

@@ -17,6 +17,6 @@ class User < ApplicationRecord
has_many :updated_wiki_pages, class_name: 'WikiPage', foreign_key: 'updated_user_id', dependent: :nullify

def viewed? post
user_post_views.exists? post_id: post.id, viewed: true
user_post_views.exists? post_id: post.id
end
end

+ 2
- 0
backend/config/routes.rb View File

@@ -40,6 +40,8 @@ Rails.application.routes.draw do
get "post_tags/create"
get "post_tags/update"
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/show"
get "nico_tag_relation/create"


+ 5
- 0
backend/db/migrate/20250529135850_remove_column_from_user_post_view.rb View File

@@ -0,0 +1,5 @@
class RemoveColumnFromUserPostView < ActiveRecord::Migration[8.0]
def change
remove_column :user_post_views, :viewed
end
end

+ 2
- 1
frontend/src/App.tsx View File

@@ -19,7 +19,8 @@ type Post = { id: number
url: string
title: string
thumbnail: string
tags: Tag[] }
tags: Tag[]
viewed: boolean }

type User = { id: number
name: string | null


+ 41
- 4
frontend/src/pages/PostDetailPage.tsx View File

@@ -3,6 +3,9 @@ import { Link, useLocation, useParams } from 'react-router-dom'
import axios from 'axios'
import { API_BASE_URL, SITE_TITLE } from '../config'
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
name: string
@@ -12,22 +15,51 @@ type Post = { id: number
url: string
title: string
thumbnail: string
tags: Tag[] }
tags: Tag[]
viewed: boolean }

type Props = { posts: Post[]
setPosts: (posts: Post[]) => void }


const PostDetailPage = (props: Props) => {
const { posts, setPosts } = props
const PostDetailPage = ({ posts, setPosts }: Props) => {
const { id } = useParams ()

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 (() => {
if (!(id))
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]))
.catch (err => console.error ('うんち!', err)))
}, [id])
@@ -56,6 +88,11 @@ const PostDetailPage = (props: Props) => {
else
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>)
}



+ 2
- 1
frontend/src/pages/PostPage.tsx View File

@@ -11,7 +11,8 @@ type Post = { id: number
url: string
title: string
thumbnail: string
tags: Tag[] }
tags: Tag[]
viewed: boolean }

type Props = { posts: Post[]
setPosts: (posts: Post[]) => void }


Loading…
Cancel
Save