Commit Graph

53 Commits

Author SHA1 Message Date
zio
d8ef5c53df feat(m2): DWG/JPG floorplan underlay tabs + CAD extraction pipeline
Owner directives 2026-07-14~15: run the DWG pipeline; split floorplan into DWG and JPG tabs.

- tools/cad/dwg_extract.py: DWG(LibreDWG dwg2dxf) -> DXF -> layer inventory /
  keyword extraction / grid-label anchor detection (ezdxf, recover fallback)
- tools/cad/render_hall_png.py: render hall-band crops from the K1 combined
  plan+trench drawing (x0=293.5m, width 171m, Y bands 80.1m + 63m pitch,
  single load -> multi-crop). Real trench layout confirmed: 7 horizontal runs
  at ~9m pitch + central feeder (differs from assumed 6m grid seed - V61 later)
- public/media/floorplans/dwg/hall1..5.png: K1 hall underlays (3m margin crop,
  deterministic calibration from render params)
- Editor left panel new tool group with JPG/DWG tabs; DWG disabled for
  halls without CAD render yet (K2 pending). Canvas switches url+region.
- docs/analysis/cad-extraction.md: pipeline findings, limits (A3002 LibreDWG
  crash, band-to-hall numbering direction to confirm), next steps

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 00:35:12 +09:00
zio
6c0d364fc9 feat(m2): floorplan tree selection + easy 3-step auto-layout wizard (real operation)
Owner directives 2026-07-14: select floorplan via tree (center > hall > zone),
generate booths inside it, images only on button click, zoom popup + save.

- V59: align hall width/depth to official floorplan orientation (all 10 halls
  were transposed vs drawings, e.g. H1 63x171 -> 171x63); re-derive assumed
  exits (V4 formula) and trench grid (V5 formula)
- V60: hall_zone tree table + drawing-measured zones (1A/1B, 6A/6B/6C, 7A/7B,
  8A/8B, 9B/9A, 10B/10A) - data as tree: center > hall > zone
- GET /api/halls/tree (HallTreeController) - selection tree for the wizard
- AutoLayoutRequest.zoneId: pack booths only inside the selected zone bounds
- S7 aerial preview is NO LONGER auto-published per option (Gemini quota);
  new POST .../auto-generate/preview publishes only on user button click,
  persisted in render_job for gallery re-view and auction reference reuse
- AutoLayoutDialog reworked as 3-step wizard (place > conditions > pick):
  per-option generate-aerial-image button, click-to-zoom lightbox with
  download/save, and REAL apply via POST /apply-option (was refetch-only -
  selected options were never persisted)
- FloorplanCanvas calibration: H8/H10 floor regions re-measured with
  union-of-blobs (center aisle split the color blob, bottom half only before)
- Editor toolbar hall selector (grouped by exhibition center)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 23:36:07 +09:00
zio
0cc7f26c56 feat(m2): place auto-generated booths inside the hall floorplan
Owner directive 2026-07-14: booths must be auto-placed inside the floorplan.

- hallFloorplan.ts: per-hall floor-region calibration [x0,y0,x1,y1] (auto-measured
  largest color blob of the exhibition floor in each crawled JPG, halls 1-10)
- FloorplanCanvas: align calibrated floor region to hall rect (0,0-W,H m) so booth
  coordinates land inside the drawn floor; raise underlay visibility (0.3 -> 0.55)
- BoothLayoutEditorPage: use real hall dims from LayoutDto.hall (was hardcoded 126x90),
  pass floorRegion; types.ts HallInfoDto added in previous commit
- FloorplanServiceImpl.packBooths: honor request conditions as reserved zones -
  central cross aisles (>=40m spans), entrance clear zones, stage/lounge blocks
  (previously mainEntranceCount/stageCount/loungeCount were ignored)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 22:59:31 +09:00
