fix(sirsoft-gdpr): 마이페이지 쿠키 동의 철회 시 철회일 미표시 수정
철회 이력(status=revoked)이 있는 항목에 한해 status_at_formatted· status_label 을 채워 마이페이지에 철회일이 표시되도록 한다. 거부· 미설정 상태는 기존대로 미표시 유지 ( 확인). 동의/철회 날짜 줄을 초록/빨강으로 구분해 시각적으로 대등하게 강조한다 (배지·관리자 GDPR 동의 이력 화면과 동일 톤).
This commit is contained in:
1 parent
f1fcd48dc3
commit
d5b6f4b457
5 files changed
+44
-21
No files matched your search
@@ -17,7 +17,7 @@
|
||||
|
||||
- 쿠키 배너 버튼을 정리했습니다 — 「필수만 사용」을 제거하고, 「환경설정」을 「선택 동의」로, 펼침 패널의 저장 버튼을 「선택 저장」으로 변경했습니다.
|
||||
- 마이페이지 「쿠키 동의 관리」를 상태 배지 + 동의/철회 버튼 방식으로 개선했습니다 — 각 항목이 「동의함/거부함/항상 적용」 상태로 표시되고, 버튼을 누르면 동의·철회 여부를 한 번 더 확인합니다. 항목명도 「기능 쿠키」처럼 알아보기 쉽게 표기합니다.
|
||||
- 마이페이지 「쿠키 동의 관리」의 글자 크기·여백이 어긋나던 문제를 바로잡고, 동의한 항목에는 동의한 날짜를 함께 표시합니다.
|
||||
- 마이페이지 「쿠키 동의 관리」의 글자 크기·여백이 어긋나던 문제를 바로잡고, 동의한 항목에는 동의한 날짜를, 철회한 항목에는 철회한 날짜를 함께 표시합니다.
|
||||
- 「동의하지 않고 계속하기」를 눌러도 필수 쿠키가 「동의함」으로 기록되지 않도록 바로잡았습니다 — 필수 쿠키는 서비스 이용에 반드시 필요하여 동의 대상이 아닙니다.
|
||||
- 거부 시 안내 문구를 「동의하지 않고 계속합니다」로 바로잡았습니다 (이전에는 「동의가 저장되었습니다」로 잘못 표시).
|
||||
|
||||
|
||||
@@ -592,11 +592,11 @@
|
||||
"text": "{{consent?.consent_description ?? ''}}"
|
||||
},
|
||||
{
|
||||
"comment": "이슈 #430 (3안) — 라벨 아래 이력 줄: '날짜 + 동의'. 상태는 이미 라벨 옆 배지가 말하므로 여기선 시점만 강조. 서버가 동의한 항목만 status_label·status_at_formatted 를 채워 내려주므로(거부/미설정은 null) 둘 다 있을 때만 렌더.",
|
||||
"comment": "이슈 #430 (3안) + #509 16번 — 라벨 아래 이력 줄: '날짜 + 동의/철회'. 동의=초록, 철회=빨강으로 둘 다 강조해 균형을 맞춘다 (배지의 동의함=green-700/green-300, 관리자 「GDPR 동의 이력」의 revoked=red 관례와 동일 톤). 서버가 동의·철회 항목만 status_label·status_at_formatted 를 채워 내려주므로(거부/미설정은 null) 둘 다 있을 때만 렌더.",
|
||||
"type": "basic",
|
||||
"name": "Div",
|
||||
"if": "{{!!consent?.status_label && !!consent?.status_at_formatted}}",
|
||||
"props": { "className": "mt-1.5 text-xs text-gray-400 dark:text-gray-500" },
|
||||
"props": { "className": "mt-1.5 text-xs font-medium {{consent?.status === 'revoked' ? 'text-red-600 dark:text-red-400' : 'text-green-600 dark:text-green-400'}}" },
|
||||
"children": [
|
||||
{ "type": "basic", "name": "Span", "text": "{{consent?.status_at_formatted ?? ''}}" },
|
||||
{ "type": "basic", "name": "Span", "props": { "className": "ml-1" }, "text": "{{consent?.status_label ?? ''}}" }
|
||||
|
||||
+21
-5
@@ -311,17 +311,33 @@ describe('extensions/mypage_privacy_tab.json — 마이페이지 GDPR 동의 매
|
||||
* @scenario entry=reject, subject=member, category=optional
|
||||
* @effects mypage_status_date_line_consented_only
|
||||
*/
|
||||
it('이슈 #430 — 동의한 항목만 날짜 줄 노출 (서버가 동의 상태에만 status_at_formatted 제공)', () => {
|
||||
// PO 결정(2026-07-20): 날짜는 "동의한 항목만". 거부·철회·미설정은 서버가 status_at_formatted 를
|
||||
// null 로 내려주므로 날짜 줄이 렌더되지 않는다. 프론트는 status_label && status_at_formatted 가 둘 다
|
||||
// 있을 때만 날짜 줄을 그린다.
|
||||
it('이슈 #430/#509 — 동의·철회 이력이 있는 항목만 날짜 줄 노출 (서버가 status_at_formatted 제공)', () => {
|
||||
// PO 결정(2026-07-20) + 이슈 #509 16번 갱신: 날짜는 "동의한 항목" + "철회 이력이 있는 항목".
|
||||
// 거부·신규 미설정은 서버가 status_at_formatted 를 null 로 내려주므로 날짜 줄이 렌더되지 않는다.
|
||||
// 프론트는 status_label && status_at_formatted 가 둘 다 있을 때만 날짜 줄을 그리며, 값 자체는
|
||||
// 서버가 상태별(동의일/철회일)로 계산해 내려주므로 프론트 조건식은 상태 무관 동일하게 유지된다.
|
||||
const text = serializeForSearch(section);
|
||||
expect(text).toContain('consent?.status_label');
|
||||
expect(text).toContain('consent?.status_at_formatted');
|
||||
// 날짜 줄은 둘 다 있을 때만 (거부/미설정은 null → 미노출)
|
||||
// 날짜 줄은 둘 다 있을 때만 (거부/미설정은 null → 미노출, 철회는 이제 값이 채워짐)
|
||||
expect(text).toContain('!!consent?.status_label && !!consent?.status_at_formatted');
|
||||
});
|
||||
|
||||
/**
|
||||
* @scenario entry=reject, subject=member, category=optional
|
||||
* @effects mypage_status_date_line_revoked_color_distinction
|
||||
*/
|
||||
it('이슈 #509 16번 — 동의·철회 날짜 줄을 서로 다른 색으로 균형있게 강조 (동의=초록/철회=빨강, 배지·관리자 이력 화면과 동일 톤)', () => {
|
||||
// 철회만 강조되고 동의는 밋밋해 보인다는 PO 피드백 반영 — 동의도 철회와 대등하게 강조한다.
|
||||
// status === 'revoked' 면 text-red-600/dark:text-red-400, 그 외(동의)는 text-green-600/dark:text-green-400.
|
||||
const text = serializeForSearch(section);
|
||||
expect(text).toContain("consent?.status === 'revoked'");
|
||||
expect(text).toContain('text-red-600');
|
||||
expect(text).toContain('dark:text-red-400');
|
||||
expect(text).toContain('text-green-600');
|
||||
expect(text).toContain('dark:text-green-400');
|
||||
});
|
||||
|
||||
/**
|
||||
* @scenario entry=reject, subject=member, category=required
|
||||
* @effects mypage_required_shows_locked_button
|
||||
|
||||
@@ -53,15 +53,22 @@ class GdprUserConsentResource extends BaseApiResource
|
||||
} else {
|
||||
$status = 'none';
|
||||
}
|
||||
// 표시 날짜/라벨은 "동의한 항목만" 노출한다 (PO 결정, 2026-07-20).
|
||||
// 동의 상태(required·consented)만 동의일 + '동의' 라벨을 내려주고,
|
||||
// 거부·철회·미선택은 status_label·status_at_formatted 를 null 로 두어 프론트가 날짜 줄을 렌더하지 않는다.
|
||||
// (거부일·철회일은 사용자 화면 확인 가치가 낮고, 감사 로그·관리자 화면에서 확인 가능)
|
||||
// 표시 날짜/라벨은 "동의한 항목" + "철회 이력이 있는 항목"만 노출한다 (PO 결정, 2026-07-20 / 이슈 #509 16번 갱신).
|
||||
// 동의 상태(required·consented)는 동의일 + '동의' 라벨, 철회(revoked)는 철회일 + '철회' 라벨을 내려준다.
|
||||
// 거부·신규 미선택은 status_label·status_at_formatted 를 null 로 두어 프론트가 날짜 줄을 렌더하지 않는다.
|
||||
// (거부일은 사용자 화면 확인 가치가 낮고, 감사 로그·관리자 화면에서 확인 가능. 철회일은 유저 본인의
|
||||
// 철회권 행사 시점 확인 필요성이 있어 노출 — 이슈 #509 16번)
|
||||
$isConsentState = $status === 'required' || $status === 'consented';
|
||||
$statusRawDate = $isConsentState ? $this->consented_at : null;
|
||||
$statusLabel = $isConsentState
|
||||
? __('sirsoft-gdpr::messages.mypage.privacy.status.granted')
|
||||
: null;
|
||||
$statusRawDate = match (true) {
|
||||
$isConsentState => $this->consented_at,
|
||||
$status === 'revoked' => $this->revoked_at,
|
||||
default => null,
|
||||
};
|
||||
$statusLabel = match (true) {
|
||||
$isConsentState => __('sirsoft-gdpr::messages.mypage.privacy.status.granted'),
|
||||
$status === 'revoked' => __('sirsoft-gdpr::messages.mypage.privacy.status.revoked'),
|
||||
default => null,
|
||||
};
|
||||
// 이슈 #430 (버튼 재설계) — 상태 배지 문구. 토글 대신 배지+단일버튼 UI 에서
|
||||
// 오른쪽 배지에 노출한다. 철회 이력(revoked)과 신규 미선택(none)은 '미설정'으로 통합.
|
||||
$statusBadgeKey = match ($status) {
|
||||
|
||||
+5
-5
@@ -84,9 +84,10 @@ class GdprUserConsentResourceTest extends PluginTestCase
|
||||
$this->assertSame(__('sirsoft-gdpr::messages.mypage.privacy.badge.rejected'), $result['status_badge_label']);
|
||||
}
|
||||
|
||||
public function test_revoked_optional_maps_to_revoked_status_with_no_date_label(): void
|
||||
public function test_revoked_optional_maps_to_revoked_status_with_revoked_date_label(): void
|
||||
{
|
||||
// 철회도 거부와 동일 — 동의 상태가 아니므로 날짜/라벨 미노출.
|
||||
// 이슈 #509 16번 — 철회 이력이 있는 항목은 철회일 + '철회' 라벨을 노출한다
|
||||
// (배지는 신규 미선택과 함께 '미설정'(unset) 유지 — 배지 통합과 날짜 줄 노출은 별개).
|
||||
$consent = new GdprUserConsent([
|
||||
'consent_key' => 'cookie_marketing',
|
||||
'is_consented' => false,
|
||||
@@ -98,9 +99,8 @@ class GdprUserConsentResourceTest extends PluginTestCase
|
||||
$result = $this->toArray($consent);
|
||||
|
||||
$this->assertSame('revoked', $result['status']);
|
||||
$this->assertNull($result['status_label']);
|
||||
$this->assertNull($result['status_at_formatted']);
|
||||
// 철회는 신규 미선택과 함께 '미설정'(unset) 배지로 통합.
|
||||
$this->assertSame(__('sirsoft-gdpr::messages.mypage.privacy.status.revoked'), $result['status_label']);
|
||||
$this->assertNotNull($result['status_at_formatted']);
|
||||
$this->assertSame(__('sirsoft-gdpr::messages.mypage.privacy.badge.unset'), $result['status_badge_label']);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user