Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
2 changes: 2 additions & 0 deletions Android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

<!-- permissions needed for using the internet or an embedded WebKit browser -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<!-- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> -->

<!-- Android 13+ notification permission -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ final class BugReportViewModel {
bodyData.append("--\(boundary)--\r\n".data(using: .utf8)!)

let endpoint = BugReportAPI.uploadImages(boundary: boundary, body: bodyData)
let response = try await APIClient.shared.request(endpoint, responseType: [String].self)
return response
let response = try await APIClient.shared.request(endpoint, responseType: ImageUploadResponse.self)
return response.fileNames
}

private func submitReport(fileNames: [String]) async throws {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,16 @@ struct StudentAttendanceCell: View {
.pickText(type: .body2, textColor: statusColor(student.status))
.padding(.horizontal, 16)
.padding(.vertical, 8)
.background(statusBackgroundColor(student.status))
.cornerRadius(8)
.background(
RoundedRectangle(cornerRadius: 8)
.fill(statusBackgroundColor(student.status))
)
.overlay(
RoundedRectangle(cornerRadius: 8)
.stroke(statusBorderColor(student.status), lineWidth: 1)
)
Comment on lines +25 to +32

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

"출석"과 "이동" 상태의 테두리가 보이지 않습니다.

"출석" 상태는 배경색과 테두리색이 모두 Primary.primary500로 동일하고, "이동" 상태는 둘 다 Gray.gray700입니다. 배경과 테두리가 같은 색상이면 테두리가 시각적으로 구분되지 않습니다.

의도된 디자인인지 확인이 필요합니다. 만약 테두리를 표시하려는 의도였다면, 테두리 색상을 배경색과 구분되는 색상으로 변경해야 합니다.

🎨 테두리를 보이게 하려면 색상 수정 예시
 private func statusBorderColor(_ status: String) -> Color {
     switch status {
     case "출석":
-        return .Primary.primary500
+        return .Primary.primary600  // 또는 더 진한 색상
     case "이동":
-        return .Gray.gray700
+        return .Gray.gray800  // 또는 더 진한 색상
     case "귀가", "외출":
         return .Error.error

Also applies to: 73-86

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Sources/PiCKAdmin/Features/SelfStudyCheck/Components/SelfStudyCheckComponents.swift`
around lines 25 - 32, The border is invisible for statuses where
statusBackgroundColor(student.status) equals statusBorderColor(student.status)
(e.g., "출석" and "이동"); update the statusBorderColor function (or wherever
statusBorderColor is defined/returned) to return a contrasting color for those
specific status values (use student.status matching "출석"/"이동" or the enum cases)
so the RoundedRectangle.stroke(...) overlay is visually distinct from the
RoundedRectangle.fill(...) background; ensure the change affects all places
using statusBorderColor(student.status) (including the other occurrence
referenced) so the border becomes visible.

}
.buttonStyle(.plain)
}
.padding(.vertical, 12)
.padding(.horizontal, 16)
Expand All @@ -36,13 +43,13 @@ struct StudentAttendanceCell: View {
private func statusColor(_ status: String) -> Color {
switch status {
case "출석":
return .Primary.primary500
return .Normal.white
case "이동":
return .Gray.gray700
return .Normal.white
Comment on lines +46 to +48

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: 디자인 시스템의 색상 정의를 찾아 Primary.primary500, Gray.gray700, Normal.white 값 확인

rg -n "primary500|gray700" --type swift -A 2 -B 2

Repository: DSM-PICK/PiCK_Android_ADMIN

Length of output: 40673


🏁 Script executed:

# Find the Normal.white color definition
rg -n "Normal.*white|white.*=" --type swift Sources/PiCKAdmin/DesignSystem/ -A 1 -B 1

Repository: DSM-PICK/PiCK_Android_ADMIN

Length of output: 937


🏁 Script executed:

# Also examine the specific file and lines mentioned in the review
head -80 Sources/PiCKAdmin/Features/SelfStudyCheck/Components/SelfStudyCheckComponents.swift | tail -40

Repository: DSM-PICK/PiCK_Android_ADMIN

Length of output: 1090


🏁 Script executed:

# Calculate contrast ratios for the color combinations
python3 << 'EOF'
from fractions import Fraction

def hex_to_rgb(hex_color):
    hex_color = hex_color.lstrip('#')
    return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))

def get_relative_luminance(r, g, b):
    """Calculate relative luminance according to WCAG formula"""
    r = r / 255
    g = g / 255
    b = b / 255
    
    r = r / 12.92 if r <= 0.03928 else ((r + 0.055) / 1.055) ** 2.4
    g = g / 12.92 if g <= 0.03928 else ((g + 0.055) / 1.055) ** 2.4
    b = b / 12.92 if b <= 0.03928 else ((b + 0.055) / 1.055) ** 2.4
    
    return 0.2126 * r + 0.7152 * g + 0.0722 * b

def get_contrast_ratio(lum1, lum2):
    """Calculate contrast ratio"""
    lighter = max(lum1, lum2)
    darker = min(lum1, lum2)
    return (lighter + 0.05) / (darker + 0.05)

# Colors
white_rgb = (255, 255, 255)  # Normal.white
primary500_rgb = hex_to_rgb("`#9650FA`")
gray700_rgb = hex_to_rgb("`#79777C`")

# Calculate luminances
white_lum = get_relative_luminance(*white_rgb)
primary500_lum = get_relative_luminance(*primary500_rgb)
gray700_lum = get_relative_luminance(*gray700_rgb)

# Calculate contrast ratios
ratio_white_on_primary = get_contrast_ratio(white_lum, primary500_lum)
ratio_white_on_gray = get_contrast_ratio(white_lum, gray700_lum)

print(f"White (`#FFFFFF`) on Primary.primary500 (`#9650FA`): {ratio_white_on_primary:.2f}:1")
print(f"White (`#FFFFFF`) on Gray.gray700 (`#79777C`): {ratio_white_on_gray:.2f}:1")
print()
print("WCAG AA Requirements:")
print("- Normal text: 4.5:1")
print("- Large text (18pt+/bold 14pt+): 3:1")
print()
if ratio_white_on_primary < 4.5:
    print(f"✗ Primary.primary500: FAILS (Current: {ratio_white_on_primary:.2f}:1)")
if ratio_white_on_gray < 4.5:
    print(f"✗ Gray.gray700: FAILS (Current: {ratio_white_on_gray:.2f}:1)")
EOF

Repository: DSM-PICK/PiCK_Android_ADMIN

Length of output: 345


접근성: 흰색 텍스트의 명암비가 WCAG AA 기준을 충족하지 못합니다.

"출석" 상태는 흰색 텍스트를 Primary.primary500(#9650FA) 배경에 표시하고, "이동" 상태는 흰색 텍스트를 Gray.gray700(#79777C) 배경에 표시합니다.

실제 명암비 계산 결과:

  • 흰색 on Primary.primary500: 4.35:1 (필요: 4.5:1)
  • 흰색 on Gray.gray700: 4.43:1 (필요: 4.5:1)

두 조합 모두 일반 텍스트 기준(4.5:1)을 0.07~0.15 포인트 하회합니다. 텍스트 색상을 밝게 변경하거나 배경색을 어둡게 하여 명암비를 4.5:1 이상으로 개선해야 합니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Sources/PiCKAdmin/Features/SelfStudyCheck/Components/SelfStudyCheckComponents.swift`
around lines 46 - 48, Switch cases for "출석" and "이동" currently return
.Normal.white which yields contrast ratios below WCAG AA (4.5:1) against
Primary.primary500 and Gray.gray700; update the return values for the "출석" and
"이동" branches so the text color (or the background color used with them) meets
at least 4.5:1 contrast—either pick a lighter text color token that achieves
≥4.5:1 on Primary.primary500 and Gray.gray700, or darken those background tokens
and verify with a contrast checker; ensure the changes are applied where the
code returns .Normal.white for the "출석" and "이동" cases.

case "귀가", "외출":
return .Primary.primary400
return .Error.error
case "현체", "취업":
return .Gray.gray600
return .Gray.gray900
default:
return .Normal.black
}
Expand All @@ -51,15 +58,30 @@ struct StudentAttendanceCell: View {
private func statusBackgroundColor(_ status: String) -> Color {
switch status {
case "출석":
return .Primary.primary50
return .Primary.primary500
case "이동":
return .Gray.gray100
return .Gray.gray700
case "귀가", "외출":
return .Primary.primary50.opacity(0.5)
return .Error.errorLight
case "현체", "취업":
return .Gray.gray100
return .Gray.gray200
default:
return .Gray.gray100
}
}

private func statusBorderColor(_ status: String) -> Color {
switch status {
case "출석":
return .Primary.primary500
case "이동":
return .Gray.gray700
case "귀가", "외출":
return .Error.error
case "현체", "취업":
return .Gray.gray600
default:
return .Gray.gray400
}
}
}