zio
c686365021 feat(live-demo): admin stats API, auction realtime ranking push, CMS scheduled publish
- AdminStatsController/AdminStatsDto: real-count admin metrics (SCR-16), SystemAccessGuard.requireAdmin
- AuctionRealtimeService: STOMP /topic/auctions/{id}/ranking broadcast after commit (public ranking only, sealed-bid safe), polling fallback kept
- CmsScheduledPublisher: 30s DB poller -> CmsService.runScheduledPublish (same path as manual publish), V58 partial index (idempotent)
- Frontend: AdminDashboardPage real stats wiring, AuctionDetailPage live ranking via websocket, CmsWorkflowPage schedule UI
- CmsServiceTest: constructor updated for AuditLogService

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 22:59:14 +09:00
zio
1c4edb0cd8 feat(m2): floorplan canvas wheel zoom + left-drag pan (owner directive 07-14)
- non-passive wheel listener zooms 0.3x~4x, synced to page zoom state via
  new onZoomChange prop (wired in BoothLayoutEditorPage)
- pointer-capture left-drag pans the canvas; 3px threshold and click-capture
  suppression so a drag never mis-fires booth select/deselect
- grab/grabbing cursor, transition off while panning, touch-action none

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 22:06:45 +09:00
zio
3f479a93cb fix(ui): resolve reviewer backlog R13-01, R15-02, R17-01, R17-02 + stale comments
- R13-01: SCR-13 revenue trend now renders AI forecast as dashed area —
  client-side least-squares linear regression, 2-month horizon, bridge point,
  AiLabel + note; skipped gracefully under 3 data points
- R15-02: SCR-15 category default is now visible — categoryDefaulted flag
  renders a '기본값' badge with tooltip instead of silent 'exhibition'
- R17-01: SCR-17 adds §8 system icon library — auto-enumerates icons.tsx
  line-SVG set (namespace import, self-syncing)
- R17-02: CHART.warning renamed CHART.violationWarn (value unchanged),
  ReportPage usage updated
- hygiene: MeetingPage/MultilingualCmsPage header comments updated to reflect
  shipped STT + AI-translation wiring (stale '미배선' removed)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 22:06:23 +09:00
zio
f7256a0c56 fix(auth): global ADMIN has full permissions; member role no longer masked by hm flag
Owner: 'admin은 모든 권한'. requireRole(ORGANIZER)-style endpoints 403'd for
admin because roleFor() returned HALL_MANAGER (hm/ADMIN flag) even when the
user held an explicit ORGANIZER membership.
- EventAccessGuard.requireRole: isAdmin() bypasses the allowed-role set
  (tenant boundary still enforced)
- KintexPrincipal.roleFor: explicit event membership role wins; HALL_MANAGER
  only as fallback
- HallAssignController: ADMIN allowed alongside hall manager

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 21:52:34 +09:00
zio
8719d110f3 fix(m2): floorplan studio — real hall drawing underlay + 404 as empty start state
Owner report: '도면이 안나온다 / 도면을 불러오지 못했습니다'.
- Canvas now renders crawled hall drawings (hall1-10.jpg, build-bundled per
  V46 poster pattern) as blueprint-tone underlay beneath booth polygons;
  hides gracefully on load failure.
- GET layout 404 (no saved layout for the hall) no longer shows a hard error
  screen — enters empty canvas with 'AI 자동배치로 시작' CTA instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 21:35:46 +09:00
zio
7a735a4c71 fix(ui): approval queue grid — remove fixed-viewport clipping, flow with page scroll
Owner directive: grids must render fully without internal scrollbars
(pagination handles row counts). .kx-aq was the only data-grid shell with
height:100% + overflow:hidden/auto clipping; now page-flow with sticky side.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 21:35:45 +09:00
zio
b5d29e6061 fix(m5): close render completion loop — worker HTTP callback + /renders static serving
Worker published only Redis pub/sub events; backend status stayed QUEUED
forever (callback endpoint never called — gap masked by earlier Gemini 429).
- worker.py: POST /api/internal/render/callback (X-Worker-Token) after each
  job with imageUrl=/renders/{key}, schemaHash, modelVersion, errorMessage
