Skip to content

Commit

Permalink
[#24] 지표 결과 도출 및 각 상황별 에러 처리
Browse files Browse the repository at this point in the history
  • Loading branch information
hanseulhee committed Apr 7, 2024
1 parent a96e48d commit 9c73b22
Show file tree
Hide file tree
Showing 9 changed files with 172 additions and 75 deletions.
26 changes: 24 additions & 2 deletions app/(route)/indicators/_components/result/index.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,39 @@
import Nav from '@/app/_common/nav'
import Title from '@/app/_common/text/title'
import { investmentItemAtom, totalinputValueAtom } from '@/app/_store/atom'
import { useRecoilValue } from 'recoil'
import S from './result.module.css'

//* 결과페이지 입니다.
//TODO: 사용자가 클릭한 아이디어 이름과 해당 툴을 사용한 사용자 수가 보여집니다.
function Result() {
const selectedItem = useRecoilValue(investmentItemAtom)
const totalinputValue: number = parseInt(useRecoilValue(totalinputValueAtom))
console.log(totalinputValue)
return (
<div className={S.wrapper}>
<Nav />
<div>
<Title title="검증 결과" />

<div>
<span className={S.title}>아이디어 이름</span>
<p className={S.subTitle}>전체 사용자 162명</p>
</div>

<div>
<Title title="아이디어 이름" />
<span>전체 사용자 162명</span>
<span className={S.title}>검증 지표</span>
<p className={S.subTitle}>계산 결과지입니다.</p>

<p>전체 이용자 수 : {totalinputValue}</p>

{selectedItem.map((item) => (
<span key={item.id}>
<p>선택한 아이템 이름: {item.name}</p>
<p>선택한 아이템 점수: {item.score}</p>
<p>최종 점수: {item.score && item.score * totalinputValue}</p>
</span>
))}
</div>
</div>
</div>
Expand Down
10 changes: 10 additions & 0 deletions app/(route)/indicators/_components/result/result.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,13 @@
padding-bottom: 50px;
padding: 0 18px;
}

.title {
font-size: 1.2rem;
font-weight: 700;
}

.subTitle {
font-size: 0.9rem;
font-weight: 400;
}
6 changes: 5 additions & 1 deletion app/(route)/indicators/indicators.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@
overflow: auto;
height: 690px;
width: 100%;
gap: 14px;
gap: 6px;
}

.marginWrapper {
margin-bottom: 50px;
}

.bottomWrapper {
Expand Down
62 changes: 39 additions & 23 deletions app/(route)/indicators/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
'use client'

import Title from '@/app/_common/text/title'
import { totalinputValueAtom } from '@/app/_store/atom'
import { useRouter } from 'next/navigation'
import { useState } from 'react'
import { useRecoilState } from 'recoil'
import Nav from '../list/_components/nav'
import ActiveInvestmentList from '../verification/ibulsin/_components/ActiveInvestmentList'
import FormTitle from './_components/form/FormTitle'
Expand All @@ -11,22 +13,29 @@ import S from './indicators.module.css'

//* 투자 지표 입력 페이지입니다.
//TODO: title에 사용자가 입력했던 요소들이 보여지게 됩니다.
//TODO: recoil 사용
function Indicators() {
const router = useRouter()
const [inputValue, setInputValue] = useState('')
const [inputValue, setInputValue] = useRecoilState(totalinputValueAtom)
const [error, setError] = useState('')
const [checkError, setCheckError] = useState('')
const [selectedIndex, setSelectedIndex] = useState<number | null>(null)

const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setInputValue(e.target.value)
setError('')
}

const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
if (!/^\d+$/.test(inputValue)) {
const handleSubmit = () => {
if (!/^\d+$/.test(inputValue) && selectedIndex === null) {
setError('숫자만 입력 가능합니다.')
setCheckError('지표 항목을 한가지 선택해야 합니다.')
} else if (!/^\d+$/.test(inputValue)) {
setError('숫자만 입력 가능합니다.')
} else if (selectedIndex === null) {
setCheckError('지표 항목을 한가지 선택해야 합니다.')
} else {
setError('')
setCheckError('')
router.push('/result')
}
}
Expand All @@ -41,32 +50,39 @@ function Indicators() {

<div className={S.formWrapper}>
<div className={S.overflowWrapper}>
<FormTitle
title="전체 이용자 수"
subTitle="전체 이용자 수를 가지고 총 결과 지표가 계산됩니다."
/>
<div className={S.marginWrapper}>
<FormTitle
title="전체 이용자 수"
subTitle="전체 이용자 수를 가지고 총 결과 지표가 계산됩니다."
/>

<div className={FormS.inputWrapper}>
<input
className={FormS.input}
placeholder="수치를 입력해 주세요."
value={inputValue}
onChange={handleChange}
<div className={FormS.inputWrapper}>
<input
className={FormS.input}
placeholder="수치를 입력해 주세요."
value={inputValue}
onChange={handleChange}
/>
</div>
{error && <span className={FormS.error}>{error}</span>}
</div>
<div className={S.marginWrapper}>
<FormTitle
title="지표 항목"
subTitle="점수 환산의 기준이 되는 한가지의 항목을 골라주세요."
/>
<ActiveInvestmentList
selectedIndex={selectedIndex}
onSelect={(index: number) => setSelectedIndex(index)}
/>
{checkError && <span className={FormS.error}>{checkError}</span>}
</div>

{error && (
<span className={FormS.error}>숫자만 입력 가능합니다.</span>
)}

<ActiveInvestmentList />
</div>

<div className={S.bottomWrapper}>
<button
type="submit"
className={S.submitBtnWrapper}
onClick={() => handleSubmit}
onClick={handleSubmit}
>
제출하기
</button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.item_container {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
margin-bottom: 3px;
height: 50px;
}
.item_input_wrapper {
Expand Down Expand Up @@ -57,3 +57,8 @@
-webkit-appearance: none;
margin: 0;
}

.checkbox {
accent-color: var(--purple-700);
margin-bottom: 20px;
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,40 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
'use client'

import investmentItemAtom, { ActiveInvestmentItemType } from '@/app/_store/atom'
import { ActiveInvestmentItemType, investmentItemAtom } from '@/app/_store/atom'
import cn from 'classnames'
import { useState } from 'react'
import { ChangeEvent, useState } from 'react'
import { useRecoilState } from 'recoil'
import ItemAddBtn from '../ItemAddBtn'
import S from './index.module.css'

interface ActiveInvestmentItemProps {
item: ActiveInvestmentItemType
index: number
selectedIndex: number | null
onSelect: (index: number) => void
}

function ActiveInvestmentItem({ item }: ActiveInvestmentItemProps) {
function ActiveInvestmentItem({
item,
index,
selectedIndex,
onSelect,
}: ActiveInvestmentItemProps) {
const [investmentItem, setInvestmentItem] = useRecoilState(investmentItemAtom)
const [itemName, setItemName] = useState(item?.name ?? '')
const [itemScore, setItemScore] = useState(item?.score ?? 0)
const [itemScore, setItemScore] = useState<number | undefined>(
item?.score ?? undefined,
)

const isChecked = selectedIndex === index

const handleCheckboxChange = () => {
onSelect(index)
const selectedInvestmentItem = investmentItem[index]
setItemName(selectedInvestmentItem.name)
setItemScore(selectedInvestmentItem?.score ?? undefined)
}

const handleDeleteItem = () => {
if (investmentItem.length <= 1) {
Expand All @@ -26,7 +45,6 @@ function ActiveInvestmentItem({ item }: ActiveInvestmentItemProps) {
const next = prev.filter(
(investmentItem) => investmentItem.id !== item.id,
)
console.log(next)

return next
})
Expand All @@ -44,50 +62,57 @@ function ActiveInvestmentItem({ item }: ActiveInvestmentItemProps) {
),
)
}
const handleChangeScoreInput = (e: any) => {
const { value } = e.target
setItemScore(value)

const handleChangeScoreInput = (e: ChangeEvent<HTMLInputElement>) => {
const value = parseInt(e.target.value)
setItemScore(isNaN(value) ? undefined : value)
setInvestmentItem((prev) =>
prev.map((investmentItem) =>
investmentItem.id === item.id
? { ...item, name: value }
? { ...item, score: value }
: investmentItem,
),
)
}

return (
<div className={S.item_container}>
<div className={S.item_input_wrapper}>
<input
className={cn(S.item_name_input, S.input)}
placeholder="아이템 이름을 입력해 주세요."
value={itemName}
onChange={(e) => handleChangeNameInput(e)}
/>
<div className={S.score_container}>
<>
<div className={S.item_container}>
<div className={S.item_input_wrapper}>
<input
className={cn(S.item_score_input, S.input)}
type="number"
placeholder="2"
value={itemScore}
onChange={(e) => handleChangeScoreInput(e)}
className={cn(S.item_name_input, S.input)}
placeholder="아이템 이름을 입력해 주세요."
value={itemName}
onChange={(e) => handleChangeNameInput(e)}
/>
<span></span>
<div className={S.score_container}>
<input
className={cn(S.item_score_input, S.input)}
type="number"
value={itemScore ?? ''}
onChange={(e) => handleChangeScoreInput(e)}
/>
<span></span>
</div>
</div>
<div className={S.columnWrapper}>
<button
type="button"
className={S.delete_btn}
onClick={handleDeleteItem}
>
삭제
</button>
<ItemAddBtn />
</div>
</div>
<div className={S.columnWrapper}>
<button
type="button"
className={S.delete_btn}
onClick={handleDeleteItem}
>
삭제
</button>
<ItemAddBtn />
</div>
</div>
<input
type="checkbox"
className={S.checkbox}
checked={isChecked}
onChange={handleCheckboxChange}
/>
</>
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,30 @@
'use client'

import investmentItemAtom from '@/app/_store/atom'
import { investmentItemAtom } from '@/app/_store/atom'
import { useRecoilValue } from 'recoil'
import ActiveInvestmentItem from '../ActiveInvestmentItem'
import S from './index.module.css'

function ActiveInvestmentList() {
interface Props {
selectedIndex: number | null
onSelect: (index: number) => void
}

function ActiveInvestmentList({ selectedIndex, onSelect }: Props) {
const investmentItem = useRecoilValue(investmentItemAtom)

return (
<div className={S.main}>
{investmentItem.map((item) => {
return <ActiveInvestmentItem key={item.id} item={item} />
{investmentItem.map((item, index) => {
return (
<ActiveInvestmentItem
key={item.id}
item={item}
index={index}
selectedIndex={selectedIndex}
onSelect={onSelect}
/>
)
})}
</div>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
'use client'

import React from 'react'
import S from './index.module.css'
import { ActiveInvestmentItemType, investmentItemAtom } from '@/app/_store/atom'
import { useSetRecoilState } from 'recoil'
import investmentItemAtom, { ActiveInvestmentItemType } from '@/app/_store/atom'
import S from './index.module.css'

function ItemAddBtn() {
const setInvestmentItem = useSetRecoilState(investmentItemAtom)
Expand All @@ -12,7 +11,7 @@ function ItemAddBtn() {
const newItem: ActiveInvestmentItemType = {
id: new Date().toISOString(),
name: '',
score: 0,
score: null,
}
setInvestmentItem((prev) => [...prev, newItem])
}
Expand Down
Loading

0 comments on commit 9c73b22

Please sign in to comment.