Skip to content

Commit

Permalink
feat : QR Image 조회 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
dlgocks1 committed Jun 27, 2024
1 parent 5c029a6 commit 6f371c5
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 13 deletions.
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ dependencies {
implementation("mysql:mysql-connector-java:8.0.28")

implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2")
implementation("com.google.zxing:javase:3.5.0")
implementation("com.google.zxing:core:3.5.0")


annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import com.example.cmc_be.domain.user.entity.User
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.Parameter
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.http.ResponseEntity
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.web.bind.annotation.*

Expand Down Expand Up @@ -55,6 +56,17 @@ class AdminAttendanceController(
return CommonResponse.onSuccess(qrCodeService.getCodeInfo(code))
}

@GetMapping("/code/image")
@Operation(summary = "03-02-1 코드 QR이미지 조회")
fun getCodeImage(
@AuthenticationPrincipal user: User,
@Parameter(description = "코드", example = "8dFsb")
@RequestParam code: String,
@RequestParam type: String,
): CommonResponse<ResponseEntity<ByteArray>> {
return CommonResponse.onSuccess(qrCodeService.getCodeImage(code, type))
}

@GetMapping("/code/all")
@Operation(summary = "03-03 모든 코드 정보 조회")
fun getCodeInfo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,17 @@ import com.example.cmc_be.domain.attendance.repository.AttendanceRepository
import com.example.cmc_be.domain.generation.entity.GenerationWeeksInfo
import com.example.cmc_be.domain.user.entity.User
import com.example.cmc_be.utils.RandomNumberUtil
import com.google.zxing.BarcodeFormat
import com.google.zxing.MultiFormatWriter
import com.google.zxing.client.j2se.MatrixToImageWriter
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Sort
import org.springframework.data.repository.findByIdOrNull
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.stereotype.Service
import java.io.ByteArrayOutputStream


@Service
class QrCodeService(
Expand Down Expand Up @@ -85,6 +92,19 @@ class QrCodeService(
)
}

fun getCodeImage(code: String, type: String): ResponseEntity<ByteArray> {
val url = if (type == "AOS") generateAndroidSchmea(code) else generateIOSSchmea(code)
val encode = MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, 300, 300)
val out = ByteArrayOutputStream()
MatrixToImageWriter.writeToStream(encode, "PNG", out)
return ResponseEntity.ok()
.contentType(MediaType.IMAGE_PNG)
.body(out.toByteArray())
.also {
out.close()
}
}

fun validateCode(user: User, attendanceCode: AttendanceCode) {
validateGeneration(user, attendanceCode.generation)
validateAlreadyAttendance(user.id, attendanceCode)
Expand Down
11 changes: 8 additions & 3 deletions src/main/webapp/src/apis/handlers/attendance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,13 @@ export const attendanceApi = {
return await request.post<AttendanceCodeDTO>(url, payload);
},

deleteAttendanceCode: async (id: any) => {
const url = setSearchParams(`/admin/attendances/code`, id);
return await request.delete<any>(url, id);
deleteAttendanceCode: async (payload: any) => {
const url = setSearchParams(`/admin/attendances/code`, payload);
return await request.delete<any>(url, payload);
},

getQRImageByCode: async (payload: { code: string, type: string }) => {
const url = setSearchParams(`/admin/attendances/code/image`, payload);
return await request.get<QRImageDTO>(url);
},
};
12 changes: 12 additions & 0 deletions src/main/webapp/src/apis/types/attendance/AttendanceCodeDTO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,15 @@ export interface AttendanceCodeDTO {
lateMinute: string;
}


export interface QRImage {
id: string;
generation: string;
week: string;
hour: number;
generationWeeksInfo: any; // TODO GenerationWeeksInfo 오브젝트인데 파싱이 안됨
startTime: string;
endTime: string;
lateMinute: string;
}

4 changes: 4 additions & 0 deletions src/main/webapp/src/apis/types/attendance/QRImageDTO.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
interface QRImageDTO {
body: string;
}

27 changes: 17 additions & 10 deletions src/main/webapp/src/pages/attendance/QRCodeList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {CButton, CFormInput} from "@coreui/react";
import useSelect, {Option} from "../../components/Select/useSelect";
import {FlexBox} from "../../components/FlexBox";
import ModalButton from "../../components/ModalButton";
import {QRImageComponent} from "./QRImageComponent";

const ATTENDANCE_CODE_COLUMN: Column[] = [
{label: 'id', key: 'id'},
Expand All @@ -22,6 +23,8 @@ const ATTENDANCE_CODE_COLUMN: Column[] = [
{label: '출석 시작 시간', key: 'startTime'},
{label: '출석 종료 시간', key: 'endTime'},
{label: '지각 허용 시간(분)', key: 'lateMinute'},
{label: 'AOS 코드', key: 'getAOSModal'},
{label: 'IOS 코드', key: 'getIOSModal'},
{label: 'QR 삭제', key: 'modal'},
];

Expand Down Expand Up @@ -214,18 +217,22 @@ const QRCodeList = () => {
renderColumnData={{
modal: data => (
<>
<>
<ModalButton
title='출석코드 삭제'
description={`출석 코드(${data.id})를 삭제하시겠어요?`}
onConfirm={() => {
deleteAttendanceCode(data.id)
}}>
삭제
</ModalButton>
</>
<ModalButton
title='출석코드 삭제'
description={`출석 코드(${data.id})를 삭제하시겠어요?`}
onConfirm={() => {
deleteAttendanceCode(data.id)
}}>
삭제
</ModalButton>
</>
),
getAOSModal: data => (
<QRImageComponent code={data.id as string} type={"AOS"}/>
),
getIOSModal: data => (
<QRImageComponent code={data.id as string} type={"IOS"}/>
),
}}
/>
</Fragment>
Expand Down
29 changes: 29 additions & 0 deletions src/main/webapp/src/pages/attendance/QRImageComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React, {useEffect, useState} from "react";
import {attendanceApi} from "../../apis/handlers/attendance";

export function QRImageComponent({code, type}: { code: string, type: string }) {
const [imageSrc, setImageSrc] = useState('');

useEffect(() => {
console.log("-------------")
attendanceApi.getQRImageByCode({
code: code,
type: type
}).then((r) => {
console.log(r)
setImageSrc(`data:image/jpeg;base64,${r.body}`);
}).catch((e) => {
console.log(e)
})
}, []);

return (
<div>
{imageSrc ? (
<img src={imageSrc} alt="Fetched from server"/>
) : (
<p>Loading image...</p>
)}
</div>
);
};

0 comments on commit 6f371c5

Please sign in to comment.