diff --git a/Dockerfile b/Dockerfile index 893f241e..98c711ed 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,25 +8,55 @@ ARG mode=prod FROM node:24-alpine AS build-stage +# Add build dependencies and security updates +RUN apk update && \ + apk upgrade && \ + apk add --no-cache dumb-init + +# Use non-root user for security USER node WORKDIR /app +# Copy package files first for better layer caching COPY --chown=1000:1000 package*.json ./ -RUN npm ci + +# Install dependencies with npm ci for reproducible builds +# Use --no-audit to speed up the build +RUN npm ci --no-audit --no-fund && \ + npm cache clean --force + +# Copy source code COPY --chown=1000:1000 . . + +# Build the application RUN npm run build # Stage 2: Prepare the Node.js API -FROM node:23-alpine AS base-prod +FROM node:24-alpine AS base-prod + +# Add security updates and dumb-init for proper process handling +RUN apk update && \ + apk upgrade && \ + apk add --no-cache dumb-init curl && \ + # Add a non-privileged user for running the application + addgroup -g 1001 -S appgroup && \ + adduser -u 1001 -S appuser -G appgroup +# Set working directory and copy built application WORKDIR /app -COPY --chown=1000:1000 --from=build-stage /app/.output /app +COPY --chown=1001:1001 --from=build-stage /app/.output /app + +# Create a health check script +RUN echo '#!/bin/sh' > /healthcheck.sh && \ + echo 'curl -f http://localhost:${NITRO_PORT:-80}/api/health || exit 1' >> /healthcheck.sh && \ + chmod +x /healthcheck.sh # Expose the port your API will run on EXPOSE 80 # Set port to 80 for backwards compatibility -ENV NITRO_PORT=80 +ENV NITRO_PORT=80 \ + NODE_ENV=production # Re-map the environment variables for the Vue.js app for backwards compatibility RUN echo '#!/bin/sh' > /entrypoint.sh && \ @@ -41,34 +71,54 @@ RUN echo '#!/bin/sh' > /entrypoint.sh && \ echo 'export NUXT_SESSION_PASSWORD=${NUXT_SESSION_PASSWORD:-$NUXT_GITHUB_TOKEN$NUXT_GITHUB_TOKEN}' >> /entrypoint.sh && \ echo 'export NUXT_OAUTH_GITHUB_CLIENT_ID=${NUXT_OAUTH_GITHUB_CLIENT_ID:-$GITHUB_CLIENT_ID}' >> /entrypoint.sh && \ echo 'export NUXT_OAUTH_GITHUB_CLIENT_SECRET=${NUXT_OAUTH_GITHUB_CLIENT_SECRET:-$GITHUB_CLIENT_SECRET}' >> /entrypoint.sh && \ + # Set default theme to ensure consistent appearance + echo 'export NUXT_PUBLIC_DEFAULT_THEME=${NUXT_PUBLIC_DEFAULT_THEME:-dark}' >> /entrypoint.sh && \ # Conditionally set NUXT_PUBLIC_USING_GITHUB_AUTH if GITHUB_CLIENT_ID is provided echo 'if [ -n "$GITHUB_CLIENT_ID" ]; then' >> /entrypoint.sh && \ echo 'export NUXT_PUBLIC_USING_GITHUB_AUTH=true' >> /entrypoint.sh && \ echo 'fi' >> /entrypoint.sh && \ - echo 'node /app/server/index.mjs' >> /entrypoint.sh && \ + echo 'exec dumb-init -- node /app/server/index.mjs' >> /entrypoint.sh && \ chmod +x /entrypoint.sh +# Configure Docker health check +HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 CMD ["/healthcheck.sh"] -USER node -ENTRYPOINT [ "/entrypoint.sh" ] +# Set proper permissions and switch to non-root user +RUN chown -R 1001:1001 /app +USER appuser +ENTRYPOINT ["/entrypoint.sh"] #----------------------------------- PW layer - not used in production FROM mcr.microsoft.com/playwright:v1.49.1 AS base-playwright WORKDIR /pw +# Install only necessary packages and clean up to reduce image size RUN apt-get update && \ - apt-get install -y --no-install-recommends gettext-base && \ + apt-get install -y --no-install-recommends gettext-base curl dumb-init && \ apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -COPY --chown=1000:1000 --from=base-prod /app /app -COPY --chown=1000:1000 e2e-tests ./e2e-tests -COPY --chown=1000:1000 playwright.config.ts playwright.docker.config.ts tsconfig.json package*.json ./ - -RUN npm install --only=dev - -ENTRYPOINT [ "npx", "playwright", "test", "-c", "playwright.docker.config.ts" ] + rm -rf /var/lib/apt/lists/* && \ + # Create a non-root user for running tests + groupadd -g 1001 pwuser && \ + useradd -u 1001 -g pwuser -m pwuser + +# Copy application and test files +COPY --chown=1001:1001 --from=base-prod /app /app +COPY --chown=1001:1001 e2e-tests ./e2e-tests +COPY --chown=1001:1001 playwright.config.ts playwright.docker.config.ts tsconfig.json package*.json ./ + +# Install only dev dependencies and clean cache +RUN npm install --only=dev && \ + npm cache clean --force + +# Create a wrapper script for better process handling +RUN echo '#!/bin/sh' > /entrypoint-pw.sh && \ + echo 'exec dumb-init -- npx playwright test -c playwright.docker.config.ts "$@"' >> /entrypoint-pw.sh && \ + chmod +x /entrypoint-pw.sh + +# Switch to non-root user for security +USER pwuser +ENTRYPOINT ["/entrypoint-pw.sh"] #----------------------------------- FROM base-${mode} AS final diff --git a/app/assets/background.css b/app/assets/background.css new file mode 100644 index 00000000..4166ec54 --- /dev/null +++ b/app/assets/background.css @@ -0,0 +1,147 @@ +/* Background styling for the entire application */ +body.v-theme--dark { + background-color: #121212; + background-image: + radial-gradient(circle at 10% 20%, rgba(100, 216, 203, 0.05) 0%, transparent 30%), + radial-gradient(circle at 90% 80%, rgba(156, 100, 216, 0.05) 0%, transparent 30%), + radial-gradient(circle at 50% 50%, rgba(139, 233, 253, 0.03) 0%, transparent 50%); + background-attachment: fixed; + min-height: 100vh; +} + +body.v-theme--light { + background-color: #F5F7FA; + background-image: + radial-gradient(circle at 10% 20%, rgba(38, 166, 154, 0.05) 0%, transparent 30%), + radial-gradient(circle at 90% 80%, rgba(123, 31, 162, 0.05) 0%, transparent 30%), + radial-gradient(circle at 50% 50%, rgba(77, 208, 225, 0.03) 0%, transparent 50%); + background-attachment: fixed; + min-height: 100vh; +} + +/* Add subtle animated gradient to the main content area */ +.v-main { + position: relative; + overflow: hidden; +} + +.v-theme--dark .v-main::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(135deg, + rgba(100, 216, 203, 0.02) 0%, + rgba(139, 233, 253, 0.02) 50%, + rgba(156, 100, 216, 0.02) 100%); + background-size: 400% 400%; + animation: gradientAnimation 15s ease infinite; + z-index: -1; +} + +.v-theme--light .v-main::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(135deg, + rgba(38, 166, 154, 0.02) 0%, + rgba(77, 208, 225, 0.02) 50%, + rgba(123, 31, 162, 0.02) 100%); + background-size: 400% 400%; + animation: gradientAnimation 15s ease infinite; + z-index: -1; +} + +@keyframes gradientAnimation { + 0% { background-position: 0% 50%; } + 50% { background-position: 100% 50%; } + 100% { background-position: 0% 50%; } +} + +/* Add subtle grid pattern overlay */ +.v-theme--dark .v-main::after { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-image: + linear-gradient(rgba(255, 255, 255, 0.01) 1px, transparent 1px), + linear-gradient(90deg, rgba(255, 255, 255, 0.01) 1px, transparent 1px); + background-size: 20px 20px; + z-index: -1; +} + +.v-theme--light .v-main::after { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-image: + linear-gradient(rgba(0, 0, 0, 0.01) 1px, transparent 1px), + linear-gradient(90deg, rgba(0, 0, 0, 0.01) 1px, transparent 1px); + background-size: 20px 20px; + z-index: -1; +} + +/* Add glow effects to cards and important elements */ +.v-theme--dark .v-card { + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25) !important; +} + +.v-theme--dark .v-card:hover { + box-shadow: 0 8px 30px rgba(100, 216, 203, 0.15) !important; +} + +.v-theme--light .v-card { + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1) !important; +} + +.v-theme--light .v-card:hover { + box-shadow: 0 8px 30px rgba(38, 166, 154, 0.15) !important; +} + +/* Custom scrollbar for the entire site */ +.v-theme--dark ::-webkit-scrollbar { + width: 10px; + height: 10px; +} + +.v-theme--dark ::-webkit-scrollbar-track { + background: #1a1a1a; +} + +.v-theme--dark ::-webkit-scrollbar-thumb { + background: linear-gradient(to bottom, #64D8CB, #9C64D8); + border-radius: 5px; +} + +.v-theme--dark ::-webkit-scrollbar-thumb:hover { + background: linear-gradient(to bottom, #8BE9FD, #64D8CB); +} + +.v-theme--light ::-webkit-scrollbar { + width: 10px; + height: 10px; +} + +.v-theme--light ::-webkit-scrollbar-track { + background: #f1f1f1; +} + +.v-theme--light ::-webkit-scrollbar-thumb { + background: linear-gradient(to bottom, #26A69A, #7B1FA2); + border-radius: 5px; +} + +.v-theme--light ::-webkit-scrollbar-thumb:hover { + background: linear-gradient(to bottom, #4DD0E1, #26A69A); +} \ No newline at end of file diff --git a/app/assets/data-table-fix-v2.css b/app/assets/data-table-fix-v2.css new file mode 100644 index 00000000..21ca50d0 --- /dev/null +++ b/app/assets/data-table-fix-v2.css @@ -0,0 +1,69 @@ +/* Target the specific white background in the dropdown */ +.v-list-item__underlay { + background-color: transparent !important; + display: none !important; +} + +/* Target all possible elements that could have a white background */ +.v-list-item__bg { + background-color: transparent !important; + display: none !important; +} + +/* Target the ripple effect which might be causing the white background */ +.v-ripple__container { + display: none !important; +} + +/* Target any other potential elements */ +.v-list-item .v-overlay__content, +.v-list-item .v-overlay, +.v-list-item .v-ripple, +.v-list-item .v-ripple__animation { + background-color: transparent !important; + display: none !important; +} + +/* Force all list items to have the correct background */ +.v-list-item { + background-color: #1E1E1E !important; +} + +/* Force selected items to have the correct background */ +.v-list-item--active { + background-color: #333333 !important; +} + +/* Target the specific element that might be causing the white background */ +.v-list-item__overlay { + background-color: transparent !important; + display: none !important; +} + +/* Target the v-select dropdown specifically */ +.v-select__content .v-list, +.v-select__content .v-list-item, +.v-select__content .v-list-item__overlay, +.v-select__content .v-list-item__underlay { + background-color: #1E1E1E !important; +} + +.v-select__content .v-list-item--active, +.v-select__content .v-list-item--active .v-list-item__overlay, +.v-select__content .v-list-item--active .v-list-item__underlay { + background-color: #333333 !important; +} + +/* Target the white box specifically */ +.v-theme--light.v-list-item .v-list-item__overlay { + background-color: transparent !important; + display: none !important; +} + +/* Target the white box in the data table footer */ +.v-data-table-footer .v-list-item__overlay, +.v-data-table-footer .v-list-item__underlay, +.v-data-table-footer .v-list-item__bg { + background-color: transparent !important; + display: none !important; +} \ No newline at end of file diff --git a/app/assets/data-table-fix-v3.css b/app/assets/data-table-fix-v3.css new file mode 100644 index 00000000..9e21871d --- /dev/null +++ b/app/assets/data-table-fix-v3.css @@ -0,0 +1,164 @@ +/* Direct targeting of the white background in the dropdown */ + +/* Target the specific element causing the white background */ +.v-list-item__underlay { + background-color: transparent !important; + opacity: 0 !important; +} + +/* Target the specific element in the dropdown */ +.v-select__content .v-list-item__underlay { + background-color: transparent !important; + opacity: 0 !important; +} + +/* Target the specific element in the data table footer */ +.v-data-table-footer .v-select__content .v-list-item__underlay { + background-color: transparent !important; + opacity: 0 !important; +} + +/* Target the specific element in the data table footer */ +.v-data-table-footer__items-per-page .v-select__content .v-list-item__underlay { + background-color: transparent !important; + opacity: 0 !important; +} + +/* Target all list items in the dropdown */ +.v-list-item { + --v-theme-overlay-multiplier: 0 !important; + --v-activated-opacity: 0 !important; + --v-selected-opacity: 0 !important; + --v-hover-opacity: 0 !important; + --v-focus-opacity: 0 !important; + --v-pressed-opacity: 0 !important; + --v-dragged-opacity: 0 !important; +} + +/* Target the specific element causing the white background */ +.v-theme--light .v-list-item__underlay, +.v-theme--dark .v-list-item__underlay { + background-color: transparent !important; + opacity: 0 !important; +} + +/* Target the specific element causing the white background */ +.v-list-item__overlay { + background-color: transparent !important; + opacity: 0 !important; +} + +/* Target the specific element causing the white background */ +.v-list-item--active .v-list-item__overlay, +.v-list-item--selected .v-list-item__overlay { + background-color: transparent !important; + opacity: 0 !important; +} + +/* Force background colors for list items */ +.v-list-item { + background-color: #1E1E1E !important; +} + +.v-list-item--active, +.v-list-item--selected { + background-color: #333333 !important; +} + +/* Target the specific element causing the white background */ +.v-list-item .v-list-item__underlay::before, +.v-list-item .v-list-item__underlay::after { + background-color: transparent !important; + opacity: 0 !important; + display: none !important; +} + +/* Target the specific element causing the white background */ +.v-list-item .v-list-item__overlay::before, +.v-list-item .v-list-item__overlay::after { + background-color: transparent !important; + opacity: 0 !important; + display: none !important; +} + +/* Target the specific element causing the white background */ +.v-list-item__content { + background-color: transparent !important; +} + +/* Target the specific element causing the white background */ +.v-list-item__prepend { + background-color: transparent !important; +} + +/* Target the specific element causing the white background */ +.v-list-item__append { + background-color: transparent !important; +} + +/* Target the specific element causing the white background */ +.v-list-item__spacer { + background-color: transparent !important; +} + +/* Target the specific element causing the white background */ +.v-list-item__base { + background-color: transparent !important; +} + +/* Target the specific element causing the white background */ +.v-list-item__bg { + background-color: transparent !important; + opacity: 0 !important; + display: none !important; +} + +/* Target the specific element causing the white background */ +.v-list-item__bg::before, +.v-list-item__bg::after { + background-color: transparent !important; + opacity: 0 !important; + display: none !important; +} + +/* Target the specific element causing the white background */ +.v-list-item__bg > * { + background-color: transparent !important; + opacity: 0 !important; + display: none !important; +} + +/* Target the specific element causing the white background */ +.v-list-item__underlay > * { + background-color: transparent !important; + opacity: 0 !important; + display: none !important; +} + +/* Target the specific element causing the white background */ +.v-list-item__overlay > * { + background-color: transparent !important; + opacity: 0 !important; + display: none !important; +} + +/* Target the specific element causing the white background */ +.v-list-item__bg > div { + background-color: transparent !important; + opacity: 0 !important; + display: none !important; +} + +/* Target the specific element causing the white background */ +.v-list-item__underlay > div { + background-color: transparent !important; + opacity: 0 !important; + display: none !important; +} + +/* Target the specific element causing the white background */ +.v-list-item__overlay > div { + background-color: transparent !important; + opacity: 0 !important; + display: none !important; +} \ No newline at end of file diff --git a/app/assets/data-table-fix.css b/app/assets/data-table-fix.css new file mode 100644 index 00000000..e1b01a14 --- /dev/null +++ b/app/assets/data-table-fix.css @@ -0,0 +1,131 @@ +/* Fix data table footer and item count selection dropdown */ +.v-data-table-footer { + background-color: #1E1E1E !important; + border-top: 1px solid rgba(255, 255, 255, 0.05); +} + +.v-data-table-footer__items-per-page { + background-color: #1E1E1E !important; +} + +/* Fix all dropdown menus and lists */ +.v-overlay__content, +.v-menu__content, +.v-list, +.v-select__content, +.v-select-list { + background-color: #1E1E1E !important; + border: 1px solid rgba(255, 255, 255, 0.1) !important; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5) !important; +} + +/* Fix all list items in dropdowns */ +.v-list-item { + background-color: #1E1E1E !important; + color: #FFFFFF !important; +} + +/* Fix the selected and active items */ +.v-list-item--active, +.v-list-item--selected, +.v-list-item--highlighted, +.v-list-item.v-list-item--active, +.v-list-item.v-list-item--selected { + background-color: #333333 !important; + color: #FFFFFF !important; + font-weight: 600 !important; +} + +/* Fix hover state */ +.v-list-item:hover { + background-color: #333333 !important; + color: #8BE9FD !important; +} + +/* Fix the dropdown fields */ +.v-field, +.v-field--variant-filled, +.v-field--variant-outlined, +.v-field--variant-plain, +.v-field--variant-underlined, +.v-field--variant-solo, +.v-field--variant-solo-filled, +.v-field--variant-solo-inverted, +.v-field--variant-solo-outlined { + background-color: #1E1E1E !important; + border: 1px solid rgba(255, 255, 255, 0.1) !important; +} + +/* Fix input text color */ +.v-field__input, +.v-select__selection, +.v-select__selection-text { + color: #FFFFFF !important; + font-weight: 600 !important; +} + +/* Fix dropdown arrow */ +.v-field__append-inner { + color: #8BE9FD !important; +} + +/* Fix pagination text */ +.v-data-table-footer__pagination { + color: #FFFFFF !important; +} + +/* Fix any white backgrounds */ +.v-theme--light.v-list, +.v-theme--light .v-list, +.v-theme--light.v-menu__content, +.v-theme--light .v-menu__content, +.v-theme--light.v-overlay__content, +.v-theme--light .v-overlay__content { + background-color: #1E1E1E !important; + color: #FFFFFF !important; +} + +/* Fix any white backgrounds in the dropdown - more specific selectors */ +.v-overlay__content > div, +.v-menu__content > div, +.v-list-item__underlay, +.v-list-item__content, +.v-list-item__prepend, +.v-list-item__append, +.v-list-item > *, +.v-list > *, +.v-select__content > *, +.v-select-list > * { + background-color: #1E1E1E !important; + color: #FFFFFF !important; +} + +/* Target the specific white box in the dropdown */ +.v-list-item__overlay { + background-color: transparent !important; + opacity: 0 !important; +} + +/* Fix any other potential white backgrounds */ +.v-overlay__scrim { + background-color: rgba(0, 0, 0, 0.5) !important; +} + +/* Fix the dropdown items container */ +.v-select__content .v-list { + background-color: #1E1E1E !important; + padding: 0 !important; +} + +/* Fix the dropdown items */ +.v-select__content .v-list-item { + background-color: #1E1E1E !important; + color: #FFFFFF !important; + min-height: 40px !important; +} + +/* Fix the selected dropdown item */ +.v-select__content .v-list-item--active { + background-color: #333333 !important; + color: #8BE9FD !important; +} \ No newline at end of file diff --git a/app/assets/date-range-fix.css b/app/assets/date-range-fix.css new file mode 100644 index 00000000..63e1ed7b --- /dev/null +++ b/app/assets/date-range-fix.css @@ -0,0 +1,33 @@ +/* Override styles for date range text */ +.section-heading .date-range-container { + display: inline-block !important; + background-color: #000000 !important; + border-radius: 4px !important; + border: 2px solid #8BE9FD !important; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.7) !important; + padding: 0 !important; + margin-left: 8px !important; + overflow: visible !important; +} + +.section-heading .date-range-text { + display: inline-block !important; + background-color: #000000 !important; + color: #FFFFFF !important; + font-weight: 700 !important; + padding: 6px 12px !important; + border-radius: 0 !important; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8) !important; + font-size: 0.9rem !important; + letter-spacing: 0.5px !important; + opacity: 1 !important; +} + +/* Override any global chip styles */ +.v-chip.date-range-chip { + background-color: #000000 !important; + color: #FFFFFF !important; + font-weight: 700 !important; + border: 2px solid #8BE9FD !important; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.7) !important; +} \ No newline at end of file diff --git a/app/assets/direct-fix.css b/app/assets/direct-fix.css new file mode 100644 index 00000000..48d59219 --- /dev/null +++ b/app/assets/direct-fix.css @@ -0,0 +1,40 @@ +/* Direct fix for the white background in the dropdown */ + +/* Target the specific element causing the white background */ +.v-list-item .v-list-item__overlay, +.v-list-item .v-list-item__underlay { + display: none !important; +} + +/* Force dark background for list items */ +.v-list-item { + background-color: #1E1E1E !important; +} + +/* Force dark background for active list items */ +.v-list-item--active { + background-color: #333333 !important; +} + +/* Force white text for list items */ +.v-list-item__content { + color: white !important; +} + +/* Target the specific element in the dropdown */ +.v-select__content .v-list-item .v-list-item__overlay, +.v-select__content .v-list-item .v-list-item__underlay { + display: none !important; +} + +/* Target the specific element in the data table footer */ +.v-data-table-footer .v-select__content .v-list-item .v-list-item__overlay, +.v-data-table-footer .v-select__content .v-list-item .v-list-item__underlay { + display: none !important; +} + +/* Target the specific element in the data table footer */ +.v-data-table-footer__items-per-page .v-select__content .v-list-item .v-list-item__overlay, +.v-data-table-footer__items-per-page .v-select__content .v-list-item .v-list-item__underlay { + display: none !important; +} \ No newline at end of file diff --git a/app/assets/dropdown-direct-fix.css b/app/assets/dropdown-direct-fix.css new file mode 100644 index 00000000..b85f0864 --- /dev/null +++ b/app/assets/dropdown-direct-fix.css @@ -0,0 +1,89 @@ +/* Direct fix for the white background in the dropdown */ + +/* Target the specific element causing the white background */ +.v-list-item .v-list-item__underlay { + background-color: transparent !important; + opacity: 0 !important; + visibility: hidden !important; +} + +/* Target the specific element causing the white background */ +.v-list-item .v-list-item__overlay { + background-color: transparent !important; + opacity: 0 !important; + visibility: hidden !important; +} + +/* Target the specific element causing the white background */ +.v-list-item__bg { + background-color: transparent !important; + opacity: 0 !important; + visibility: hidden !important; +} + +/* Force dark background for list items */ +.v-list-item { + background-color: #1E1E1E !important; +} + +/* Force dark background for active list items */ +.v-list-item--active { + background-color: #333333 !important; +} + +/* Force white text for list items */ +.v-list-item__content { + color: white !important; +} + +/* Target the specific element in the dropdown */ +.v-select__content .v-list-item .v-list-item__underlay { + background-color: transparent !important; + opacity: 0 !important; + visibility: hidden !important; +} + +/* Target the specific element in the dropdown */ +.v-select__content .v-list-item .v-list-item__overlay { + background-color: transparent !important; + opacity: 0 !important; + visibility: hidden !important; +} + +/* Target the specific element in the dropdown */ +.v-select__content .v-list-item__bg { + background-color: transparent !important; + opacity: 0 !important; + visibility: hidden !important; +} + +/* Force dark background for dropdown menu */ +.v-select__content { + background-color: #1E1E1E !important; +} + +/* Force dark background for list */ +.v-list { + background-color: #1E1E1E !important; +} + +/* Target the specific element in the data table footer */ +.v-data-table-footer .v-select__content .v-list-item .v-list-item__underlay { + background-color: transparent !important; + opacity: 0 !important; + visibility: hidden !important; +} + +/* Target the specific element in the data table footer */ +.v-data-table-footer .v-select__content .v-list-item .v-list-item__overlay { + background-color: transparent !important; + opacity: 0 !important; + visibility: hidden !important; +} + +/* Target the specific element in the data table footer */ +.v-data-table-footer .v-select__content .v-list-item__bg { + background-color: transparent !important; + opacity: 0 !important; + visibility: hidden !important; +} \ No newline at end of file diff --git a/app/assets/dropdown-fix.css b/app/assets/dropdown-fix.css new file mode 100644 index 00000000..6835c258 --- /dev/null +++ b/app/assets/dropdown-fix.css @@ -0,0 +1,40 @@ +/* Direct fix for the white background in the dropdown */ + +/* Target the specific element causing the white background */ +.v-list-item__underlay { + display: none !important; +} + +/* Override Vuetify's theme variables for list items */ +:root { + --v-theme-surface: #1E1E1E !important; + --v-theme-surface-variant: #2D2D2D !important; + --v-activated-opacity: 0 !important; + --v-selected-opacity: 0 !important; + --v-hover-opacity: 0 !important; +} + +/* Force background colors for all list items */ +.v-list-item { + background-color: #1E1E1E !important; +} + +/* Force background colors for active list items */ +.v-list-item--active { + background-color: #333333 !important; +} + +/* Force text color for all list items */ +.v-list-item__content { + color: white !important; +} + +/* Force background color for the dropdown menu */ +.v-menu__content { + background-color: #1E1E1E !important; +} + +/* Force background color for the list */ +.v-list { + background-color: #1E1E1E !important; +} \ No newline at end of file diff --git a/app/assets/final-dropdown-fix.css b/app/assets/final-dropdown-fix.css new file mode 100644 index 00000000..e69de29b diff --git a/app/assets/final-fix.css b/app/assets/final-fix.css new file mode 100644 index 00000000..c8084cee --- /dev/null +++ b/app/assets/final-fix.css @@ -0,0 +1,5 @@ +/* Final fix for the white background in the dropdown */ +.v-list-item__underlay { + background-color: transparent !important; + display: none !important; +} \ No newline at end of file diff --git a/app/assets/global.css b/app/assets/global.css index a4ea1a92..2f08f568 100644 --- a/app/assets/global.css +++ b/app/assets/global.css @@ -1,78 +1,419 @@ +/* Base styles */ +:root { + --transition-speed: 0.3s; + --border-radius-sm: 4px; + --border-radius-md: 8px; + --border-radius-lg: 12px; + --shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.1); + --shadow-md: 0 4px 8px rgba(0, 0, 0, 0.15); + --shadow-lg: 0 8px 16px rgba(0, 0, 0, 0.2); + + /* Color palette based on the image */ + --color-cyan: #8BE9FD; + --color-teal: #64D8CB; + --color-purple: #9C64D8; + --color-dark-bg: #121212; + --color-card-bg: #1E1E1E; + --color-success: #50FA7B; + --color-warning: #FFB86C; + --color-error: #FF5252; + --color-text: #F8F8F2; + --color-text-muted: #BFBFBF; + + /* Gradients */ + --gradient-primary: linear-gradient(135deg, var(--color-teal) 0%, var(--color-purple) 100%); + --gradient-secondary: linear-gradient(135deg, var(--color-cyan) 0%, var(--color-teal) 100%); + --gradient-accent: linear-gradient(135deg, var(--color-purple) 0%, var(--color-cyan) 100%); +} + +body { + font-family: 'Inter', sans-serif; + line-height: 1.6; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + background-color: var(--color-dark-bg); + color: var(--color-text); +} + +/* Layout components */ .tiles-container { - display: flex; - justify-content: flex-start; - flex-wrap: wrap; - } - .tiles-text { - display: flex; - flex-direction: column; - align-items: center; - text-align: center; - } + display: flex; + justify-content: center; + flex-wrap: wrap; + gap: 24px; + margin-bottom: 32px; +} - .error-message { - color: red; - } +.tiles-text { + display: flex; + flex-direction: column; + align-items: center; + text-align: center; +} - .spacing-10 { - margin-bottom: 10px; - } +.content-container { + max-width: 1400px; + margin: 0 auto; + padding: 24px; +} - .spacing-25 { - margin-bottom: 25px; - } +/* Utility classes */ +.error-message { + color: var(--color-error); + font-weight: 500; + padding: 8px 12px; + border-radius: var(--border-radius-sm); + background-color: rgba(255, 82, 82, 0.1); + margin: 8px 0; + display: inline-block; +} - /* Fix tab hover styles - dark blue overlay using pseudo-element */ - .v-tab { - position: relative !important; - } - - .v-tab:hover::before { - content: '' !important; - position: absolute !important; - top: 0 !important; - left: 0 !important; - width: 100% !important; - height: 100% !important; - background-color: rgba(44, 32, 157, 0.557) !important; - pointer-events: none !important; - z-index: 1 !important; - } +.spacing-10 { + margin-bottom: 10px; +} - /* Ensure tab content is above overlay */ - .v-tab .v-tab__content { - position: relative !important; - z-index: 2 !important; - } +.spacing-25 { + margin-bottom: 25px; +} - /* Fix expansion panel title overlay on hover - gray overlay */ - .v-expansion-panel-title:hover .v-expansion-panel-title__overlay { - display: block !important; - background-color: rgba(0, 0, 0, 0.04) !important; - opacity: 1 !important; - position: absolute !important; - top: 0 !important; - left: 0 !important; - width: 100% !important; - height: 100% !important; - pointer-events: none !important; - } +.text-capitalize { + text-transform: capitalize !important; +} + +/* Card enhancements */ +.v-card { + transition: transform var(--transition-speed), box-shadow var(--transition-speed); + overflow: hidden; + border-radius: var(--border-radius-md) !important; + background-color: var(--color-card-bg) !important; + border: 1px solid rgba(255, 255, 255, 0.05); +} + +.v-card:hover { + transform: translateY(-2px); + box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3) !important; + border: 1px solid rgba(100, 216, 203, 0.2); +} + +.v-card__title { + font-weight: 600 !important; + letter-spacing: -0.01em !important; + color: var(--color-cyan) !important; +} + +/* Tab styling */ +.v-tab { + position: relative !important; + text-transform: capitalize !important; + font-weight: 500 !important; + letter-spacing: 0.5px !important; + transition: all var(--transition-speed) !important; + border-radius: 0 !important; + min-width: 100px; + color: var(--color-text) !important; +} + +.v-tab:hover::before { + content: '' !important; + position: absolute !important; + top: 0 !important; + left: 0 !important; + width: 100% !important; + height: 100% !important; + background-color: rgba(100, 216, 203, 0.1) !important; + pointer-events: none !important; + z-index: 1 !important; +} + +.v-tab .v-tab__content { + position: relative !important; + z-index: 2 !important; +} + +/* App bar styling */ +.app-header { + border-bottom: 1px solid rgba(255, 255, 255, 0.1); +} + +.toolbar-title { + font-weight: 600 !important; + letter-spacing: -0.01em !important; +} + +/* Expansion panel enhancements */ +.v-expansion-panel { + border-radius: var(--border-radius-md) !important; + margin-bottom: 8px !important; + overflow: hidden; + box-shadow: var(--shadow-sm) !important; + background-color: var(--color-card-bg) !important; + border: 1px solid rgba(255, 255, 255, 0.05); +} + +.v-expansion-panel-title { + font-weight: 500 !important; + padding: 16px !important; + color: var(--color-text) !important; +} + +.v-expansion-panel-title:hover .v-expansion-panel-title__overlay { + background-color: rgba(100, 216, 203, 0.1) !important; +} + +.v-expansion-panel-text__wrapper { + padding: 16px !important; + background-color: var(--color-card-bg) !important; +} + +/* Button enhancements */ +.v-btn { + font-weight: 500 !important; + letter-spacing: 0 !important; + transition: all var(--transition-speed) !important; + text-transform: none !important; +} + +.v-btn--elevated { + box-shadow: var(--shadow-sm) !important; + background: var(--gradient-primary) !important; + color: white !important; +} + +.v-btn--elevated:hover { + box-shadow: var(--shadow-md) !important; + transform: translateY(-1px); +} + +.v-btn:hover .v-btn__overlay { + opacity: 0.1 !important; +} + +/* GitHub login button styling */ +.github-login-container { + display: flex; + justify-content: center; + margin-top: 32px; + margin-bottom: 32px; +} + +.github-login-button { + display: flex; + align-items: center; + background: var(--gradient-primary); + color: white; + padding: 12px 24px; + border-radius: var(--border-radius-md); + text-decoration: none; + font-weight: 600; + font-size: 14px; + transition: all var(--transition-speed); + box-shadow: var(--shadow-sm); +} + +.github-login-button:hover { + transform: translateY(-2px); + box-shadow: var(--shadow-md); + filter: brightness(1.1); +} + +.github-login-button .v-icon { + margin-right: 8px; +} - /* Fix button hover styles - light gray background */ - .v-btn:hover { - background-color: rgba(63, 81, 181, 0.1) !important; +/* User info styling */ +.user-info { + display: flex; + align-items: center; + background-color: rgba(255, 255, 255, 0.1); + padding: 4px 12px; + border-radius: 24px; +} + +.user-avatar { + margin-right: 8px; + margin-left: 8px; + border: 2px solid var(--color-cyan); +} + +/* Organization info styling */ +.organization-info { + background-color: rgba(100, 216, 203, 0.05); + border-left: 4px solid var(--color-teal); + border-radius: var(--border-radius-sm); + margin: 16px 0; +} + +/* Date range selector styling */ +.date-range-selector { + background-color: var(--color-card-bg); + border-radius: var(--border-radius-md); + box-shadow: var(--shadow-sm); + margin-bottom: 24px; + border: 1px solid rgba(255, 255, 255, 0.05); +} + +/* Chart enhancements */ +.chart-container { + background-color: var(--color-card-bg); + border-radius: var(--border-radius-md); + padding: 16px; + box-shadow: var(--shadow-sm); + margin-bottom: 24px; + border: 1px solid rgba(255, 255, 255, 0.05); +} + +/* Data table styling */ +.v-data-table { + border-radius: var(--border-radius-md) !important; + overflow: hidden; + box-shadow: var(--shadow-sm) !important; + background-color: var(--color-card-bg) !important; +} + +.v-data-table__thead { + background-color: rgba(100, 216, 203, 0.05); +} + +.v-data-table__th { + font-weight: 600 !important; + text-transform: uppercase !important; + font-size: 0.75rem !important; + letter-spacing: 0.05em !important; + color: var(--color-cyan) !important; +} + +/* Responsive adjustments */ +@media (max-width: 768px) { + .content-container { + padding: 16px; } - .v-btn:hover .v-btn__overlay { - display: none !important; + .tiles-container { + gap: 12px; } - - /* Override Vuetify's default overlay behavior for tabs */ - .v-tab.v-btn--variant-text .v-tab__overlay { - background: transparent !important; + + .v-card { + border-radius: var(--border-radius-sm) !important; } +} + +/* Glow effects for cards */ +.metric-card { + position: relative; + overflow: hidden; +} + +.metric-card::before { + content: ''; + position: absolute; + top: -2px; + left: -2px; + right: -2px; + bottom: -2px; + background: var(--gradient-primary); + z-index: -1; + border-radius: calc(var(--border-radius-md) + 2px); + opacity: 0; + transition: opacity var(--transition-speed); +} + +.metric-card:hover::before { + opacity: 0.7; +} + +/* Custom scrollbar */ +::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +::-webkit-scrollbar-track { + background: #1a1a1a; +} + +::-webkit-scrollbar-thumb { + background: var(--color-teal); + border-radius: 4px; +} + +::-webkit-scrollbar-thumb:hover { + background: var(--color-cyan); +} + +/* Text colors */ +.text-primary { + color: var(--color-teal) !important; +} + +.text-secondary { + color: var(--color-cyan) !important; +} + +.text-accent { + color: var(--color-purple) !important; +} + +.text-success { + color: var(--color-success) !important; +} + +.text-warning { + color: var(--color-warning) !important; +} + +.text-error { + color: var(--color-error) !important; +} + +/* Background colors */ +.bg-primary { + background-color: var(--color-teal) !important; +} + +.bg-secondary { + background-color: var(--color-cyan) !important; +} + +.bg-accent { + background-color: var(--color-purple) !important; +} + +.bg-gradient-primary { + background: var(--gradient-primary) !important; +} + +.bg-gradient-secondary { + background: var(--gradient-secondary) !important; +} + +.bg-gradient-accent { + background: var(--gradient-accent) !important; +} + +/* Chip styling */ +.v-chip { + background: var(--gradient-primary) !important; + color: white !important; +} + +/* Progress indicators */ +.v-progress-circular { + color: var(--color-teal) !important; +} + +.v-progress-linear { + background-color: rgba(100, 216, 203, 0.2) !important; +} + +.v-progress-linear__determinate { + background: var(--gradient-primary) !important; +} + +/* Switch styling */ +.v-switch__track { + background-color: rgba(100, 216, 203, 0.2) !important; +} - /* Override Vuetify's default overlay behavior for variant-text buttons in tabs */ - .v-tab .v-btn--variant-text .v-btn__overlay { - background: transparent !important; - } \ No newline at end of file +.v-switch--active .v-switch__track { + background-color: var(--color-teal) !important; +} \ No newline at end of file diff --git a/app/assets/light-theme.css b/app/assets/light-theme.css new file mode 100644 index 00000000..efe4b89e --- /dev/null +++ b/app/assets/light-theme.css @@ -0,0 +1,310 @@ +/* Light Theme CSS Variables */ +.v-theme--light { + /* Light mode color palette */ + --color-cyan-light: #4DD0E1; + --color-teal-light: #26A69A; + --color-purple-light: #7B1FA2; + --color-light-bg: #F5F7FA; + --color-card-bg-light: #FFFFFF; + --color-success-light: #4CAF50; + --color-warning-light: #FF9800; + --color-error-light: #F44336; + --color-text-light: #333333; + --color-text-muted-light: #666666; + + /* Light mode gradients */ + --gradient-primary-light: linear-gradient(135deg, #26A69A 0%, #7B1FA2 100%); + --gradient-secondary-light: linear-gradient(135deg, #4DD0E1 0%, #26A69A 100%); + --gradient-accent-light: linear-gradient(135deg, #7B1FA2 0%, #4DD0E1 100%); + + /* Light mode shadows */ + --shadow-sm-light: 0 2px 4px rgba(0, 0, 0, 0.05); + --shadow-md-light: 0 4px 8px rgba(0, 0, 0, 0.08); + --shadow-lg-light: 0 8px 16px rgba(0, 0, 0, 0.1); +} + +/* Light Theme Overrides */ +.v-theme--light .v-card { + background-color: var(--color-card-bg-light) !important; + border: 1px solid rgba(0, 0, 0, 0.05); + box-shadow: var(--shadow-sm-light) !important; +} + +.v-theme--light .v-card:hover { + box-shadow: var(--shadow-md-light) !important; + border: 1px solid rgba(38, 166, 154, 0.2); +} + +.v-theme--light .v-card__title { + color: var(--color-teal-light) !important; +} + +.v-theme--light .v-tab { + color: var(--color-text-light) !important; +} + +.v-theme--light .v-tab:hover::before { + background-color: rgba(38, 166, 154, 0.1) !important; +} + +.v-theme--light .v-expansion-panel { + background-color: var(--color-card-bg-light) !important; + border: 1px solid rgba(0, 0, 0, 0.05); + box-shadow: var(--shadow-sm-light) !important; +} + +.v-theme--light .v-expansion-panel-title { + color: var(--color-text-light) !important; +} + +.v-theme--light .v-expansion-panel-title:hover .v-expansion-panel-title__overlay { + background-color: rgba(38, 166, 154, 0.1) !important; +} + +.v-theme--light .v-expansion-panel-text__wrapper { + background-color: var(--color-card-bg-light) !important; +} + +.v-theme--light .v-btn--elevated { + background: var(--gradient-primary-light) !important; +} + +.v-theme--light .date-range-selector { + background-color: var(--color-card-bg-light); + border: 1px solid rgba(0, 0, 0, 0.05); + box-shadow: var(--shadow-sm-light); +} + +.v-theme--light .chart-container { + background-color: var(--color-card-bg-light); + border: 1px solid rgba(0, 0, 0, 0.05); + box-shadow: var(--shadow-sm-light); +} + +.v-theme--light .v-data-table { + background-color: var(--color-card-bg-light) !important; + box-shadow: var(--shadow-sm-light) !important; +} + +.v-theme--light .v-data-table__thead { + background-color: rgba(38, 166, 154, 0.05); +} + +.v-theme--light .v-data-table__th { + color: var(--color-teal-light) !important; +} + +.v-theme--light .metric-card::before { + background: var(--gradient-primary-light); +} + +.v-theme--light ::-webkit-scrollbar-track { + background: #f1f1f1; +} + +.v-theme--light ::-webkit-scrollbar-thumb { + background: var(--color-teal-light); +} + +.v-theme--light ::-webkit-scrollbar-thumb:hover { + background: var(--color-cyan-light); +} + +.v-theme--light .text-primary { + color: var(--color-teal-light) !important; +} + +.v-theme--light .text-secondary { + color: var(--color-cyan-light) !important; +} + +.v-theme--light .text-accent { + color: var(--color-purple-light) !important; +} + +.v-theme--light .text-success { + color: var(--color-success-light) !important; +} + +.v-theme--light .text-warning { + color: var(--color-warning-light) !important; +} + +.v-theme--light .text-error { + color: var(--color-error-light) !important; +} + +.v-theme--light .bg-primary { + background-color: var(--color-teal-light) !important; +} + +.v-theme--light .bg-secondary { + background-color: var(--color-cyan-light) !important; +} + +.v-theme--light .bg-accent { + background-color: var(--color-purple-light) !important; +} + +.v-theme--light .bg-gradient-primary { + background: var(--gradient-primary-light) !important; +} + +.v-theme--light .bg-gradient-secondary { + background: var(--gradient-secondary-light) !important; +} + +.v-theme--light .bg-gradient-accent { + background: var(--gradient-accent-light) !important; +} + +.v-theme--light .v-chip { + background: var(--gradient-primary-light) !important; +} + +.v-theme--light .v-progress-circular { + color: var(--color-teal-light) !important; +} + +.v-theme--light .v-progress-linear { + background-color: rgba(38, 166, 154, 0.2) !important; +} + +.v-theme--light .v-progress-linear__determinate { + background: var(--gradient-primary-light) !important; +} + +.v-theme--light .v-switch__track { + background-color: rgba(38, 166, 154, 0.2) !important; +} + +.v-theme--light .v-switch--active .v-switch__track { + background-color: var(--color-teal-light) !important; +} + +/* Light theme specific styles for metric cards */ +.v-theme--light .metric-card { + background-color: white !important; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08) !important; + border: 1px solid rgba(0, 0, 0, 0.05); +} + +.v-theme--light .metric-card:hover { + box-shadow: 0 4px 12px rgba(38, 166, 154, 0.15) !important; + border: 1px solid rgba(38, 166, 154, 0.2); +} + +.v-theme--light .card-accent { + background: linear-gradient(90deg, #4DD0E1, #26A69A, #7B1FA2) !important; +} + +.v-theme--light .text-h4 { + background: linear-gradient(90deg, #4DD0E1, #26A69A, #7B1FA2); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + color: transparent; + font-weight: 700 !important; +} + +/* Light theme navigation drawer */ +.v-theme--light .navigation-drawer { + background-color: white !important; + border-right: 1px solid rgba(38, 166, 154, 0.2); +} + +.v-theme--light .drawer-list { + background-color: white !important; +} + +.v-theme--light .custom-menu-item { + color: #333333; +} + +.v-theme--light .custom-menu-item:hover { + background-color: rgba(38, 166, 154, 0.05); +} + +.v-theme--light .custom-menu-item-active { + background-color: #E8F5F5 !important; + border-left: 3px solid #26A69A; + box-shadow: 0 0 8px rgba(0, 0, 0, 0.1); +} + +.v-theme--light .custom-menu-item-active .menu-icon { + color: #26A69A; +} + +.v-theme--light .custom-menu-item-active .menu-text { + color: #333333; + font-weight: 700; +} + +.v-theme--light .drawer-header :deep(.v-list-item-title) { + color: #26A69A !important; +} + +.v-theme--light .drawer-header :deep(.v-list-item-subtitle) { + color: rgba(0, 0, 0, 0.7) !important; +} + +.v-theme--light .drawer-divider { + border-color: rgba(38, 166, 154, 0.1) !important; +} + +/* Light theme chart styles */ +.v-theme--light .chart-title { + color: #26A69A; + text-shadow: none; +} + +.v-theme--light .breakdown-title { + color: #26A69A; + text-shadow: none; +} + +.v-theme--light .tooltip-card { + background-color: rgba(255, 255, 255, 0.95) !important; + border: 1px solid rgba(38, 166, 154, 0.3); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); +} + +.v-theme--light .tooltip-text { + color: #333333 !important; +} + +/* Light theme app header */ +.v-theme--light .app-header { + background: linear-gradient(135deg, #26A69A 0%, #7B1FA2 100%) !important; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1) !important; +} + +.v-theme--light .app-header::after { + background: linear-gradient(90deg, #4DD0E1, #26A69A, #7B1FA2); +} + +/* Light theme welcome banner */ +.v-theme--light .section-heading { + color: #333333; +} + +.v-theme--light .section-title { + color: #333333 !important; + text-shadow: none; +} + +.v-theme--light .custom-date-badge { + background-color: white; + color: #333333; + border: 2px solid #26A69A; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); +} + +.v-theme--light .date-icon { + color: #26A69A; +} + +.v-theme--light .date-text { + color: #333333; + text-shadow: none; +} \ No newline at end of file diff --git a/app/assets/settings.scss b/app/assets/settings.scss index 3e36a279..8804ff05 100644 --- a/app/assets/settings.scss +++ b/app/assets/settings.scss @@ -1,10 +1,143 @@ -/** - * src/styles/settings.scss - * - * Configures SASS variables and Vuetify overwrites - */ - -// https://vuetifyjs.com/features/sass-variables/` -// @use 'vuetify/settings' with ( -// $color-pack: false -// ); +// Custom Vuetify SASS variables +@use 'vuetify/settings' with ( + // Global font settings + $body-font-family: ('Inter', sans-serif), + $heading-font-family: ('Inter', sans-serif), + + // Typography + $typography: ( + 'h1': ( + 'weight': 700, + 'letter-spacing': -0.02em, + ), + 'h2': ( + 'weight': 700, + 'letter-spacing': -0.01em, + ), + 'h3': ( + 'weight': 600, + 'letter-spacing': -0.01em, + ), + 'h4': ( + 'weight': 600, + 'letter-spacing': -0.01em, + ), + 'h5': ( + 'weight': 600, + 'letter-spacing': -0.01em, + ), + 'h6': ( + 'weight': 600, + 'letter-spacing': -0.01em, + ), + 'subtitle-1': ( + 'weight': 500, + ), + 'subtitle-2': ( + 'weight': 500, + ), + 'body-1': ( + 'weight': 400, + ), + 'body-2': ( + 'weight': 400, + ), + 'button': ( + 'weight': 500, + 'letter-spacing': 0.01em, + 'text-transform': none, + ), + 'caption': ( + 'weight': 400, + ), + 'overline': ( + 'weight': 500, + 'letter-spacing': 0.05em, + ), + ), + + // Border radius + $border-radius-root: 8px, + + // Elevation (shadows) + $shadow-key-umbra-opacity: rgba(0, 0, 0, 0.1), + $shadow-key-penumbra-opacity: rgba(0, 0, 0, 0.12), + $shadow-key-ambient-opacity: rgba(0, 0, 0, 0.06), + + // Card specific + $card-border-radius: 12px, + $card-elevation: 2 +); + +// Custom CSS variables +:root { + --primary-gradient: linear-gradient(135deg, #3F51B5 0%, #5C6BC0 100%); + --card-hover-transform: translateY(-2px); + --card-hover-shadow: 0 6px 12px rgba(0, 0, 0, 0.1); + --transition-speed: 0.3s; + --border-radius-sm: 4px; + --border-radius-md: 8px; + --border-radius-lg: 12px; + --button-border-radius: 8px; + --expansion-panel-border-radius: 8px; + --data-table-border-radius: 8px; + --tabs-item-letter-spacing: 0; + --tabs-item-font-weight: 500; +} + +// Global styles +html { + scroll-behavior: smooth; +} + +// Button styles +.v-btn { + text-transform: none !important; +} + +// Custom scrollbar +::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +::-webkit-scrollbar-track { + background: #f1f1f1; +} + +::-webkit-scrollbar-thumb { + background: #c1c1c1; + border-radius: 4px; +} + +::-webkit-scrollbar-thumb:hover { + background: #a8a8a8; +} + +// Dark mode scrollbar +.v-theme--dark ::-webkit-scrollbar-track { + background: #2d2d2d; +} + +.v-theme--dark ::-webkit-scrollbar-thumb { + background: #555; +} + +.v-theme--dark ::-webkit-scrollbar-thumb:hover { + background: #777; +} + +// Additional component styles +.v-data-table { + border-radius: var(--border-radius-md) !important; + overflow: hidden; +} + +.v-expansion-panel { + border-radius: var(--border-radius-md) !important; +} + +.v-tabs .v-tab { + letter-spacing: 0 !important; + font-weight: 500 !important; +} \ No newline at end of file diff --git a/app/assets/vuetify-fix.css b/app/assets/vuetify-fix.css new file mode 100644 index 00000000..582ed853 --- /dev/null +++ b/app/assets/vuetify-fix.css @@ -0,0 +1,66 @@ +/* Fix for Vuetify list item underlay */ +.v-list-item__underlay { + background-color: transparent !important; + opacity: 0 !important; +} + +/* Fix for Vuetify list item overlay */ +.v-list-item__overlay { + background-color: transparent !important; + opacity: 0 !important; +} + +/* Fix for Vuetify list item background */ +.v-list-item { + background-color: #1E1E1E !important; +} + +/* Fix for Vuetify list item active background */ +.v-list-item--active { + background-color: #333333 !important; +} + +/* Fix for Vuetify list item selected background */ +.v-list-item--selected { + background-color: #333333 !important; +} + +/* Fix for Vuetify list item hover background */ +.v-list-item:hover { + background-color: #333333 !important; +} + +/* Fix for Vuetify list item text color */ +.v-list-item__content { + color: #FFFFFF !important; +} + +/* Fix for Vuetify list background */ +.v-list { + background-color: #1E1E1E !important; +} + +/* Fix for Vuetify menu content background */ +.v-menu__content { + background-color: #1E1E1E !important; +} + +/* Fix for Vuetify select content background */ +.v-select__content { + background-color: #1E1E1E !important; +} + +/* Fix for Vuetify select list background */ +.v-select-list { + background-color: #1E1E1E !important; +} + +/* Fix for Vuetify overlay content background */ +.v-overlay__content { + background-color: #1E1E1E !important; +} + +/* Fix for Vuetify overlay scrim background */ +.v-overlay__scrim { + background-color: rgba(0, 0, 0, 0.5) !important; +} \ No newline at end of file diff --git a/app/components/AgentModeViewer.vue b/app/components/AgentModeViewer.vue index 2e47979c..2ea12eaa 100644 --- a/app/components/AgentModeViewer.vue +++ b/app/components/AgentModeViewer.vue @@ -1,162 +1,68 @@ + + \ No newline at end of file diff --git a/app/components/BreakdownComponent.vue b/app/components/BreakdownComponent.vue index 0889a043..da01eddf 100644 --- a/app/components/BreakdownComponent.vue +++ b/app/components/BreakdownComponent.vue @@ -1,29 +1,24 @@ + + \ No newline at end of file diff --git a/app/components/CopilotChatViewer.vue b/app/components/CopilotChatViewer.vue index ebe4db9b..ee046c01 100644 --- a/app/components/CopilotChatViewer.vue +++ b/app/components/CopilotChatViewer.vue @@ -1,73 +1,46 @@ + + diff --git a/app/components/CopilotLogo.vue b/app/components/CopilotLogo.vue new file mode 100644 index 00000000..d8a529c0 --- /dev/null +++ b/app/components/CopilotLogo.vue @@ -0,0 +1,94 @@ + + + + + \ No newline at end of file diff --git a/app/components/DashboardLayout.vue b/app/components/DashboardLayout.vue new file mode 100644 index 00000000..d152e635 --- /dev/null +++ b/app/components/DashboardLayout.vue @@ -0,0 +1,87 @@ + + + + + \ No newline at end of file diff --git a/app/components/DateRangeSelector.vue b/app/components/DateRangeSelector.vue index 9d0f86a6..2fd4316e 100644 --- a/app/components/DateRangeSelector.vue +++ b/app/components/DateRangeSelector.vue @@ -1,66 +1,126 @@ \ No newline at end of file + + + \ No newline at end of file diff --git a/app/components/LoadingAnimation.vue b/app/components/LoadingAnimation.vue new file mode 100644 index 00000000..0553612f --- /dev/null +++ b/app/components/LoadingAnimation.vue @@ -0,0 +1,100 @@ + + + + + \ No newline at end of file diff --git a/app/components/MainComponent.vue b/app/components/MainComponent.vue index 5f40741c..38d1789c 100644 --- a/app/components/MainComponent.vue +++ b/app/components/MainComponent.vue @@ -1,101 +1,247 @@