Skip to content

Commit 18608ed

Browse files
committed
feature completed top page
1 parent 57b13aa commit 18608ed

File tree

15 files changed

+287
-120
lines changed

15 files changed

+287
-120
lines changed

backend/app/api/v0/shared/urls.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22
from django.conf.urls import include
33
from django.urls import re_path
44
from rest_framework.routers import DefaultRouter
5-
5+
from db_schema.views import *
66
from .views.data import *
77

88
router = DefaultRouter()
99

1010

1111
urlpatterns = [
1212
re_path(r'^data/role$', GetRoleAPI.as_view()),
13+
re_path(r'^article/popular$', PopularArticlesView.as_view()),
14+
re_path(r'^article/follow_article$', FollowArticlesView.as_view()),
15+
re_path(r'^article/category_article$', CategoryArticlesView.as_view()),
1316
]

backend/app/db_schema/views.py

+35
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,38 @@ def post(self, request, *args, **kwargs):
6464
except Exception as e:
6565
print(str(e))
6666
return Response({"msg": str(e)}, status=400)
67+
68+
class PopularArticlesView(APIView):
69+
permission_classes = [AllowAny]
70+
71+
def post(self, request, *args, **kwargs):
72+
try:
73+
category = request.data.get('category')
74+
print(category)
75+
top_articles = Article.objects.filter(public=1,categories__contains=category).order_by('-visited')[:4]
76+
return Response(ArticleSerializer(top_articles, many=True).data, 200)
77+
except Exception as e:
78+
print(str(e))
79+
return Response({"msg": "Can't find Article Info"}, status=404)
80+
class FollowArticlesView(APIView):
81+
permission_classes = [AllowAny]
82+
83+
def post(self, request, *args, **kwargs):
84+
try:
85+
category = request.data.get('category')
86+
print(category)
87+
top_articles = Article.objects.filter(public=1,categories__contains=category).order_by('-visited')[:4]
88+
return Response(ArticleSerializer(top_articles, many=True).data, 200)
89+
except Exception as e:
90+
print(str(e))
91+
return Response({"msg": "Can't find Article Info"}, status=404)
92+
class CategoryArticlesView(APIView):
93+
permission_classes = [AllowAny]
94+
95+
def get(self, request, *args, **kwargs):
96+
try:
97+
top_articles = Article.objects.filter(public=1,categories__contains='ゲーム').order_by('-visited')[:4]
98+
return Response(ArticleSerializer(top_articles, many=True).data, 200)
99+
except Exception as e:
100+
print(str(e))
101+
return Response({"msg": "Can't find Article Info"}, status=404)

frontend/app/src/app/nologin/popular/page.tsx frontend/app/src/app/common/popular/page.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import dynamic from 'next/dynamic';
44
import Loading from '@/components/templates/Loading';
55

