diff --git a/src/main/resources/static/sass/components/_apikey-common.scss b/src/main/resources/static/sass/components/_apikey-common.scss new file mode 100644 index 0000000..bfaf6e9 --- /dev/null +++ b/src/main/resources/static/sass/components/_apikey-common.scss @@ -0,0 +1,556 @@ +@charset "utf-8"; + +// ============================================================================= +// API Key Common Styles +// Shared styles across apikey-list, apikey-detail, apikey-register pages +// ============================================================================= + +// ----------------------------------------------------------------------------- +// Common Variables +// ----------------------------------------------------------------------------- +$apikey-bg-color: #f6f9fb; +$apikey-primary-blue: #0049b4; +$apikey-secondary-blue: #3ba4ed; +$apikey-text-secondary: #6e7780; +$apikey-text-dark: #212529; +$apikey-border-color: #dadada; + +// ----------------------------------------------------------------------------- +// Common Container +// ----------------------------------------------------------------------------- +.apikey-container { + max-width: $container-max-width; + margin: 0 auto; + padding: 60px $spacing-lg 80px; + + @include respond-to('sm') { + padding: 40px $spacing-md 60px; + } +} + +// ----------------------------------------------------------------------------- +// Common Section Box (Background container) +// ----------------------------------------------------------------------------- +.apikey-section-box { + background-color: $apikey-bg-color; + border-radius: $border-radius-lg; + padding: 30px 45px; + + @include respond-to('sm') { + padding: $spacing-lg; + } +} + +// ----------------------------------------------------------------------------- +// Common Title Bar +// ----------------------------------------------------------------------------- +.apikey-title-bar { + background-color: $apikey-bg-color; + border-radius: $border-radius-lg; + padding: 14px 45px; + margin-bottom: 30px; + + @include respond-to('sm') { + padding: 12px $spacing-lg; + } + + .apikey-title { + font-family: $font-family-primary; + font-size: 28px; + font-weight: $font-weight-bold; + color: $text-dark; + margin: 0; + + @include respond-to('sm') { + font-size: 22px; + } + } + + .apikey-subtitle { + font-size: 16px; + font-weight: $font-weight-regular; + color: #515151; + + @include respond-to('sm') { + font-size: 14px; + } + } +} + +// ----------------------------------------------------------------------------- +// Common Status Badge +// ----------------------------------------------------------------------------- +.apikey-status-badge { + display: inline-flex; + align-items: center; + justify-content: center; + padding: 5px 14px; + border-radius: 40px; + font-family: $font-family-primary; + font-size: 13px; + font-weight: $font-weight-bold; + color: $white; + white-space: nowrap; + + &.status-pending { + background-color: #8c959f; + } + + &.status-approved, + &.status-active { + background-color: $apikey-primary-blue; + } + + &.status-changing { + background-color: #88a5f3; + } + + &.status-inactive, + &.status-rejected { + background-color: #dc3545; + } + + // Alternative light style (for detail pages) + &.status-light { + &.status-pending { + background-color: #FFF3CD; + color: #856404; + } + + &.status-approved, + &.status-active { + background-color: #D4EDDA; + color: #155724; + } + + &.status-rejected, + &.status-inactive { + background-color: #F8D7DA; + color: #721C24; + } + } +} + +// ----------------------------------------------------------------------------- +// Common Status Indicator (with dot) +// ----------------------------------------------------------------------------- +.apikey-status-indicator { + display: inline-flex; + align-items: center; + gap: $spacing-sm; + padding: $spacing-xs $spacing-md; + border-radius: $border-radius-xl; + font-size: $font-size-sm; + font-weight: $font-weight-semibold; + + .status-dot { + width: 8px; + height: 8px; + border-radius: $border-radius-circle; + background-color: currentColor; + } + + &.status-active { + background-color: #D4EDDA; + color: #155724; + } + + &.status-inactive { + background-color: #F8D7DA; + color: #721C24; + } +} + +// ----------------------------------------------------------------------------- +// Common App Icon +// ----------------------------------------------------------------------------- +.apikey-icon-display { + width: 120px; + height: 120px; + + &.icon-sm { + width: 70px; + height: 70px; + + @include respond-to('sm') { + width: 60px; + height: 60px; + } + } + + &.icon-md { + width: 100px; + height: 100px; + } +} + +.apikey-icon-image { + width: 100%; + height: 100%; + object-fit: cover; + border-radius: $border-radius-lg; + border: 2px solid $border-gray; +} + +.apikey-icon-placeholder { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + background-color: #e9ecef; + border-radius: $border-radius-lg; + color: #868e96; + font-size: 48px; + + &.placeholder-sm { + font-size: 24px; + } +} + +// ----------------------------------------------------------------------------- +// Common Empty State +// ----------------------------------------------------------------------------- +.apikey-empty-state { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 80px $spacing-lg; + text-align: center; + + .empty-icon { + font-size: 64px; + margin-bottom: $spacing-lg; + opacity: 0.5; + } + + h3 { + font-family: $font-family-primary; + font-size: $font-size-xl; + font-weight: $font-weight-bold; + color: $text-dark; + margin: 0 0 $spacing-md; + } + + p { + font-family: $font-family-primary; + font-size: $font-size-base; + color: $apikey-text-secondary; + margin: 0; + } +} + +// ----------------------------------------------------------------------------- +// Common Action Button +// ----------------------------------------------------------------------------- +.apikey-action-btn { + display: inline-flex; + align-items: center; + justify-content: center; + width: 220px; + height: 60px; + border: none; + border-radius: $border-radius-lg; + font-family: $font-family-primary; + font-size: 18px; + font-weight: $font-weight-bold; + cursor: pointer; + text-decoration: none; + transition: background-color 0.2s ease, transform 0.2s ease; + + &:hover { + transform: translateY(-2px); + } + + &:active { + transform: translateY(0); + } + + &.btn-primary { + background-color: $apikey-primary-blue; + color: $white; + + &:hover { + background-color: #003a91; + } + } + + &.btn-secondary { + background-color: #e5e7eb; + color: #5f666c; + + &:hover { + background-color: #d1d5db; + } + } + + &.btn-accent { + background-color: $apikey-secondary-blue; + color: $white; + + &:hover { + background-color: #2b94dd; + } + } + + @include respond-to('sm') { + width: 100%; + max-width: 300px; + height: 54px; + font-size: $font-size-base; + } +} + +// ----------------------------------------------------------------------------- +// Common Copy Button +// ----------------------------------------------------------------------------- +.apikey-btn-copy { + display: inline-flex; + align-items: center; + gap: $spacing-xs; + padding: 6px 12px; + background: $white; + border: 1px solid $border-gray; + border-radius: $border-radius-sm; + font-size: $font-size-sm; + color: $text-dark; + cursor: pointer; + transition: $transition-base; + + svg { + width: 16px; + height: 16px; + } + + &:hover { + background: $primary-blue; + border-color: $primary-blue; + color: $white; + } + + @media (max-width: $breakpoint-sm) { + align-self: stretch; + justify-content: center; + } +} + +// ----------------------------------------------------------------------------- +// Common Detail Section +// ----------------------------------------------------------------------------- +.apikey-detail-section { + background: $white; + border-radius: $border-radius-lg; + padding: $spacing-4xl; + margin-bottom: $spacing-lg; + box-shadow: $shadow-md; + + @media (max-width: $breakpoint-sm) { + padding: $spacing-xl; + } + + .section-title { + font-size: $font-size-xl; + font-weight: $font-weight-bold; + color: $text-dark; + margin-bottom: $spacing-lg; + padding-bottom: $spacing-md; + } +} + +// ----------------------------------------------------------------------------- +// Common Detail Grid +// ----------------------------------------------------------------------------- +.apikey-detail-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: $spacing-lg; + + @media (max-width: $breakpoint-sm) { + grid-template-columns: 1fr; + } +} + +.apikey-detail-item { + display: flex; + flex-direction: column; + gap: $spacing-sm; + + &.full-width { + grid-column: 1 / -1; + } + + .detail-label { + font-size: $font-size-sm; + font-weight: $font-weight-semibold; + color: $text-gray; + } + + .detail-value { + font-size: $font-size-base; + color: $text-dark; + word-break: break-word; + } +} + +// ----------------------------------------------------------------------------- +// Common IP Tag +// ----------------------------------------------------------------------------- +.apikey-ip-list { + display: flex; + flex-wrap: wrap; + gap: $spacing-sm; +} + +.apikey-ip-tag { + display: inline-block; + padding: $spacing-xs $spacing-md; + background-color: $light-bg; + color: $secondary-blue; + border-radius: $border-radius-sm; + font-size: $font-size-sm; + font-family: $font-family-mono; +} + +// ----------------------------------------------------------------------------- +// Common Credential Code +// ----------------------------------------------------------------------------- +.apikey-credential-code { + display: inline-block; + padding: $spacing-sm $spacing-md; + background-color: $gray-bg; + border: 1px solid $border-gray; + border-radius: $border-radius-sm; + font-family: $font-family-mono; + font-size: $font-size-sm; + color: $secondary-blue; +} + +// ----------------------------------------------------------------------------- +// Common Secret Box +// ----------------------------------------------------------------------------- +.apikey-secret-box { + display: flex; + align-items: center; + gap: $spacing-md; + + @media (max-width: $breakpoint-sm) { + flex-direction: column; + align-items: flex-start; + } +} + +// ----------------------------------------------------------------------------- +// Common API List Item +// ----------------------------------------------------------------------------- +.apikey-api-list { + display: flex; + flex-direction: column; + gap: $spacing-sm; +} + +.apikey-api-item { + display: flex; + align-items: center; + gap: $spacing-md; + padding: $spacing-md $spacing-lg; + background: $white; + border: 1px solid $border-gray; + border-radius: $border-radius-md; + transition: all 0.2s; + + &:hover { + border-color: $primary-blue; + box-shadow: $shadow-sm; + } + + @media (max-width: $breakpoint-sm) { + padding: $spacing-md; + gap: $spacing-sm; + } + + .api-method { + display: inline-block; + padding: $spacing-xs $spacing-md; + border-radius: $border-radius-sm; + font-size: $font-size-sm; + font-weight: $font-weight-bold; + font-family: $font-family-mono; + min-width: 80px; + text-align: center; + + &.method-get { + background-color: #D1FAE5; + color: #065F46; + } + + &.method-post { + background-color: #DBEAFE; + color: #1E40AF; + } + + &.method-put { + background-color: #FEF3C7; + color: #92400E; + } + + &.method-delete { + background-color: #FEE2E2; + color: #991B1B; + } + + &.method-other { + background-color: $border-gray; + color: $text-dark; + } + } + + .api-name { + flex: 1; + font-size: $font-size-base; + font-weight: $font-weight-medium; + color: $text-dark; + margin: 0; + } + + .api-status { + padding: $spacing-xs $spacing-md; + border-radius: $border-radius-lg; + font-size: $font-size-sm; + font-weight: $font-weight-semibold; + + &.status-pending { + background-color: #FFF3CD; + color: #856404; + } + + &.status-active { + background-color: #D4EDDA; + color: #155724; + } + } +} + +// ----------------------------------------------------------------------------- +// Common Form Actions +// ----------------------------------------------------------------------------- +.apikey-form-actions { + display: flex; + justify-content: center; + gap: $spacing-md; + flex-wrap: wrap; + margin-top: $spacing-4xl; + padding-top: $spacing-4xl; + border-top: 1px solid $border-gray; + + @media (max-width: $breakpoint-sm) { + flex-direction: column; + align-items: stretch; + } + + .btn { + @media (max-width: $breakpoint-sm) { + width: 100%; + } + } +} diff --git a/src/main/resources/static/sass/pages/_apikey-list.scss b/src/main/resources/static/sass/pages/_apikey-list.scss new file mode 100644 index 0000000..195b700 --- /dev/null +++ b/src/main/resources/static/sass/pages/_apikey-list.scss @@ -0,0 +1,172 @@ +@charset "utf-8"; + +// ==================================== +// API Key List Page Styles +// For apiKeyList.html +// Uses common styles from components/_apikey-common.scss +// ==================================== + +// App Management Container - extends common +.app-management-container { + @extend .apikey-container; +} + +// App List Title Section - extends common +.app-list-title-section { + @extend .apikey-title-bar; +} + +.app-list-title { + font-family: $font-family-primary; + font-size: 28px; + font-weight: $font-weight-bold; + color: $text-dark; + margin: 0; + + @include respond-to('sm') { + font-size: 22px; + } +} + +// App List Container - extends common +.app-list-container { + @extend .apikey-section-box; + min-height: 400px; +} + +// App List Item +.app-list-item { + display: flex; + align-items: center; + gap: $spacing-lg; + padding: 40px 0; + border-bottom: 1px solid #e0e0e0; + text-decoration: none; + color: inherit; + transition: background-color 0.2s ease; + + &:last-child { + border-bottom: none; + } + + &:hover { + background-color: rgba(255, 255, 255, 0.5); + margin: 0 -20px; + padding-left: 20px; + padding-right: 20px; + border-radius: $border-radius-md; + } + + @include respond-to('sm') { + flex-direction: column; + align-items: flex-start; + padding: 30px 0; + gap: $spacing-md; + + &:hover { + margin: 0 -10px; + padding-left: 10px; + padding-right: 10px; + } + } +} + +// App Icon - uses common icon styles +.app-list-icon { + @extend .apikey-icon-display; + width: 70px; + height: 70px; + + @include respond-to('sm') { + width: 60px; + height: 60px; + } + + .app-icon-image { + @extend .apikey-icon-image; + border: none; + } + + .app-icon-placeholder { + @extend .apikey-icon-placeholder; + font-size: inherit; + } +} + +// App Info +.app-list-info { + display: flex; + flex-direction: column; + gap: 14px; + flex: 1; +} + +.app-list-header { + display: flex; + align-items: center; + gap: $border-radius-lg; + + @include respond-to('sm') { + flex-wrap: wrap; + gap: $spacing-sm; + } +} + +// Status Badge - extends common +.app-status-badge { + @extend .apikey-status-badge; +} + +// App Name +.app-list-name { + font-family: $font-family-primary; + font-size: 22px; + font-weight: $font-weight-bold; + color: $text-dark; + margin: 0; + + @include respond-to('sm') { + font-size: 18px; + } +} + +// App Description +.app-list-description { + font-family: $font-family-primary; + font-size: $font-size-base; + font-weight: $font-weight-regular; + color: #6e7780; + margin: 0; + line-height: 1.5; + + @include respond-to('sm') { + font-size: $font-size-sm; + } +} + +// Empty State - extends common +.app-list-empty { + @extend .apikey-empty-state; +} + +// Create App Button Wrapper +.app-create-button-wrapper { + display: flex; + justify-content: center; + margin-top: 60px; + + @include respond-to('sm') { + margin-top: 40px; + } +} + +// Create App Button - extends common +.btn-app-create { + @extend .apikey-action-btn; + background-color: #0049b4; + color: $white; + + &:hover { + background-color: #003a91; + } +}