Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

πŸ”€ 폼 apiλ“€ μ—°κ²° #46

Merged
merged 2 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions src/app/api/application/[trainingPro_id]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { AxiosError } from 'axios';
import { cookies } from 'next/headers';
import { NextResponse } from 'next/server';
import { apiClient } from '@/shared/libs/apiClient';

export async function POST(
request: Request,
{ params }: { params: { expo_id: number } },
) {
const body = await request.json();
const { expo_id } = params;
const cookieStore = cookies();
const accessToken = cookieStore.get('accessToken')?.value;

const config = accessToken
? {
headers: {
Authorization: `Bearer ${accessToken}`,
},
}
: {};

try {
const response = await apiClient.post(`/form/${expo_id}`, body, config);
return NextResponse.json(response.data);
} catch (error) {
const axiosError = error as AxiosError<{ message: string }>;

const status = axiosError.response?.status;
const message = axiosError.response?.data?.message;

return NextResponse.json({ error: message }, { status });
}
}
31 changes: 31 additions & 0 deletions src/app/api/sms/qr/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { AxiosError } from 'axios';
import { cookies } from 'next/headers';
import { NextResponse } from 'next/server';
import { apiClient } from '@/shared/libs/apiClient';

export async function POST(request: Request) {
const body = await request.json();
const cookieStore = cookies();
const accessToken = cookieStore.get('accessToken')?.value;
const config = accessToken
? {
headers: {
Authorization: `Bearer ${accessToken}`,
},
}
: {};

console.log('QR Route called with body:', body);

try {
const response = await apiClient.post('/sms/qr', body, config);
return NextResponse.json(response.data);
} catch (error) {
const axiosError = error as AxiosError<{ message: string }>;

const status = axiosError.response?.status;
const message = axiosError.response?.data?.message;

return NextResponse.json({ error: message }, { status });
}
}
113 changes: 113 additions & 0 deletions src/entities/application/ui/TrainingRadioGroup/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
'use client';
import axios from 'axios';
import React, { useState, useEffect, useRef } from 'react';

interface ExpoData {
id: number;
title: string;
startedAt: string;
endedAt: string;
}

interface RadioGroupProps {
label: string;
name: string;
error?: string;
params: number;
trainingId?: string;
setSelectedValue: (value: number) => void;
selectedValue: number | null;
}

const TrainingRadioGroup = ({
label,
name,
error,
params,
setSelectedValue,
selectedValue,
}: RadioGroupProps) => {
const [otherInput] = useState('');
const [expoData, setExpoData] = useState<ExpoData[]>([]);
const [navigation] = useState<string>('training');

const otherInputRef = useRef<HTMLInputElement | null>(null);

useEffect(() => {
if (otherInputRef.current) {
otherInputRef.current.focus();
}
}, [otherInput]);

useEffect(() => {
const fetchExpoData = async () => {
try {
const endpoint =
navigation === 'training'
? `/api/training/program/${params}`
: `/api/standard/program/${params}`;

const response = await axios.get(endpoint);
setExpoData(response.data);
} catch (error) {
console.error('Error fetching expo data:', error);
}
};
fetchExpoData();
}, [navigation, params]);

const handleRadioChange = (id: number) => {
setSelectedValue(id);
};

return (
<div>
<div className="w-full rounded-sm border-1 border-solid border-gray-200 p-[18px]">
<div className="mb-3 text-xl">{label}</div>
<div className="flex flex-col space-y-2">
{expoData.map((option) => {
const optionId = `radio-${name}-${option.id}-${Math.random().toString(36).substr(2, 9)}`;
return (
<label
key={option.id}
htmlFor={optionId}
className="flex items-center space-x-2"
>
<input
type="radio"
id={optionId}
name={name}
value={option.id}
checked={selectedValue === option.id}
onChange={() => handleRadioChange(option.id)}
className="form-radio text-gray-500"
/>
<span className="text-gray-800">{option.title}</span>
</label>
);
})}
</div>
</div>
{error && (
<div className="float-right mt-2 flex text-sm text-error">{error}</div>
)}
</div>
);
};

TrainingRadioGroup.handleTrainingSubmit = async (
selectedValue: number,
trainingId: string,
) => {
try {
const response = await axios.post(`/api/application/${selectedValue}`, {
trainingId,
});
return response.data;
} catch (error) {
console.error('Error submitting training:', error);
throw error;
}
};

export default TrainingRadioGroup;
1 change: 1 addition & 0 deletions src/widgets/application/types/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ export type StandardForms = {
affiliation: string;
position: string;
informationStatus: boolean;
test?: string;
};
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
'use client';
import axios from 'axios';
import { useForm } from 'react-hook-form';
import { Input, RadioGroup } from '@/entities/application';
import { Button } from '@/shared/ui';
import { handleStandardFormsSubmit } from '@/widgets/application/model/applicationFormHandler';
import { StandardForms } from '../../../../types/type';
// import TrainingRadioGroup from '@/entities/application/ui/TrainingRadioGroup';