- backend: serve /renders/** from RENDER_OUTPUT_DIR + security permit

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 20:52:54 +09:00
zio
a03f9d4de8 fix(seed): make demo EDM recipients deliverable via owner plus-addressing (V56)
All @kintex.test seed addresses bounce now that live send is open.
Replace them with ythong86+<registrationId>@gmail.com so live-send E2E
actually delivers — every address routes to the owner's own inbox; no
third-party real addresses are introduced. Idempotent (post-update the
LIKE predicate matches nothing).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 07:13:02 +09:00
zio
0892bbfb07 feat(marketing): open EDM live send — double-confirm UI path (live=true)
Server EDM_TEST_MODE flipped to false (env, owner request), so the UI
gains an explicit live-send button: existing button stays as safe test
send, live send requires an audience-count warning confirm plus typing
LIVE. sendMut now carries {id, live}; i18n keys x4 locales.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 07:09:27 +09:00
zio
e47fb0f8aa fix(marketing): honest send-result wording — queued counts, mail_log is source of truth
sentCount tallies async queue submissions, so SMTP failures (e.g. the
2026-07-14 MailAuthenticationException) were invisible in the response.
Meta now says 'N queued, see send history' for both test and live paths.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 06:57:12 +09:00
zio
b3d3a5588c style(ui): finish Nifty component alignment + grey border token sweep (backlog 1.5/1.10)
Buttons gain Nifty size scale/icon-only/group/focus ring (additive,
md default unchanged); .kx-select gets kx caret + hover/focus/disabled
states; .kx-menu and .kx-list-group canonical patterns added. Undefined
/hardcoded border vars converge on --color-neutral-200 (theme-aware);
hallassign primary-hall accent moves off-palette blue to
--color-primary-600. Print border and recharts tooltip intentionally
excluded (documented exceptions).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 06:57:11 +09:00
zio
216f3720a1 feat(render): booth render history gallery (G-09)
History endpoint over render_job (DONE only) with covering index V54;
design studio shows a per-booth history gallery with watermark intact.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 06:26:52 +09:00
zio
23ff7d1799 feat(document): report PDF generation with embedded NanumGothic (G-05)
openhtmltopdf renderer with bundled NanumGothic for Korean text;
report authoring page gains PDF download wired to the new endpoint.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 06:26:52 +09:00
zio
660568f332 feat(cms): AI translate for multilingual content (Claude-routed)
CmsService translate path returns per-locale drafts with degraded
fallback; multilingual CMS page gets an AI translate action. Service
test updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 06:26:51 +09:00
zio
a836b79852 feat(account): my-page profile, password change and notification prefs (G-08)
AccountSettings endpoints (profile update, password change with current
-password check, notification preference toggles persisted via V55;
absent row = server defaults all-on). MyPage wires the settings UI.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 06:26:50 +09:00
zio
cf431a8809 feat(marketing): EDM real send with consent, unsubscribe and history (G-04)
Consent-filtered recipient resolution, SMTP send with test-mode ON by
default (EDM_TEST_MODE, campaign cap, per-minute rate), opaque
unsubscribe tokens with a public unsubscribe endpoint (no PII in
URLs/logs), and per-campaign send history via V53.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 06:26:32 +09:00
zio
0922e5660b feat(search): AI natural-language search over work data (grounded)
SearchAiService interprets the query via AiTextRouter and grounds
results on existing search providers; degraded fallback keeps plain
search working when AI is unavailable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 06:26:31 +09:00
zio
ef7400632e feat(meeting): audio upload + STT + AI minutes generation (G-06)
Meeting recording upload (<=20MB, multipart cap raised to 25MB),
configurable on-prem whisper STT (empty URL = degraded fallback),
Claude-routed minutes generation with action-item drafts, transcript
persisted via V52 for re-generation. Frontend meeting page wires the
record->transcribe->minutes flow (shared workAiApi client).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 06:26:30 +09:00
zio
3c8058546e fix(ui): stop table/grid clipping — min-width:0 + overflow-x sweep
Root cause: flex/grid children default min-width:auto let wide tables
blow out their track instead of scrolling, and .kx-dash__table-wrap
clipped with overflow:hidden. Converge the fix on the canonical
wrappers (.kx-table-scroll, .kx-dt) plus four screens lacking a scroll
wrapper (dashboard, admin matrix, settlement modal/report, hallassign
quote).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 02:25:18 +09:00
zio
a3fdb62fc6 feat(shell): left-nav menu search (UIWS NavSearch pattern) + accordion alignment
Adds a menu search box above the nav (match-highlight, Escape/clear
restores the accordion, track/admin gates preserved). Single-open
accordion with route-driven active group confirmed per owner request.
i18n keys shell.menu.search.* added across ko/en/ja/zh.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 02:25:17 +09:00
zio
3860e7e88a fix(auth): rehydrate session store on refresh (empty workspaces broke event-scoped screens)
Token lives in sessionStorage but user/workspaces existed only in the
zustand store, so any full reload left workspaces=[] and every
event-scoped screen fell to 'select an event' with an empty selector.
RequireAuth now restores /api/auth/me + /api/auth/workspaces once when
authenticated with an empty store, and logs out on 401.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 02:25:17 +09:00
zio
ecc00f8739 fix(system): cast null-check params to ::text in SysMessageMapper (PG $2 type inference 500)
PostgreSQL cannot infer the type of a bare bind in '(? IS NULL OR col = ?)',
failing GET /api/admin/messages with BadSqlGrammarException. Cast the
null-check occurrence to ::text (findAll category/locale, delete locale).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 02:02:31 +09:00
zio
1d46da8398 fix(ticket): escape <= in TicketMapper.xml SELECTs (boot crash, stale-jar rollback)
Unescaped <= at findProducts/findProduct broke SqlSessionFactory XML
parsing, crashing every new jar at startup; deploy rolled back to the
pre-V50 jar, so V50/V51 never reached prod and the admin demo account
lost event membership again (floorplan menu fell back to /home).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 01:51:47 +09:00
zio
1e349aa319 fix(seed): give admin demo event memberships (scoped menu home-fallback)
Floorplan/dashboard scoped menu resolves the target event from the
user workspaces; admin had zero event_member rows so clicks silently
landed on /home (perceived broken link). Idempotent V51 enrolls admin
as ORGANIZER of e-2026-live and e-2026-smf.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 00:25:25 +09:00
zio
8943c806ee feat(ticket): public ticket booking/lookup domain with mock PG (GAP G-02)
V50 ticket_product/ticket_order/ticket_issue (tenant-leading composite
PK, e-2026-live demo seeds). Public API: product list with server-side
remaining/sale-window, transactional order flow with conditional stock
decrement (oversell-safe) + MockPaymentGateway adapter, hash-verified
lookup returning masked PII only. PublicTicketPage wired via
react-query (degraded sample fallback retained); ticket.* i18n x4.
Mark G-02 resolved in GAP_AUDIT.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 00:25:24 +09:00
zio
0f91dcf4ae feat(ai): ReRoomAI image-to-image booth photo restyling (M5 pipeline reuse)
Reference photo upload (magic-byte check, 10MB, server-named files) +
reroom render job on the existing RenderJob queue/callback/WS pipeline.
Worker gains R1 reroom mode: 4-part prompt with fixed preserve-lock
(architecture + camera perspective) and style dictionary (6 styles,
JSON single source); NL instruction injects into replace-part only.
Booth Design Studio gets a photo-mockup section with client 1024px
downscale, style cards and Before/After slider (watermark enforced).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 00:25:23 +09:00
zio
ba34abaafe feat(ai): natural-language auto-layout interpret + per-option AI summary (M2)
POST .../auto-generate/interpret parses NL conditions into a clamped
AutoLayoutRequest via AiTextRouter (Claude, injection-guarded JSON-only
prompt; degraded:true fallback keeps manual form authoritative).
auto-generate?ai=true attaches metric-grounded pros/cons per option
(generation never blocked by AI failure). AutoLayoutDialog gains an NL
input bar + interpreted-note + AI summary cards with WISE AI label.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 00:24:56 +09:00
zio
fe6757f00a docs(web): fix stale backend-not-implemented comments (GAP hygiene item)
auction/visitor/marketing sample data + cms.css headers now state the
real wiring status (live API primary, samples are degraded fallback
only; G-04 SMTP follow-up noted). Mark hygiene item resolved in
GAP_AUDIT.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 23:48:03 +09:00
zio
465ebd8e19 feat(web): apply KxDataTable to holiday/program/ruleset admin (screens 5-7)
Replace hand-rolled zebra tables with KxDataTable (sort/filter/CSV,
per-column control) on HolidayAdminPage, ProgramAdminPage and
RulesetVersionsPage. Manage columns excluded from CSV/sort/search;
empty states delegated to the table.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 23:47:37 +09:00
zio
9144186e8a fix(web): drop unused EmptyState import in TenantAdminPage (build break)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 23:47:23 +09:00
zio
a6098ef002 feat(web): wire TenantAdminPage to live tenant API (GAP G-01)
Replace hardcoded TENANTS array and disabled add button with live
GET/POST /api/admin/tenants via react-query: list states, create modal
(server-authoritative validation mirrored client-side), KxDataTable
search/sort/CSV. tenant.* i18n 17 keys x 4 locales (parity kept).
Mark G-01 resolved in GAP_AUDIT.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 23:25:35 +09:00
zio
d19b74207b feat(web): apply KxDataTable to common-code admin (4th screen, per-column control demo)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 05:38:57 +09:00
zio
39660772ab fix(web): full-bleed responsive sweep across all screens (task #39)
Normalize 13 custom page roots to the .kx-page canon (flex:1, min-width:0,
overflow-y:auto) fixing right-side dead space and bottom clipping inside the
shell content flexbox; add missing narrow-width breakpoints to settlement KPIs
and hall-assignment forms. No visual redesign - WISE shell and kx tokens intact.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 05:31:31 +09:00
zio
ecf60aac1d feat(web): tabulator data table + breadcrumb/404 navigation + message-template admin
- KxDataTable: in-house tabulator features (sort/filter/pagination/CSV UTF-8 BOM)
  on canonical .kx-table; applied to exhibitors, lead scoring, visitor registration
- Breadcrumb in shell content top (menu-IA-aligned trails, detail->list return),
  NotFoundPage wired to router catch-all with role-aware home return
- MessageAdminPage (/admin/messages): V48 sys_message CRUD + {key} placeholder
  render preview, wired to shell menu / breadcrumb / MDI labels / admin dashboard
- i18n: datatable/breadcrumb/notFound/msg namespaces, ko-en-zh-ja parity kept

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 05:16:35 +09:00
zio
37aeebdd28 솔루션명 수정 2026-07-13 04:23:07 +09:00
zio
0add2cd417 fix(web): restore public header login + track-tab icons/tooltips, visitor CTA to /tickets/lookup, accent-button white-text sweep
- PublicShell: track tabs get icons + title tooltips (right-aligned), login link restored at >=768px
- VisitorTrackPage: wayfinding/checkin CTAs point to #guide/#transport//tickets/lookup instead of /login
- accent buttons: enforce --color-on-accent (white text) across approval/docs/home/movein/schedule/work/public

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 00:29:12 +09:00
zio
f3b800f9be fix(auth): grant global ADMIN hall-manager scope to resolve 403 on event-scoped APIs
KintexPrincipal.hasAccess/roleFor ignored global role_code=ADMIN, so
admin@ users got 403 on all event-scoped endpoints. Add isAdmin() and
treat ADMIN as hall-manager equivalent (all-event read + approve).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 00:15:25 +09:00
zio
c77cba7c5b feat(web): home calendar holiday markers + unify public header into single frame
- HomePage: wire fetchHolidaySet, is-holiday cell class + holiday name label
- home.css: is-holiday red daynum, kx-home__cal-holiday-name, neutral-100 grid lines
- PublicShell: absorb 3-track switcher into single top header (COEX 1-frame), drop dark topbar
- public.css: remove .kxp-topbar styles, tracktabs bar/menu variants

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 23:56:59 +09:00
zio
a5a78f1ea1 feat(web): exhibitor mgmt, Nifty detail views, app-download QR, settings customizer, home todos + i18n
- exhibitors: organizer exhibitor roster page + read-only backend (Controller/Service/@Mapper/dto), /exhibitors route
- detail views: Nifty blog-style .kx-detailview for auction & review-details (+shared.css)
- app download: AppQrCodePage visual/class hardening
- settings customizer: customizerStore + SettingsCustomizer panel (density/accent), AppShell gear wiring, menu-fallback removal
- home: todos aggregation (8 sources) HomePage/homeApi/HomeMapper/HomeService
- i18n: merge 112 new keys across ko/en/zh/ja (parity 0 missing)

No new migrations (read-only queries); Flyway stays at V49.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 23:36:02 +09:00
zio
55a3114141 feat(login): add password show/hide (eye) toggle on login form
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 22:31:34 +09:00
zio
7316cd99c5 feat(public): rotating 5-slide hero backdrop with real photos on public tracks
Add PublicHeroSlides cross-fade component (5 real JPGs) wired into
gateway/visitor/business/agency hero backdrops. Rotation handled by
usePublicMotion ([data-hero-slides], reduced-motion aware); .pub-hero__slides
layering + is-active transition in public.css. Graceful gradient fallback on
image load error.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 22:09:35 +09:00
zio
c595560d82 fix(system/message): avoid bean-name collision with existing work/message module
Existing com.zioinfo.kintex.work.message.{MessageController,MessageService,MessageMapper}
share default bean names with the new system/message beans, causing
ConflictingBeanDefinitionException at startup (health-check fail -> rollback).
- rename mapper interface MessageMapper -> SysMessageMapper (MyBatis bean name can't
  be overridden by annotation value)
- explicit bean names: @RestController("sysMessageController"), @Service("sysMessageService")
No request-path change (new: /api/admin/messages, /api/messages/{code}/render).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 21:51:24 +09:00
zio
276293ebe7 feat(system,ui): message-template admin (V48) + empty-table demo seed (V49) + Nifty design/token alignment & public card visuals
- system/message: sys_message template CRUD + {key} render API (ADMIN-gated, render for authed)
- V48: sys_message table + 36 seeded templates (9 codes x ko/en/zh/ja), idempotent upsert
- V49: backfill 12 empty domain tables (render_job, cms_media, logistics_*, mail_log,
  edm_followup, webhook_*, login_history, sys_role_menu, audit_log); idempotent guards.
  followup ON CONFLICT targets business key (event_id, lead_id) to skip pre-seeded rows
- frontend: Nifty token/typography sweep (--fs-*/--fw-*), public e-card 3:4 media + cover fit,
  footer copy update across ko/en/zh/ja

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 21:40:38 +09:00
zio
3077cb04f5 feat(public,settlement): coex-style public visuals + Nifty calendar + local poster assets + e-2026-live close-loop demo (V46,V47)
- public: motion hooks (usePublicMotion), gateway/track/shell visual refresh, stat-band white->on-accent contrast fix
- schedule: Nifty calendar restyle (neutral cell borders, today warning-bg)
- settlement: card padding fix
- i18n: +public visual keys (ko/en/zh/ja)
- backend: PublicEventDto.posterUrl (additive, non-breaking) via PublicSiteMapper/Service
- db: V46 rewires event.poster_url to local /media/posters assets (34 imgs); V47 seeds e-2026-live close-loop (invoice/payment/tax/refund, auction/bid/award, visitor/lead, edm/sponsorship)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 20:59:59 +09:00
zio
55e27b3309 fix(theme): white text on colored buttons/badges in dark mode (--color-on-accent)
Root cause: dark theme remaps --color-white to --dk-surface (a dark color),
so every 'color: var(--color-white)' on a colored background (primary/error/
success buttons, badges, chips, hero CTAs) rendered dark/invisible text in
dark mode (e.g. '등록 신청' blue button showed navy text).

Add always-white --color-on-accent token and repoint 77 text-color usages
across 28 files to it. Background/border usages of --color-white untouched
(they legitimately flip to dark surface). Full-CSS audit applied.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 20:34:30 +09:00
zio
87f310f40a fix(brand): replace Tomcat default favicon.ico with KINTEX-branded icon
Root cause of persistent Tomcat cat favicon: public/favicon.ico was the
Tomcat default (21630 bytes), shipped by every build; browsers prefer
/favicon.ico over the correct favicon.png. Regenerate favicon.ico from the
KINTEX wordmark PNG (multi-size 16/32/48/64) and bump cache-bust to v3.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 20:10:56 +09:00
zio
a2b2bd9110 feat(ui): add line shield-check icon to 2FA challenge panel
- icons.tsx: new IconShieldCheck (stroke/line, 24 viewBox standard)
- OtpChallengePanel: shield badge above 2차 인증 title (was icon-less/bare)
- login.css: .kx-otp__badge circular primary-tinted badge

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 20:05:01 +09:00