diff --git a/app/javascript/components/Notification.jsx b/app/javascript/components/Notification.jsx new file mode 100644 index 00000000000..dbe05dcb380 --- /dev/null +++ b/app/javascript/components/Notification.jsx @@ -0,0 +1,62 @@ +import React from 'react' +import dayjs from 'dayjs' +import ja from 'dayjs/locale/ja' +dayjs.locale(ja) + +export default function Notification({ notification }) { + const createdAt = dayjs(notification.created_at).format( + 'YYYY年MM月DD日(ddd) HH:mm' + ) + const roleClass = `is-${notification.sender.primary_role}` + + return ( +
+
+
+ +
+
+
+
+
+ {notification.read === false && ( +
+ 未読 +
+ )} +

+ +

+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ ) +} diff --git a/app/javascript/components/Notifications.jsx b/app/javascript/components/Notifications.jsx new file mode 100644 index 00000000000..f725fca2c29 --- /dev/null +++ b/app/javascript/components/Notifications.jsx @@ -0,0 +1,113 @@ +import React from 'react' +import Notification from './Notification' +import LoadingListPlaceholder from './LoadingListPlaceholder' +import Pagination from './Pagination' +import UnconfirmedLink from './UnconfirmedLink' +import useSWR from 'swr' +import fetcher from '../fetcher' +import usePage from './hooks/usePage' + +export default function Notifications({ isMentor }) { + const per = 20 + const isUnreadPage = () => { + const params = new URLSearchParams(location.search) + return params.get('status') !== null && params.get('status') === 'unread' + } + const url = () => { + const params = new URLSearchParams(location.search) + return `/api/notifications.json?${params}` + } + + const { data, error } = useSWR(url, fetcher) + + const { page, setPage } = usePage() + + if (error) { + console.warn(error) + return
failed to load
+ } + + if (!data) { + return ( +
+ +
+ ) + } else if (data.notifications.length === 0) { + return ( +
+
+ +
+

+ {isUnreadPage ? '未読の通知はありません' : '通知はありません'} +

+
+ ) + } else { + const params = new URLSearchParams(location.search) + return ( + <> + +
+ {data.total_pages > 1 && ( + + )} +
+ {data.notifications.map((notification) => { + return ( + + ) + })} +
+ {isMentor && isUnreadPage() && ( + + )} + {data.total_pages > 1 && ( + + )} +
+ + ) + } +} diff --git a/app/javascript/notification.vue b/app/javascript/notification.vue deleted file mode 100644 index 0bbf9352f5d..00000000000 --- a/app/javascript/notification.vue +++ /dev/null @@ -1,49 +0,0 @@ - - diff --git a/app/javascript/notifications.js b/app/javascript/notifications.js deleted file mode 100644 index cc93b84557b..00000000000 --- a/app/javascript/notifications.js +++ /dev/null @@ -1,21 +0,0 @@ -import Vue from 'vue' -import Notifications from 'notifications.vue' - -document.addEventListener('DOMContentLoaded', () => { - const selector = '#js-notifications' - const notifications = document.querySelector(selector) - if (notifications) { - const isMentor = notifications.getAttribute('data-is-mentor') - const target = notifications.getAttribute('data-target') - new Vue({ - render: (h) => - h(Notifications, { - props: { - // 文字列を真偽値に変換して渡す - isMentor: isMentor === 'true', - target: target - } - }) - }).$mount(selector) - } -}) diff --git a/app/javascript/notifications.vue b/app/javascript/notifications.vue deleted file mode 100644 index e712784b5eb..00000000000 --- a/app/javascript/notifications.vue +++ /dev/null @@ -1,130 +0,0 @@ - - - diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index eeecca08434..666dfe648a5 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -29,7 +29,6 @@ import '../github_grass' import '../following.js' import '../hide-user.js' import '../categories-practice.js' -import '../notifications.js' import '../products.js' import '../courses-categories.js' import '../courses-practices.js' diff --git a/app/views/notifications/index.html.slim b/app/views/notifications/index.html.slim index a8590bb6a9b..738ce06b75d 100644 --- a/app/views/notifications/index.html.slim +++ b/app/views/notifications/index.html.slim @@ -42,11 +42,4 @@ main.page-main hr.a-border .page-body .container.is-md - nav.pill-nav - .container - ul.pill-nav__items - li.pill-nav__item - = link_to '未読', notifications_path(status: 'unread', target: @target), class: "pill-nav__item-link #{params[:status] == 'unread' ? 'is-active' : ''}" - li.pill-nav__item - = link_to '全て', notifications_path(target: @target), class: "pill-nav__item-link #{params[:status] == 'unread' ? '' : 'is-active'}" - #js-notifications(data-is-mentor="#{mentor_login?}" data-target="#{@target}") + = react_component('Notifications', isMentor: mentor_login?) diff --git a/test/system/notifications_test.rb b/test/system/notifications_test.rb index a0e72257ccb..461961ea163 100644 --- a/test/system/notifications_test.rb +++ b/test/system/notifications_test.rb @@ -88,7 +88,7 @@ class NotificationsTest < ApplicationSystemTestCase login_user 'mentormentaro', 'testtest' visit '/notifications' within first('nav.pagination') do - find('a', text: '2').click + find('button', text: '2').click end # 2ページ目に1番古い通知が表示されることを確認 assert_text '1番古い通知' @@ -123,7 +123,7 @@ class NotificationsTest < ApplicationSystemTestCase login_user 'mentormentaro', 'testtest' visit '/notifications?status=unread' within first('nav.pagination') do - find('a', text: '2').click + find('button', text: '2').click end assert_text '1番古い通知' assert_no_text '1番新しい通知' @@ -156,7 +156,7 @@ class NotificationsTest < ApplicationSystemTestCase login_user 'mentormentaro', 'testtest' visit '/notifications?status=unread&target=mention' within first('nav.pagination') do - find('a', text: '2').click + find('button', text: '2').click end assert_text '1番古い通知' assert_no_text '1番新しい通知' @@ -218,8 +218,9 @@ class NotificationsTest < ApplicationSystemTestCase login_user 'mentormentaro', 'testtest' visit '/notifications?page=2' within first('nav.pagination') do - find('a', text: '1').click + find('button', text: '1').click end + assert_text '1番新しい通知' page.go_back assert_text '1番古い通知' assert_no_text '1番新しい通知'