const StandardForm = ({ params }: { params: number }) => {
const {
Expand All @@ -26,8 +28,30 @@ const StandardForm = ({ params }: { params: number }) => {
{ value: 'no', label: 'μ•„λ‹ˆμš”' },
];

const onSubmit = (data: StandardForms) => {
handleStandardFormsSubmit(data, params);
const onSubmit = async (data: StandardForms) => {
try {
await handleStandardFormsSubmit(data, params);

const qrBody = {
phoneNumber: data.phoneNumber,
authority: 'ROLE_STANDARD',
};

const response = await axios.post('/api/sms/qr', qrBody);

console.log('QR SMS API Response:', response.data);
alert('QR SMS μš”μ²­μ΄ μ„±κ³΅μ μœΌλ‘œ μ²˜λ¦¬λ˜μ—ˆμŠ΅λ‹ˆλ‹€.');
} catch (error) {
if (axios.isAxiosError(error)) {
const errorMessage =
error.response?.data?.message || 'μ•Œ 수 μ—†λŠ” 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€.';
console.error('QR SMS API Error:', errorMessage);
alert(`QR SMS API ν˜ΈμΆœμ— μ‹€νŒ¨ν–ˆμŠ΅λ‹ˆλ‹€: ${errorMessage}`);
} else {
console.error('폼 제좜 쀑 μ—λŸ¬ λ°œμƒ:', error);
alert('폼 μ œμΆœμ— μ‹€νŒ¨ν–ˆμŠ΅λ‹ˆλ‹€. λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”.');
}
}
};

return (
Expand Down Expand Up @@ -63,6 +87,7 @@ const StandardForm = ({ params }: { params: number }) => {
options={yesNoOptions}
error={errors.informationStatus?.message}
/>
{/* <TrainingRadioGroup label="μ—°μˆ˜ 선택" name="test" params={params} trainingId={}/> */}

<Button text="μ‹ μ²­ν•˜κΈ°" type="submit" />
</form>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
'use client';
import axios from 'axios';
import { useState } from 'react';
import { useForm } from 'react-hook-form';
import { Input, RadioGroup } from '@/entities/application';
import TrainingRadioGroup from '@/entities/application/ui/TrainingRadioGroup';
import { Button } from '@/shared/ui';
import { handleTraineeFormsSubmit } from '@/widgets/application/model/applicationFormHandler';
import { TraineeForms } from '../../../../types/type';

const TraineeForm = ({ params }: { params: number }) => {
const [trainingId, setTrainingId] = useState('');

const {
control,
handleSubmit,
Expand Down Expand Up @@ -37,10 +42,34 @@ const TraineeForm = ({ params }: { params: number }) => {
{ value: 'no', label: 'μ•„λ‹ˆμš”' },
];

const onSubmit = (data: TraineeForms) => {
handleTraineeFormsSubmit(data, params);
const onSubmit = async (data: TraineeForms) => {
await handleTraineeFormsSubmit(data, params);
if (trainingId && selectedValue) {
const result = await TrainingRadioGroup.handleTrainingSubmit(
selectedValue,
trainingId,
);
console.log('Training Submit Result:', result);
}

const qrBody = {
phoneNumber: data.phoneNumber,
authority: 'ROLE_TRAINEE',
};

const response = await axios.post('/api/sms/qr', qrBody);

console.log('QR SMS API Response:', response.data);
alert('QR SMS μš”μ²­μ΄ μ„±κ³΅μ μœΌλ‘œ μ²˜λ¦¬λ˜μ—ˆμŠ΅λ‹ˆλ‹€.');
};

const handleTrainingIdChange = (
event: React.ChangeEvent<HTMLInputElement>,
) => {
setTrainingId(event.target.value);
};
const [selectedValue, setSelectedValue] = useState<number | null>(null);

return (
<form
onSubmit={handleSubmit(onSubmit)}
Expand All @@ -52,6 +81,7 @@ const TraineeForm = ({ params }: { params: number }) => {
label="μ—°μˆ˜ 아이디"
placeholder="μ—°μˆ˜ 아이디"
error={errors.trainingId?.message}
onChange={handleTrainingIdChange}
/>
<RadioGroup
control={control}
Expand Down Expand Up @@ -103,7 +133,14 @@ const TraineeForm = ({ params }: { params: number }) => {
options={yesNoOptions}
error={errors.informationStatus?.message}
/>

<TrainingRadioGroup
label="μ—°μˆ˜ 선택"
name="test"
params={params}
trainingId={trainingId}
selectedValue={selectedValue}
setSelectedValue={setSelectedValue}
/>
<Button text="μ‹ μ²­ν•˜κΈ°" type="submit" />
</form>
);
Expand Down
Loading