6-
const PopularPage = dynamic(() => import('@/components/pages/nologin/Popular'), {
6+
const PopularPage = dynamic(() => import('@/components/pages/common/Popular'), {
77
loading: () => <Loading />
88
});
99

frontend/app/src/app/nologin/top/page.tsx frontend/app/src/app/common/top/page.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import dynamic from 'next/dynamic';
44
import Loading from '@/components/templates/Loading';
55

6-
const TopPage = dynamic(() => import('@/components/pages/nologin/TopPage'), {
6+
const TopPage = dynamic(() => import('@/components/pages/common/TopPage'), {
77
loading: () => <Loading />
88
});
99

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
'use client';
2+
3+
import dynamic from 'next/dynamic';
4+
import Loading from '@/components/templates/Loading';
5+
6+
const PurchaseSuccessPage = dynamic(() => import('@/components/pages/members/articles/PurchaseSuccess'), {
7+
loading: () => <Loading />
8+
});
9+
10+
const Page = () => {
11+
return <PurchaseSuccessPage />;
12+
};
13+
14+
export default Page;

frontend/app/src/components/pages/nologin/TopPage.tsx frontend/app/src/components/pages/common/TopPage.tsx

+96-48
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,25 @@
11
import MainLayout from "@/components/templates/layout/MainLayout";
2+
import { useAuth } from "@/contexts/AuthContext";
3+
import { IUser } from "@/interfaces";
4+
import { setArticleData } from "@/store/features/shared_data";
5+
import { useAppDispatch } from "@/store/hooks";
6+
import { getRequest, postRequest } from "@/utils/axios";
27
import { useRouter } from "next/navigation";
8+
import { useEffect, useState } from "react";
39

10+
interface Article {
11+
cur_step: number;
12+
id: number;
13+
image: string;
14+
title: string;
15+
content: string;
16+
category: string;
17+
price: number;
18+
nonfree: number;
19+
created_by: IUser;
20+
created_at: string;
21+
has_bought: boolean;
22+
}
423

524
const TopPage = () => {
625
const router = useRouter();
@@ -18,6 +37,13 @@ const TopPage = () => {
1837
"中部・近畿",
1938
"中国・四国・九州"
2039
];
40+
const [popular_articles, setPopularArticles] = useState<Article[] | null>(null)
41+
const [follower_articles, setFollowerArticles] = useState<Article[] | null>(null)
42+
const [categoryA_articles, setCategoryArticles] = useState<Article[] | null>(null)
43+
const [category, setCategory] = useState('')
44+
const { user , isAuthenticated } = useAuth()
45+
const dispatch = useAppDispatch();
46+
2147
const articles = [
2248
{
2349
title: "記事タイトル記事タイトル記事タイトル",
@@ -43,9 +69,25 @@ const TopPage = () => {
4369
price: "¥1,980",
4470
image: "/images/image3.jpeg", // Replace with actual image URLs
4571
},
46-
];
72+
];
73+
const goToArticle = (id:number) => {
74+
router.push(`/members/articles/${id}`)
75+
}
76+
useEffect(()=>{
77+
(async()=>{
78+
const formData = new FormData();
79+
formData.append('category',category)
80+
const res = await postRequest('/article/popular',formData)
81+
setPopularArticles(res.data)
82+
const res1 = await postRequest('/article/follow_article', formData)
83+
setFollowerArticles(res1.data)
84+
console.log("****voldin",res1.data)
85+
const res2 = await getRequest('/article/category_article')
86+
setCategoryArticles(res2.data)
87+
})()
88+
},[])
4789
const popular_clicked = () => {
48-
router.push('/nologin/popular')
90+
router.push('/common/popular')
4991
}
5092
return (
5193
<MainLayout>
@@ -59,6 +101,7 @@ const TopPage = () => {
59101
<button
60102
key={index}
61103
className="px-6 py-3 border border-gray-300 rounded-full text-sm text-gray-700 hover:bg-gray-100"
104+
onClick={()=>setCategory(category)}
62105
>
63106
{category}
64107
</button>
@@ -76,97 +119,102 @@ const TopPage = () => {
76119

77120
{/* Article Grid */}
78121
<div className="grid grid-cols-4 gap-6">
79-
{articles.map((article, index) => (
122+
{popular_articles && popular_articles.map((article, index) => (
80123
<div
81124
key={index}
82-
className="p-4"
125+
className="p-4 cursor-pointer"
126+
onClick={()=>goToArticle(article.id)}
83127
>
84128
{/* Article Image */}
85129
<img
86-
src={article.image}
87-
alt={article.title}
130+
src={process.env.NEXT_PUBLIC_BACKEND_URL + article.image}
88131
className="w-full h-[150px] object-cover rounded-md mb-4"
89132
/>
90133

91134
{/* Article Details */}
92-
<h3 className="text-sm font-bold text-gray-800 mb-2">
135+
<h3 className="text-sm font-bold text-gray-800 mb-2 overflow-hidden whitespace-nowrap text-ellipsis">
93136
{article.title}
94137
</h3>
95138
<div className="flex items-center mb-2">
96139
<div className="w-6 h-6 bg-gray-300 rounded-full mr-2"></div>
97-
<span className="text-sm text-gray-500">{article.creator}</span>
140+
<span className="text-sm text-gray-500">{article.created_by.user_info.name}</span>
98141
</div>
99-
<p className="text-sm font-bold text-gray-800 float-right">{article.price}</p>
142+
<p className="text-sm font-bold text-gray-800 float-right">¥ {article.price}</p>
100143
</div>
101144
))}
102145
</div>
103146
</section>
104-
<section className="max-w-[1440px] mx-auto px-[94px] py-8">
105-
{/* Header */}
106-
<div className="flex justify-between items-center mb-6">
107-
<h2 className="text-xl font-bold">フォロー中のクリエイターの記事</h2>
108-
<a href="#" className="text-sm text-gray-500 hover:underline">
109-
もっと見る
110-
</a>
111-
</div>
147+
{
148+
isAuthenticated && <>
149+
<section className="max-w-[1440px] mx-auto px-[94px] py-8">
150+
{/* Header */}
151+
<div className="flex justify-between items-center mb-6">
152+
<h2 className="text-xl font-bold">フォロー中のクリエイターの記事</h2>
153+
<a href="#" className="text-sm text-gray-500 hover:underline">
154+
もっと見る
155+
</a>
156+
</div>
112157

113-
{/* Article Grid */}
114-
<div className="grid grid-cols-4 gap-6">
115-
{articles.map((article, index) => (
116-
<div
117-
key={index}
118-
className="p-4"
119-
>
120-
{/* Article Image */}
121-
<img
122-
src={article.image}
123-
alt={article.title}
124-
className="w-full h-[150px] object-cover rounded-md mb-4"
125-
/>
158+
{/* Article Grid */}
159+
<div className="grid grid-cols-4 gap-6">
160+
{follower_articles && follower_articles.map((article, index) => (
161+
<div
162+
key={index}
163+
className="p-4 cursor-pointer"
164+
onClick={()=>goToArticle(article.id)}
165+
>
166+
{/* Article Image */}
167+
<img
168+
src={process.env.NEXT_PUBLIC_BACKEND_URL + article.image}
169+
alt={article.title}
170+
className="w-full h-[150px] object-cover rounded-md mb-4"
171+
/>
126172

127-
{/* Article Details */}
128-
<h3 className="text-sm font-bold text-gray-800 mb-2">
129-
{article.title}
130-
</h3>
131-
<div className="flex items-center mb-2">
132-
<div className="w-6 h-6 bg-gray-300 rounded-full mr-2"></div>
133-
<span className="text-sm text-gray-500">{article.creator}</span>
173+
{/* Article Details */}
174+
<h3 className="text-sm font-bold text-gray-800 mb-2 overflow-hidden whitespace-nowrap text-ellipsis">
175+
{article.title}
176+
</h3>
177+
<div className="flex items-center mb-2">
178+
<div className="w-6 h-6 bg-gray-300 rounded-full mr-2"></div>
179+
<span className="text-sm text-gray-500">{article.created_by.user_info.name}</span>
180+
</div>
181+
<p className="text-sm font-bold text-gray-800 float-right">{article.price}</p>
134182
</div>
135-
<p className="text-sm font-bold text-gray-800 float-right">{article.price}</p>
183+
))}
136184
</div>
137-
))}
138-
</div>
139-
</section>
185+
</section>
186+
</>
187+
}
188+
140189
<section className="max-w-[1440px] mx-auto px-[94px] py-8">
141190
{/* Header */}
142191
<div className="flex justify-between items-center mb-6">
143-
<h2 className="text-xl font-bold">カテゴリーAの記事</h2>
192+
<h2 className="text-xl font-bold">ゲームの記事</h2>
144193
<a href="#" className="text-sm text-gray-500 hover:underline">
145194
もっと見る
146195
</a>
147196
</div>
148197

149198
{/* Article Grid */}
150199
<div className="grid grid-cols-4 gap-6">
151-
{articles.map((article, index) => (
200+
{categoryA_articles && categoryA_articles.map((article, index) => (
152201
<div
153202
key={index}
154203
className="p-4"
155204
>
156205
{/* Article Image */}
157206
<img
158-
src={article.image}
159-
alt={article.title}
160-
className="w-full h-[150px] object-cover rounded-md mb-4"
207+
src={process.env.NEXT_PUBLIC_BACKEND_URL + article.image}
208+
className="w-full h-[150px] object-cover rounded-md mb-4"
161209
/>
162210

163211
{/* Article Details */}
164-
<h3 className="text-sm font-bold text-gray-800 mb-2">
212+
<h3 className="text-sm font-bold text-gray-800 mb-2 overflow-hidden whitespace-nowrap text-ellipsis">
165213
{article.title}
166214
</h3>
167215
<div className="flex items-center mb-2">
168216
<div className="w-6 h-6 bg-gray-300 rounded-full mr-2"></div>
169-
<span className="text-sm text-gray-500">{article.creator}</span>
217+
<span className="text-sm text-gray-500">{article.created_by.user_info.name}</span>
170218
</div>
171219
<p className="text-sm font-bold text-gray-800 float-right">{article.price}</p>
172220
</div>

frontend/app/src/components/pages/members/articles/Article.tsx

+10-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { useAppDispatch, useAppSelector } from '@/store/hooks';
1010
import { getRequest } from '@/utils/axios';
1111
import { useTheme } from '@emotion/react';
1212
import { Chip } from '@mui/material';
13-
import { useParams } from 'next/navigation';
13+
import { useParams, useRouter } from 'next/navigation';
1414
import { useEffect, useState } from 'react';
1515
import { FaRegUser } from 'react-icons/fa';
1616

@@ -34,14 +34,18 @@ const ArticlePage = () => {
3434
const {user, isAuthenticated} = useAuth();
3535
const theme = useTheme()
3636
const [article, setArticle] = useState<Article | null>(null)
37-
console.log("****voldin isAuthenticated", isAuthenticated, user)
37+
const router = useRouter()
3838
useEffect(()=>{
3939
(async()=>{
4040
const res =await getRequest(`/v0/articles/${id}`)
4141
setArticle(res.data)
4242
console.log(res.data)
4343
})()
4444
},[])
45+
46+
const gotoPurChase = () => {
47+
router.push('/members/articles/purchase_success')
48+
}
4549
return (
4650
<AuthLayout>
4751
<AdminLayout>
@@ -90,7 +94,9 @@ const ArticlePage = () => {
9094
</div>
9195
<div>¥ {article.price}</div>
9296
</div>
93-
<div className='flex items-center justify-end pb-[26px]'>
97+
<div className='flex items-center justify-end pb-[26px]'
98+
onClick={()=>gotoPurChase()}
99+
>
94100
<div className='cursor-pointer text-[20px] text-white bg-[#00A4E5] rounded-[124px] flex items-center justify-center gap-[20px] w-[340px] h-[64px] '>
95101
<svg width="29" height="31" viewBox="0 0 29 31" fill="none" xmlns="http://www.w3.org/2000/svg">
96102
<path d="M28.6595 7.6733L7.83792 5.90321L7.52123 3.97412C7.23038 2.21366 5.92454 0.849232 4.27502 0.587003L0.576688 0L0.294922 2.04146L3.99371 2.62998C4.82191 2.76106 5.48025 3.44761 5.62567 4.33341L8.61375 22.504C8.89417 24.2095 10.2746 25.452 11.8893 25.4525H24.8533L25.2387 23.3877H11.8894C11.2094 23.3888 10.6268 22.8633 10.5094 22.1452L10.0906 19.6027H26.0937L28.6595 7.6733Z" fill="white"/>
@@ -116,7 +122,7 @@ const ArticlePage = () => {
116122

117123
<p className="text-2xl font-bold text-gray-800">¥ {article.price}</p>
118124
</div>
119-
<div className='cursor-pointer text-[20px] text-white bg-[#00A4E5] rounded-[124px] flex items-center justify-center gap-[20px] w-[340px] py-2 mx-auto h-[64px]'>
125+
<div className='cursor-pointer text-[20px] text-white bg-[#00A4E5] rounded-[124px] flex items-center justify-center gap-[20px] w-[340px] py-2 mx-auto h-[64px]' onClick={()=>gotoPurChase()}>
120126
<svg width="29" height="31" viewBox="0 0 29 31" fill="none" xmlns="http://www.w3.org/2000/svg">
121127
<path d="M28.6595 7.6733L7.83792 5.90321L7.52123 3.97412C7.23038 2.21366 5.92454 0.849232 4.27502 0.587003L0.576688 0L0.294922 2.04146L3.99371 2.62998C4.82191 2.76106 5.48025 3.44761 5.62567 4.33341L8.61375 22.504C8.89417 24.2095 10.2746 25.452 11.8893 25.4525H24.8533L25.2387 23.3877H11.8894C11.2094 23.3888 10.6268 22.8633 10.5094 22.1452L10.0906 19.6027H26.0937L28.6595 7.6733Z" fill="white"/>
122128
<path d="M12.6229 26.5594C11.48 26.5594 10.5537 27.5539 10.5537 28.7801C10.5537 30.0064 11.48 31 12.6229 31C13.7661 31 14.6926 30.0064 14.6926 28.7801C14.6926 27.5539 13.7661 26.5594 12.6229 26.5594Z" fill="white"/>

frontend/app/src/components/pages/members/articles/CreateArticle2.tsx

-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ const CreateArticle2Page = () => {
1919
PaperProps: {
2020
style: {
2121
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
22-
width: '100%',
2322
},
2423
},
2524
};

0 commit comments

Comments
 (0)