공지사항 삭제등록 등11
This commit is contained in:
@@ -16,6 +16,9 @@ export default function LessonEditPage() {
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||
const videoFileInputRef = useRef<HTMLInputElement>(null);
|
||||
const vrFileInputRef = useRef<HTMLInputElement>(null);
|
||||
const csvFileInputRef = useRef<HTMLInputElement>(null);
|
||||
const [courses, setCourses] = useState<Course[]>([]);
|
||||
const [showToast, setShowToast] = useState(false);
|
||||
|
||||
@@ -184,11 +187,134 @@ export default function LessonEditPage() {
|
||||
|
||||
// 기존 평가 문제 파일
|
||||
if (data.csvKey || data.csvUrl) {
|
||||
const csvFileKey = data.csvKey || (data.csvUrl && data.csvUrl.startsWith('csv/') ? data.csvUrl.substring(4) : data.csvUrl);
|
||||
|
||||
setExistingQuestionFile({
|
||||
fileName: data.csvFileName || data.csv_file_name || data.csvName || '평가문제.csv',
|
||||
fileKey: data.csvKey,
|
||||
fileKey: csvFileKey,
|
||||
});
|
||||
setQuestionFileCount(1);
|
||||
|
||||
// CSV 파일 다운로드 및 파싱
|
||||
if (data.csvUrl || data.csvKey) {
|
||||
try {
|
||||
const baseURL = process.env.NEXT_PUBLIC_API_BASE_URL || 'https://hrdi.coconutmeet.net';
|
||||
const token = typeof window !== 'undefined' ? localStorage.getItem('token') : null;
|
||||
|
||||
let fileKey: string | null = null;
|
||||
|
||||
// csvUrl에서 fileKey 추출
|
||||
if (data.csvUrl) {
|
||||
// 전체 URL인 경우 fileKey 추출
|
||||
if (data.csvUrl.startsWith('http://') || data.csvUrl.startsWith('https://')) {
|
||||
// URL에서 /api/files/ 이후 부분을 fileKey로 사용
|
||||
const filesIndex = data.csvUrl.indexOf('/api/files/');
|
||||
if (filesIndex !== -1) {
|
||||
const extractedKey = data.csvUrl.substring(filesIndex + '/api/files/'.length);
|
||||
// URL 디코딩
|
||||
fileKey = decodeURIComponent(extractedKey);
|
||||
} else {
|
||||
// URL에서 마지막 경로를 fileKey로 사용
|
||||
const urlParts = data.csvUrl.split('/');
|
||||
const lastPart = urlParts[urlParts.length - 1];
|
||||
if (lastPart) {
|
||||
fileKey = decodeURIComponent(lastPart);
|
||||
}
|
||||
}
|
||||
} else if (data.csvUrl.startsWith('csv/')) {
|
||||
// "csv/" 접두사 제거
|
||||
fileKey = data.csvUrl.substring(4);
|
||||
} else {
|
||||
// 그 외의 경우 fileKey로 사용
|
||||
fileKey = data.csvUrl;
|
||||
}
|
||||
} else if (data.csvKey) {
|
||||
// csvKey가 있으면 fileKey로 사용
|
||||
fileKey = data.csvKey;
|
||||
}
|
||||
|
||||
if (!fileKey) {
|
||||
return; // fileKey가 없으면 종료
|
||||
}
|
||||
|
||||
// /api/files/{fileKey} 형태로 요청
|
||||
const csvUrl = `${baseURL}/api/files/${encodeURIComponent(fileKey as string)}`;
|
||||
|
||||
const csvResponse = await fetch(csvUrl, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
...(token && { Authorization: `Bearer ${token}` }),
|
||||
},
|
||||
});
|
||||
|
||||
// 404 에러는 파일이 없는 것으로 간주하고 조용히 처리
|
||||
if (csvResponse.status === 404) {
|
||||
console.warn('CSV 파일을 찾을 수 없습니다:', data.csvUrl || data.csvKey);
|
||||
} else if (csvResponse.ok) {
|
||||
const csvText = await csvResponse.text();
|
||||
|
||||
// CSV 파싱 함수
|
||||
const parseCsv = (csvText: string): string[][] => {
|
||||
const lines: string[][] = [];
|
||||
let currentLine: string[] = [];
|
||||
let currentField = '';
|
||||
let inQuotes = false;
|
||||
|
||||
for (let i = 0; i < csvText.length; i++) {
|
||||
const char = csvText[i];
|
||||
const nextChar = csvText[i + 1];
|
||||
|
||||
if (char === '"') {
|
||||
if (inQuotes && nextChar === '"') {
|
||||
currentField += '"';
|
||||
i++;
|
||||
} else {
|
||||
inQuotes = !inQuotes;
|
||||
}
|
||||
} else if (char === ',' && !inQuotes) {
|
||||
currentLine.push(currentField.trim());
|
||||
currentField = '';
|
||||
} else if ((char === '\n' || char === '\r') && !inQuotes) {
|
||||
if (char === '\r' && nextChar === '\n') {
|
||||
i++;
|
||||
}
|
||||
if (currentField || currentLine.length > 0) {
|
||||
currentLine.push(currentField.trim());
|
||||
lines.push(currentLine);
|
||||
currentLine = [];
|
||||
currentField = '';
|
||||
}
|
||||
} else {
|
||||
currentField += char;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentField || currentLine.length > 0) {
|
||||
currentLine.push(currentField.trim());
|
||||
lines.push(currentLine);
|
||||
}
|
||||
|
||||
return lines;
|
||||
};
|
||||
|
||||
const parsed = parseCsv(csvText);
|
||||
|
||||
if (parsed.length > 0) {
|
||||
const headers = parsed[0];
|
||||
const rows = parsed.slice(1);
|
||||
|
||||
setCsvHeaders(headers);
|
||||
setCsvRows(rows);
|
||||
setCsvData(parsed);
|
||||
}
|
||||
} else if (!csvResponse.ok) {
|
||||
console.error(`CSV 파일을 가져오는데 실패했습니다. (${csvResponse.status})`);
|
||||
}
|
||||
} catch (csvError) {
|
||||
console.error('CSV 파일 파싱 실패:', csvError);
|
||||
// CSV 파싱 실패해도 계속 진행
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('강좌 로드 실패:', err);
|
||||
@@ -365,82 +491,94 @@ export default function LessonEditPage() {
|
||||
|
||||
const handleCsvFileUpload = async (file: File) => {
|
||||
try {
|
||||
// CSV 파일 파싱
|
||||
const reader = new FileReader();
|
||||
reader.onload = (event) => {
|
||||
const text = event.target?.result as string;
|
||||
if (!text) return;
|
||||
// CSV 파일 파싱 (Promise로 감싸서 파일 읽기 완료 대기)
|
||||
const parseCsvFile = (): Promise<string[][]> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = (event) => {
|
||||
const text = event.target?.result as string;
|
||||
if (!text) {
|
||||
reject(new Error('파일을 읽을 수 없습니다.'));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// CSV 파싱 함수
|
||||
const parseCsv = (csvText: string): string[][] => {
|
||||
const lines: string[][] = [];
|
||||
let currentLine: string[] = [];
|
||||
let currentField = '';
|
||||
let inQuotes = false;
|
||||
try {
|
||||
// CSV 파싱 함수
|
||||
const parseCsv = (csvText: string): string[][] => {
|
||||
const lines: string[][] = [];
|
||||
let currentLine: string[] = [];
|
||||
let currentField = '';
|
||||
let inQuotes = false;
|
||||
|
||||
for (let i = 0; i < csvText.length; i++) {
|
||||
const char = csvText[i];
|
||||
const nextChar = csvText[i + 1];
|
||||
for (let i = 0; i < csvText.length; i++) {
|
||||
const char = csvText[i];
|
||||
const nextChar = csvText[i + 1];
|
||||
|
||||
if (char === '"') {
|
||||
if (inQuotes && nextChar === '"') {
|
||||
currentField += '"';
|
||||
i++;
|
||||
} else {
|
||||
inQuotes = !inQuotes;
|
||||
}
|
||||
} else if (char === ',' && !inQuotes) {
|
||||
currentLine.push(currentField.trim());
|
||||
currentField = '';
|
||||
} else if ((char === '\n' || char === '\r') && !inQuotes) {
|
||||
if (char === '\r' && nextChar === '\n') {
|
||||
i++;
|
||||
if (char === '"') {
|
||||
if (inQuotes && nextChar === '"') {
|
||||
currentField += '"';
|
||||
i++;
|
||||
} else {
|
||||
inQuotes = !inQuotes;
|
||||
}
|
||||
} else if (char === ',' && !inQuotes) {
|
||||
currentLine.push(currentField.trim());
|
||||
currentField = '';
|
||||
} else if ((char === '\n' || char === '\r') && !inQuotes) {
|
||||
if (char === '\r' && nextChar === '\n') {
|
||||
i++;
|
||||
}
|
||||
if (currentField || currentLine.length > 0) {
|
||||
currentLine.push(currentField.trim());
|
||||
lines.push(currentLine);
|
||||
currentLine = [];
|
||||
currentField = '';
|
||||
}
|
||||
} else {
|
||||
currentField += char;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentField || currentLine.length > 0) {
|
||||
currentLine.push(currentField.trim());
|
||||
lines.push(currentLine);
|
||||
currentLine = [];
|
||||
currentField = '';
|
||||
}
|
||||
} else {
|
||||
currentField += char;
|
||||
|
||||
return lines;
|
||||
};
|
||||
|
||||
const parsed = parseCsv(text);
|
||||
|
||||
if (parsed.length === 0) {
|
||||
reject(new Error('CSV 파일이 비어있습니다.'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentField || currentLine.length > 0) {
|
||||
currentLine.push(currentField.trim());
|
||||
lines.push(currentLine);
|
||||
resolve(parsed);
|
||||
} catch (parseError) {
|
||||
reject(new Error('CSV 파일을 읽는 중 오류가 발생했습니다.'));
|
||||
}
|
||||
|
||||
return lines;
|
||||
};
|
||||
|
||||
const parsed = parseCsv(text);
|
||||
|
||||
if (parsed.length === 0) {
|
||||
alert('CSV 파일이 비어있습니다.');
|
||||
return;
|
||||
}
|
||||
reader.onerror = () => {
|
||||
reject(new Error('파일을 읽는 중 오류가 발생했습니다.'));
|
||||
};
|
||||
|
||||
// 첫 번째 줄을 헤더로 사용
|
||||
const headers = parsed[0];
|
||||
const rows = parsed.slice(1);
|
||||
|
||||
setCsvHeaders(headers);
|
||||
setCsvRows(rows);
|
||||
setCsvData(parsed);
|
||||
} catch (parseError) {
|
||||
console.error('CSV 파싱 오류:', parseError);
|
||||
alert('CSV 파일을 읽는 중 오류가 발생했습니다.');
|
||||
}
|
||||
reader.readAsText(file, 'UTF-8');
|
||||
});
|
||||
};
|
||||
|
||||
reader.onerror = () => {
|
||||
alert('파일을 읽는 중 오류가 발생했습니다.');
|
||||
};
|
||||
// CSV 파일 파싱
|
||||
const parsed = await parseCsvFile();
|
||||
|
||||
// 첫 번째 줄을 헤더로 사용
|
||||
const headers = parsed[0];
|
||||
const rows = parsed.slice(1);
|
||||
|
||||
reader.readAsText(file, 'UTF-8');
|
||||
setCsvHeaders(headers);
|
||||
setCsvRows(rows);
|
||||
setCsvData(parsed);
|
||||
|
||||
// 단일 파일 업로드
|
||||
const uploadResponse = await apiService.uploadFile(file);
|
||||
@@ -465,22 +603,24 @@ export default function LessonEditPage() {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('학습 평가 문제 업로드 실패:', error);
|
||||
alert('파일 업로드에 실패했습니다. 다시 시도해주세요.');
|
||||
const errorMessage = error instanceof Error ? error.message : '파일 업로드에 실패했습니다. 다시 시도해주세요.';
|
||||
alert(errorMessage);
|
||||
}
|
||||
};
|
||||
|
||||
// 파일 교체 확인 모달 핸들러
|
||||
const handleFileReplaceConfirm = async () => {
|
||||
if (!pendingFiles.length || !pendingFileType) return;
|
||||
const handleFileReplaceConfirm = () => {
|
||||
if (!pendingFileType) return;
|
||||
|
||||
setIsFileReplaceModalOpen(false);
|
||||
|
||||
if (pendingFileType === 'video') {
|
||||
await handleVideoFileUpload(pendingFiles);
|
||||
} else if (pendingFileType === 'vr') {
|
||||
await handleVrFileUpload(pendingFiles);
|
||||
} else if (pendingFileType === 'csv' && pendingFiles.length > 0) {
|
||||
await handleCsvFileUpload(pendingFiles[0]);
|
||||
// 파일 선택 다이얼로그 열기
|
||||
if (pendingFileType === 'video' && videoFileInputRef.current) {
|
||||
videoFileInputRef.current.click();
|
||||
} else if (pendingFileType === 'vr' && vrFileInputRef.current) {
|
||||
vrFileInputRef.current.click();
|
||||
} else if (pendingFileType === 'csv' && csvFileInputRef.current) {
|
||||
csvFileInputRef.current.click();
|
||||
}
|
||||
|
||||
setPendingFiles([]);
|
||||
@@ -634,9 +774,9 @@ export default function LessonEditPage() {
|
||||
// 성공 시 토스트 표시
|
||||
setShowToast(true);
|
||||
|
||||
// 토스트 표시 후 상세 페이지로 이동
|
||||
// 토스트 표시 후 상세 페이지로 이동 (새로고침하여 최신 데이터 표시)
|
||||
setTimeout(() => {
|
||||
router.push(`/admin/lessons/${params.id}`);
|
||||
router.push(`/admin/lessons/${params.id}?refresh=${Date.now()}`);
|
||||
}, 1500);
|
||||
} catch (error) {
|
||||
console.error('강좌 수정 실패:', error);
|
||||
@@ -858,9 +998,21 @@ export default function LessonEditPage() {
|
||||
30MB 미만 파일
|
||||
</span>
|
||||
</div>
|
||||
<label className="h-[32px] w-[62px] px-[4px] py-[3px] border border-[#8c95a1] rounded-[6px] bg-white text-[13px] font-medium leading-[1.4] text-[#4c5561] whitespace-nowrap hover:bg-gray-50 transition-colors cursor-pointer flex items-center justify-center">
|
||||
<label
|
||||
className="h-[32px] w-[62px] px-[4px] py-[3px] border border-[#8c95a1] rounded-[6px] bg-white text-[13px] font-medium leading-[1.4] text-[#4c5561] whitespace-nowrap hover:bg-gray-50 transition-colors cursor-pointer flex items-center justify-center"
|
||||
onClick={(e) => {
|
||||
// 기존 파일이나 새로 첨부한 파일이 있으면 확인 모달 표시
|
||||
if (existingVideoFiles.length > 0 || courseVideoFiles.length > 0 || courseVideoFileKeys.length > 0) {
|
||||
e.preventDefault();
|
||||
setPendingFiles([]);
|
||||
setPendingFileType('video');
|
||||
setIsFileReplaceModalOpen(true);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<span>첨부</span>
|
||||
<input
|
||||
ref={videoFileInputRef}
|
||||
type="file"
|
||||
multiple
|
||||
accept=".mp4,video/mp4"
|
||||
@@ -916,16 +1068,8 @@ export default function LessonEditPage() {
|
||||
}
|
||||
|
||||
if (validFiles.length > 0) {
|
||||
// 새로 첨부한 파일이 있으면 확인 모달 표시
|
||||
if (courseVideoFiles.length > 0 || courseVideoFileKeys.length > 0) {
|
||||
setPendingFiles(validFiles);
|
||||
setPendingFileType('video');
|
||||
setIsFileReplaceModalOpen(true);
|
||||
e.target.value = '';
|
||||
return;
|
||||
}
|
||||
|
||||
// 새로 첨부한 파일이 없으면 바로 업로드
|
||||
// 기존 파일 삭제 후 새 파일 업로드
|
||||
setExistingVideoFiles([]);
|
||||
handleVideoFileUpload(validFiles);
|
||||
}
|
||||
e.target.value = '';
|
||||
@@ -948,7 +1092,7 @@ export default function LessonEditPage() {
|
||||
className="h-[40px] px-[20px] py-[12px] flex items-center gap-[12px]"
|
||||
>
|
||||
<p className="flex-1 text-[15px] font-normal leading-[1.5] text-[#333c47]">
|
||||
{file.fileName} (기존)
|
||||
{file.fileName}
|
||||
</p>
|
||||
<button
|
||||
type="button"
|
||||
@@ -1002,9 +1146,21 @@ export default function LessonEditPage() {
|
||||
30MB 미만 파일
|
||||
</span>
|
||||
</div>
|
||||
<label className="h-[32px] w-[62px] px-[4px] py-[3px] border border-[#8c95a1] rounded-[6px] bg-white text-[13px] font-medium leading-[1.4] text-[#4c5561] whitespace-nowrap hover:bg-gray-50 transition-colors cursor-pointer flex items-center justify-center">
|
||||
<label
|
||||
className="h-[32px] w-[62px] px-[4px] py-[3px] border border-[#8c95a1] rounded-[6px] bg-white text-[13px] font-medium leading-[1.4] text-[#4c5561] whitespace-nowrap hover:bg-gray-50 transition-colors cursor-pointer flex items-center justify-center"
|
||||
onClick={(e) => {
|
||||
// 기존 파일이나 새로 첨부한 파일이 있으면 확인 모달 표시
|
||||
if (existingVrFiles.length > 0 || vrContentFiles.length > 0 || vrContentFileKeys.length > 0) {
|
||||
e.preventDefault();
|
||||
setPendingFiles([]);
|
||||
setPendingFileType('vr');
|
||||
setIsFileReplaceModalOpen(true);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<span>첨부</span>
|
||||
<input
|
||||
ref={vrFileInputRef}
|
||||
type="file"
|
||||
multiple
|
||||
accept=".zip,application/zip"
|
||||
@@ -1060,16 +1216,8 @@ export default function LessonEditPage() {
|
||||
}
|
||||
|
||||
if (validFiles.length > 0) {
|
||||
// 새로 첨부한 파일이 있으면 확인 모달 표시
|
||||
if (vrContentFiles.length > 0 || vrContentFileKeys.length > 0) {
|
||||
setPendingFiles(validFiles);
|
||||
setPendingFileType('vr');
|
||||
setIsFileReplaceModalOpen(true);
|
||||
e.target.value = '';
|
||||
return;
|
||||
}
|
||||
|
||||
// 새로 첨부한 파일이 없으면 바로 업로드
|
||||
// 기존 파일 삭제 후 새 파일 업로드
|
||||
setExistingVrFiles([]);
|
||||
handleVrFileUpload(validFiles);
|
||||
}
|
||||
e.target.value = '';
|
||||
@@ -1092,7 +1240,7 @@ export default function LessonEditPage() {
|
||||
className="h-[40px] px-[20px] py-[12px] flex items-center gap-[12px]"
|
||||
>
|
||||
<p className="flex-1 text-[15px] font-normal leading-[1.5] text-[#333c47]">
|
||||
{file.fileName} (기존)
|
||||
{file.fileName}
|
||||
</p>
|
||||
<button
|
||||
type="button"
|
||||
@@ -1147,9 +1295,21 @@ export default function LessonEditPage() {
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-[8px]">
|
||||
<label className="h-[32px] w-[62px] px-[4px] py-[3px] border border-[#8c95a1] rounded-[6px] bg-white text-[13px] font-medium leading-[1.4] text-[#4c5561] whitespace-nowrap hover:bg-gray-50 transition-colors cursor-pointer flex items-center justify-center">
|
||||
<label
|
||||
className="h-[32px] w-[62px] px-[4px] py-[3px] border border-[#8c95a1] rounded-[6px] bg-white text-[13px] font-medium leading-[1.4] text-[#4c5561] whitespace-nowrap hover:bg-gray-50 transition-colors cursor-pointer flex items-center justify-center"
|
||||
onClick={(e) => {
|
||||
// 기존 파일이나 새로 첨부한 파일이 있으면 확인 모달 표시
|
||||
if (questionFileObject || questionFileKey || existingQuestionFile) {
|
||||
e.preventDefault();
|
||||
setPendingFiles([]);
|
||||
setPendingFileType('csv');
|
||||
setIsFileReplaceModalOpen(true);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<span>첨부</span>
|
||||
<input
|
||||
ref={csvFileInputRef}
|
||||
type="file"
|
||||
accept=".csv"
|
||||
className="hidden"
|
||||
@@ -1166,100 +1326,9 @@ export default function LessonEditPage() {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// CSV 파일 파싱
|
||||
const reader = new FileReader();
|
||||
reader.onload = (event) => {
|
||||
const text = event.target?.result as string;
|
||||
if (!text) return;
|
||||
|
||||
try {
|
||||
// CSV 파싱 함수
|
||||
const parseCsv = (csvText: string): string[][] => {
|
||||
const lines: string[][] = [];
|
||||
let currentLine: string[] = [];
|
||||
let currentField = '';
|
||||
let inQuotes = false;
|
||||
|
||||
for (let i = 0; i < csvText.length; i++) {
|
||||
const char = csvText[i];
|
||||
const nextChar = csvText[i + 1];
|
||||
|
||||
if (char === '"') {
|
||||
if (inQuotes && nextChar === '"') {
|
||||
currentField += '"';
|
||||
i++;
|
||||
} else {
|
||||
inQuotes = !inQuotes;
|
||||
}
|
||||
} else if (char === ',' && !inQuotes) {
|
||||
currentLine.push(currentField.trim());
|
||||
currentField = '';
|
||||
} else if ((char === '\n' || char === '\r') && !inQuotes) {
|
||||
if (char === '\r' && nextChar === '\n') {
|
||||
i++;
|
||||
}
|
||||
if (currentField || currentLine.length > 0) {
|
||||
currentLine.push(currentField.trim());
|
||||
lines.push(currentLine);
|
||||
currentLine = [];
|
||||
currentField = '';
|
||||
}
|
||||
} else {
|
||||
currentField += char;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentField || currentLine.length > 0) {
|
||||
currentLine.push(currentField.trim());
|
||||
lines.push(currentLine);
|
||||
}
|
||||
|
||||
return lines;
|
||||
};
|
||||
|
||||
const parsed = parseCsv(text);
|
||||
|
||||
if (parsed.length === 0) {
|
||||
alert('CSV 파일이 비어있습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
// 첫 번째 줄을 헤더로 사용
|
||||
const headers = parsed[0];
|
||||
const rows = parsed.slice(1);
|
||||
|
||||
setCsvHeaders(headers);
|
||||
setCsvRows(rows);
|
||||
setCsvData(parsed);
|
||||
} catch (parseError) {
|
||||
console.error('CSV 파싱 오류:', parseError);
|
||||
alert('CSV 파일을 읽는 중 오류가 발생했습니다.');
|
||||
}
|
||||
};
|
||||
|
||||
reader.onerror = () => {
|
||||
alert('파일을 읽는 중 오류가 발생했습니다.');
|
||||
};
|
||||
|
||||
reader.readAsText(file, 'UTF-8');
|
||||
|
||||
// 기존 파일이 있으면 확인 모달 표시
|
||||
if (questionFileObject || questionFileKey) {
|
||||
setPendingFiles([file]);
|
||||
setPendingFileType('csv');
|
||||
setIsFileReplaceModalOpen(true);
|
||||
e.target.value = '';
|
||||
return;
|
||||
}
|
||||
|
||||
// 기존 파일이 없으면 바로 업로드
|
||||
await handleCsvFileUpload(file);
|
||||
} catch (error) {
|
||||
console.error('학습 평가 문제 업로드 실패:', error);
|
||||
alert('파일 업로드에 실패했습니다. 다시 시도해주세요.');
|
||||
}
|
||||
// input 초기화 (같은 파일 다시 선택 가능하도록)
|
||||
// 기존 파일 삭제 후 새 파일 업로드
|
||||
setExistingQuestionFile(null);
|
||||
await handleCsvFileUpload(file);
|
||||
e.target.value = '';
|
||||
}}
|
||||
/>
|
||||
@@ -1279,7 +1348,7 @@ export default function LessonEditPage() {
|
||||
{(existingQuestionFile || questionFileObject) && (
|
||||
<div className="h-[40px] px-[20px] py-[12px] flex items-center gap-[12px] bg-white border-b border-[#dee1e6]">
|
||||
<p className="flex-1 text-[15px] font-normal leading-[1.5] text-[#333c47]">
|
||||
{existingQuestionFile ? `${existingQuestionFile.fileName} (기존)` : questionFileObject?.name}
|
||||
{existingQuestionFile ? existingQuestionFile.fileName : questionFileObject?.name}
|
||||
</p>
|
||||
<button
|
||||
type="button"
|
||||
|
||||
Reference in New Issue
Block a user