Compare commits
No commits in common. "b11cd41ceb3e0c90db76874a9406d38d3ff778df" and "ed47d6abf592eb8edb3eaab33cd349041565c087" have entirely different histories.
b11cd41ceb
...
ed47d6abf5
73
src/components/inquiry/InquiryDetail.tsx
Normal file
73
src/components/inquiry/InquiryDetail.tsx
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useParams } from 'next/navigation'
|
||||||
|
|
||||||
|
const inquiryDummyData = {
|
||||||
|
writer: {
|
||||||
|
name: 'writer',
|
||||||
|
email: 'writer@example.com',
|
||||||
|
},
|
||||||
|
title: 'title',
|
||||||
|
content: 'content',
|
||||||
|
files: ['file1.jpg', 'file2.jpg', 'file3.jpg'],
|
||||||
|
createdAt: '2021-01-01',
|
||||||
|
answer: {
|
||||||
|
writer: '佐藤一貴',
|
||||||
|
content:
|
||||||
|
'一次側接続は、自動切替開閉器と住宅分電盤主幹ブレーカの間に蓄電システムブレーカを配線する方法です。\n二次側接続は、住宅分電盤主幹ブレ―カの二次側に蓄電システムブレーカを接続する',
|
||||||
|
createdAt: '2021-01-01 12:00:00',
|
||||||
|
files: ['file4.jpg', 'file5.jpg', 'file6.jpg'],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function InquiryDetail() {
|
||||||
|
const params = useParams()
|
||||||
|
const id = params.id
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>InquiryDetail</h1>
|
||||||
|
<p>{id}</p>
|
||||||
|
<div className="mt-5">
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<p>writer</p>
|
||||||
|
<p>{inquiryDummyData.writer.name}</p>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<p>email</p>
|
||||||
|
<p>{inquiryDummyData.writer.email}</p>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<p>title</p>
|
||||||
|
<p>{inquiryDummyData.title}</p>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<p>content</p>
|
||||||
|
<p>{inquiryDummyData.content}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p>files</p>
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
{inquiryDummyData.files.map((file) => (
|
||||||
|
<span key={file}>{file}</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{inquiryDummyData.answer && (
|
||||||
|
<div className="mt-4">
|
||||||
|
<h1>Reply: Hanwha Japan</h1>
|
||||||
|
<div>
|
||||||
|
<p>{inquiryDummyData.answer.writer}</p>
|
||||||
|
<p>{inquiryDummyData.answer.createdAt}</p>
|
||||||
|
<p>{inquiryDummyData.answer.content}</p>
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
{inquiryDummyData.answer.files.map((file) => (
|
||||||
|
<span key={file}>{file}</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
20
src/components/inquiry/InquiryFilter.tsx
Normal file
20
src/components/inquiry/InquiryFilter.tsx
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { Search } from 'lucide-react'
|
||||||
|
import { useRouter } from 'next/navigation'
|
||||||
|
|
||||||
|
|
||||||
|
export default function InquiryFilter({ handleSearch }: { handleSearch: (e: React.ChangeEvent<HTMLInputElement>) => void }) {
|
||||||
|
const router = useRouter()
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<button onClick={() => router.push('/inquiry/write')}>write 1:1 Inquiry {'>'}</button>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<input type="text" placeholder="Search" onChange={handleSearch} />
|
||||||
|
<button>
|
||||||
|
<Search />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
21
src/components/inquiry/InquiryItems.tsx
Normal file
21
src/components/inquiry/InquiryItems.tsx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useRouter } from 'next/navigation'
|
||||||
|
|
||||||
|
export default function InquiryItems({ inquiryData }: { inquiryData: any }) {
|
||||||
|
const router = useRouter()
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{inquiryData.map((item: any) => (
|
||||||
|
<div key={item.id} onClick={() => router.push(`/inquiry/${item.id}`)}>
|
||||||
|
<div>{item.title}</div>
|
||||||
|
<div>{item.content}</div>
|
||||||
|
<div>{item.createdAt}</div>
|
||||||
|
<div>{item.writer}</div>
|
||||||
|
<div>{item.category}</div>
|
||||||
|
{item.file && <div>{item.file}</div>}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
171
src/components/inquiry/InquiryList.tsx
Normal file
171
src/components/inquiry/InquiryList.tsx
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
'use client'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import InquiryItems from './InquiryItems'
|
||||||
|
import InquiryFilter from './InquiryFilter'
|
||||||
|
import LoadMoreButton from '../LoadMoreButton'
|
||||||
|
|
||||||
|
const inquiryDummyData = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: 'post',
|
||||||
|
content: 'content',
|
||||||
|
file: 'file.png',
|
||||||
|
createdAt: '2024-01-01',
|
||||||
|
writer: 'writer',
|
||||||
|
category: 'A',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: 'post',
|
||||||
|
content: 'content',
|
||||||
|
file: 'file.png',
|
||||||
|
createdAt: '2024-01-01',
|
||||||
|
writer: 'writer1',
|
||||||
|
category: 'B',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
title: 'post',
|
||||||
|
content: 'content',
|
||||||
|
file: null,
|
||||||
|
createdAt: '2024-01-01',
|
||||||
|
writer: 'writer1',
|
||||||
|
category: 'C',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
title: 'post',
|
||||||
|
content: 'content',
|
||||||
|
file: null,
|
||||||
|
createdAt: '2024-01-01',
|
||||||
|
writer: 'writer1',
|
||||||
|
category: 'A',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
title: 'post',
|
||||||
|
content: 'content',
|
||||||
|
file: null,
|
||||||
|
createdAt: '2024-01-01',
|
||||||
|
writer: 'writer1',
|
||||||
|
category: 'B',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
title: 'post',
|
||||||
|
content: 'content',
|
||||||
|
file: null,
|
||||||
|
createdAt: '2024-01-01',
|
||||||
|
writer: 'writer1',
|
||||||
|
category: 'C',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
title: 'post',
|
||||||
|
content: 'content',
|
||||||
|
file: 'file.png',
|
||||||
|
createdAt: '2024-01-01',
|
||||||
|
writer: 'writer',
|
||||||
|
category: 'A',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
title: 'post',
|
||||||
|
content: 'content',
|
||||||
|
file: 'file.png',
|
||||||
|
createdAt: '2024-01-01',
|
||||||
|
writer: 'writer1',
|
||||||
|
category: 'B',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 9,
|
||||||
|
title: 'post',
|
||||||
|
content: 'content',
|
||||||
|
file: null,
|
||||||
|
createdAt: '2024-01-01',
|
||||||
|
writer: 'writer1',
|
||||||
|
category: 'C',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
id: 10,
|
||||||
|
title: 'post',
|
||||||
|
content: 'content',
|
||||||
|
file: 'file.png',
|
||||||
|
createdAt: '2024-01-01',
|
||||||
|
writer: 'writer1',
|
||||||
|
category: 'A',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 11,
|
||||||
|
title: 'post',
|
||||||
|
content: 'content',
|
||||||
|
file: 'file.png',
|
||||||
|
createdAt: '2024-01-01',
|
||||||
|
writer: 'writer',
|
||||||
|
category: 'B',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 12,
|
||||||
|
title: 'post',
|
||||||
|
content: 'content',
|
||||||
|
file: null,
|
||||||
|
createdAt: '2024-01-01',
|
||||||
|
writer: 'writer1',
|
||||||
|
category: 'C',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export default function InquiryList() {
|
||||||
|
const [visibleItems, setVisibleItems] = useState(5)
|
||||||
|
const [isMyPostsOnly, setIsMyPostsOnly] = useState(false)
|
||||||
|
const [category, setCategory] = useState('')
|
||||||
|
const [search, setSearch] = useState('')
|
||||||
|
const [hasMore, setHasMore] = useState(inquiryDummyData.length > 5)
|
||||||
|
|
||||||
|
const inquriyData = () => {
|
||||||
|
if (isMyPostsOnly) {
|
||||||
|
return inquiryDummyData.filter((item) => item.writer === 'writer')
|
||||||
|
}
|
||||||
|
if (category.trim().length > 0) {
|
||||||
|
return inquiryDummyData.filter((item) => item.category === category)
|
||||||
|
}
|
||||||
|
if (search.trim().length > 0) {
|
||||||
|
return inquiryDummyData.filter((item) => item.title.includes(search))
|
||||||
|
}
|
||||||
|
return inquiryDummyData
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleLoadMore = () => {
|
||||||
|
const newVisibleItems = Math.min(visibleItems + 5, inquriyData().length)
|
||||||
|
setVisibleItems(newVisibleItems)
|
||||||
|
setHasMore(newVisibleItems < inquriyData().length)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setSearch(e.target.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleScrollToTop = () => {
|
||||||
|
window.scrollTo({ top: 0, behavior: 'smooth' })
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<InquiryFilter handleSearch={handleSearch} />
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<input type="checkbox" id="myPosts" checked={isMyPostsOnly} onChange={(e) => setIsMyPostsOnly(e.target.checked)} />
|
||||||
|
<label htmlFor="myPosts">my posts</label>
|
||||||
|
</div>
|
||||||
|
<select onChange={(e) => setCategory(e.target.value)}>
|
||||||
|
<option value="">All</option>
|
||||||
|
<option value="A">A</option>
|
||||||
|
<option value="B">B</option>
|
||||||
|
<option value="C">C</option>
|
||||||
|
</select>
|
||||||
|
<span>total {inquriyData().length}</span>
|
||||||
|
<InquiryItems inquiryData={inquriyData().slice(0, visibleItems)} />
|
||||||
|
<LoadMoreButton hasMore={hasMore} onLoadMore={handleLoadMore} onScrollToTop={handleScrollToTop} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
67
src/components/inquiry/InquiryWriteForm.tsx
Normal file
67
src/components/inquiry/InquiryWriteForm.tsx
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { useRouter } from 'next/navigation'
|
||||||
|
|
||||||
|
export interface InquiryFormData {
|
||||||
|
category: string
|
||||||
|
title: string
|
||||||
|
content: string
|
||||||
|
file: File[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function InquiryWriteForm() {
|
||||||
|
const router = useRouter()
|
||||||
|
const [formData, setFormData] = useState<InquiryFormData>({
|
||||||
|
category: 'A',
|
||||||
|
title: '',
|
||||||
|
content: '',
|
||||||
|
file: [],
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const file = Array.from(e.target.files || [])
|
||||||
|
setFormData({ ...formData, file: [...formData.file, ...file] })
|
||||||
|
}
|
||||||
|
const handleSubmit = () => {
|
||||||
|
console.log('submit: ', formData)
|
||||||
|
// router.push(`/inquiry`)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="category">category</label>
|
||||||
|
<select id="category" onChange={(e) => setFormData({ ...formData, category: e.target.value })}>
|
||||||
|
<option value="A">A</option>
|
||||||
|
<option value="B">B</option>
|
||||||
|
<option value="C">C</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="title">title</label>
|
||||||
|
<input type="text" id="title" onChange={(e) => setFormData({ ...formData, title: e.target.value })} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="content">content</label>
|
||||||
|
<textarea id="content" onChange={(e) => setFormData({ ...formData, content: e.target.value })} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="file">file</label>
|
||||||
|
<input type="file" id="file" accept="image/*" capture="environment" onChange={handleFileChange} />
|
||||||
|
<div>
|
||||||
|
<p>file count: {formData.file.length}</p>
|
||||||
|
{formData.file.map((f) => (
|
||||||
|
<div key={f.name}>
|
||||||
|
<div>{f.name}</div>
|
||||||
|
<div>
|
||||||
|
<button>delete</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button onClick={handleSubmit}>submit</button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { SEARCH_OPTIONS_ENUM, SEARCH_OPTIONS_PARTNERS_ENUM, SORT_OPTIONS_ENUM } from '@/store/surveyFilterStore'
|
||||||
|
|
||||||
export type SurveyBasicInfo = {
|
export type SurveyBasicInfo = {
|
||||||
ID: number
|
ID: number
|
||||||
REPRESENTATIVE: string
|
REPRESENTATIVE: string
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user