Newer
Older
bugtrail / packages / web / src / pages / DownloadPage.vue
<script setup lang="ts">
import { computed } from "vue";
import { useI18n } from "vue-i18n";
import { GnCard } from "gnexus-ui-kit/vue";
import AppShell from "../components/AppShell.vue";

const { t, tm, rt } = useI18n();

// stable archive names, rebuilt by `npm run package -w @ltt/extension`
const zips = {
  chrome: "/ext/bugtrail-chrome.zip",
  firefox: "/ext/bugtrail-firefox.zip",
};

/** the panel's own origin is what the extension should be pointed at */
const serverUrl = computed(() => window.location.origin);

/** tm() returns the raw message array; rt() resolves each entry to a string */
function steps(key: string): string[] {
  const messages = tm(key);
  if (!Array.isArray(messages)) return [];
  return messages.map((message) => rt(message as never));
}
</script>

<template>
  <AppShell>
    <div class="download-page">
      <h1 class="download-title">{{ t("download.title") }}</h1>
      <p class="download-subtitle">{{ t("download.subtitle") }}</p>

      <div class="download-grid">
        <GnCard class="download-card">
          <div class="download-card-head">
            <i class="ph ph-browsers" />
            <h2>{{ t("download.chrome") }}</h2>
          </div>
          <a :href="zips.chrome" class="download-btn" download>
            <i class="ph ph-download-simple" /> {{ t("download.downloadZip") }}
          </a>
          <p class="download-hint">{{ t("download.downloadHint") }}</p>
          <ol class="download-steps">
            <li v-for="(step, index) in steps('download.chromeSteps')" :key="index">{{ step }}</li>
          </ol>
        </GnCard>

        <GnCard class="download-card">
          <div class="download-card-head">
            <i class="ph ph-firefox-logo" />
            <h2>{{ t("download.firefox") }}</h2>
          </div>
          <a :href="zips.firefox" class="download-btn" download>
            <i class="ph ph-download-simple" /> {{ t("download.downloadZip") }}
          </a>
          <p class="download-hint">{{ t("download.downloadHint") }}</p>
          <ol class="download-steps">
            <li v-for="(step, index) in steps('download.firefoxSteps')" :key="index">{{ step }}</li>
          </ol>
        </GnCard>
      </div>

      <GnCard class="download-card download-wide">
        <h2 class="download-section-title">{{ t("download.setupTitle") }}</h2>
        <ol class="download-steps">
          <li>{{ t("download.setupOpen") }}</li>
          <li>
            {{ t("download.setupServer") }}
            <code class="download-server">{{ serverUrl }}</code>
          </li>
          <li>{{ t("download.setupSignIn") }}</li>
        </ol>
      </GnCard>

      <GnCard class="download-card download-wide">
        <h2 class="download-section-title">{{ t("download.usageTitle") }}</h2>
        <p class="download-usage">{{ t("download.usageNote") }}</p>
      </GnCard>
    </div>
  </AppShell>
</template>

<style scoped>
.download-page {
  display: flex;
  flex-direction: column;
  gap: 16px;
  max-width: 900px;
}
.download-title {
  margin: 0;
  font-size: 22px;
}
.download-subtitle {
  margin: 0;
  opacity: 0.7;
}
.download-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 16px;
  align-items: start;
}
.download-card {
  width: 100%;
  max-width: none;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}
.download-card :deep(.card-content) {
  padding: 18px;
}
.download-card-head {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 16px;
}
.download-card-head .ph {
  font-size: 20px;
  color: var(--ltt-accent, #7aa2f7);
}
.download-card-head h2 {
  margin: 0;
  font-size: 16px;
}
.download-section-title {
  margin: 0;
  font-size: 16px;
}
.download-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  align-self: flex-start;
  padding: 8px 16px;
  border: 2px solid var(--ltt-accent, #7aa2f7);
  background: var(--ltt-accent, #7aa2f7);
  color: var(--ltt-bg, #10121c);
  font-weight: 700;
  font-size: 13px;
  text-decoration: none;
}
.download-btn:hover {
  filter: brightness(1.1);
}
.download-hint {
  margin: 0;
  font-size: 12px;
  opacity: 0.6;
}
.download-steps {
  margin: 0;
  padding-left: 20px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 13px;
}
.download-usage {
  margin: 0;
  font-size: 13px;
  white-space: pre-wrap;
}
.download-server {
  padding: 2px 8px;
  border: 1px solid var(--ltt-border, rgba(192, 202, 245, 0.24));
  background: var(--ltt-surface-sunken, #10121c);
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 12px;
  user-select: all;
}
</style>