Hello from MCP server

List Files | Just Commands | Repo | Logs

← back |
<template>
  <BaseLayout title="Problem Preview">
    <ion-grid :fixed="true">
      <ion-row>
        <ion-col>
          <!-- Problem Information -->
          <div class="problem-header">
            <h2>{{ problem?.name || "Loading..." }}</h2>
            <p class="problem-description" v-if="problem?.description">
              {{ problem.description }}
            </p>
          </div>

          <div class="divider"></div>

          <!-- Linked Menus Section -->
          <div class="menus-section" v-if="linkedMenus.length > 0">
            <h3>Related Menus</h3>
            <div class="menu-list">
              <div v-for="menu in linkedMenus" :key="menu.id" class="menu-item">
                <h4>{{ menu.name }}</h4>
              </div>
            </div>
          </div>

          <!-- Offers Overview -->
          <div class="offers-section" v-if="relatedOffers.length > 0">
            <h3>Available Offers ({{ relatedOffers.length }})</h3>
            <div class="offers-grid">
              <div
                v-for="offer in relatedOffers"
                :key="offer.id"
                class="offer-card"
              >
                <div class="tier-badge" v-if="offer.tierName">
                  {{ offer.tierName }}
                </div>
                <div class="offer-name">{{ offer.name }}</div>
                <div class="offer-subtitle" v-if="offer.tierTitle">
                  {{ offer.tierTitle }}
                </div>
                <div>Tech handbook info will go here</div>
              </div>
            </div>
          </div>

          <div v-if="relatedOffers.length === 0 && !loading" class="no-offers">
            <p>No offers found for the linked menus.</p>
          </div>

          <div class="button-group">
            <ion-button @click="confirmProblem" :disabled="!problem">
              Select Problem
            </ion-button>
            <ion-button color="tertiary" fill="outline" @click="goToSession">
              Session Home
            </ion-button>
          </div>
        </ion-col>
      </ion-row>
    </ion-grid>
  </BaseLayout>
</template>

<script setup lang="ts">
import { onMounted, ref } from "vue";
import { useRoute, useRouter, RouterLink } from "vue-router";
import { IonButton, IonGrid, IonRow, IonCol } from "@ionic/vue";
import BaseLayout from "@/components/BaseLayout.vue";
import { getDb } from "@/dataAccess/getDb";
import { getApi } from "@/dataAccess/getApi";
import type {
  ProblemsRecord,
  MenusRecord,
  OffersRecord,
} from "@/pocketbase-types.ts";
import { useSessionStore } from "@/stores/session";

const route = useRoute();
const router = useRouter();
const sessionStore = useSessionStore();

const problem = ref<ProblemsRecord>();
const linkedMenus = ref<MenusRecord[]>([]);
const relatedOffers = ref<any[]>([]); // Changed to any[] to include tier data
const loading = ref(true);

const confirmProblem = async () => {
  // Navigate to confirm-job with problem ID (don't create job yet)
  if (problem.value) {
    router.push(`/confirm-job?problemId=${problem.value.id}`);
  }
};

const goToSession = () => {
  router.push("/service-call");
};

onMounted(async () => {
  loading.value = true;
  const db = await getDb();

  if (db) {
    // Fetch the problem
    problem.value = (await db.problems.byId(route.params.id as string)) || {};

    if (problem.value && problem.value.menus) {
      // Fetch linked menus with their tiers and offers
      const offerSet = new Set<string>();

      for (const menuId of problem.value.menus) {
        // Use byMenuId to get the full menu with tiers
        const menuWithTiers = await db.menus.byMenuId(menuId);

        if (menuWithTiers) {
          // Add to linked menus list (simplified version for display)
          linkedMenus.value.push({
            id: menuWithTiers.id,
            name: menuWithTiers.name,
            refId: menuWithTiers.refId,
            org: menuWithTiers.org,
            books: menuWithTiers.books,
            created: menuWithTiers.created,
            updated: menuWithTiers.updated,
          } as MenusRecord);

          // Extract offers from tiers with their content items
          if (menuWithTiers.tiers && Array.isArray(menuWithTiers.tiers)) {
            for (const tier of menuWithTiers.tiers) {
              if (tier.offer && !offerSet.has(tier.offer.id)) {
                offerSet.add(tier.offer.id);

                // Find the title from content items
                let title = "";
                if (tier.contentItems && Array.isArray(tier.contentItems)) {
                  const titleItem = tier.contentItems.find(
                    (item: any) => item.refId && item.refId.includes("_title"),
                  );
                  if (titleItem) {
                    title = titleItem.content;
                  }
                }

                // Create an enhanced offer object with tier information
                const enhancedOffer = {
                  ...tier.offer,
                  tierName: tier.name,
                  tierTitle: title,
                  contentItems: tier.contentItems || [],
                };

                relatedOffers.value.push(enhancedOffer);
              }
            }
          }
        }
      }

      // Sort offers by name for better display
      relatedOffers.value.sort((a, b) =>
        (a.name || "").localeCompare(b.name || ""),
      );
    }
  }

  loading.value = false;
});
</script>

<style scoped>
.button-group {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 24px;
}

.problem-header {
  margin-bottom: 20px;
}

.problem-header h2 {
  margin: 0 0 12px 0;
  font-size: 1.8rem;
  font-weight: 600;
  color: var(--ion-color-primary);
}

.problem-description {
  font-size: 1.1rem;
  line-height: 1.6;
  color: var(--ion-text-color);
  margin: 0;
}

.divider {
  border-top: 1px solid var(--ion-color-medium);
  margin: 24px 0;
}

.menus-section {
  margin-bottom: 24px;
}

.menus-section h3,
.offers-section h3 {
  font-size: 1.3rem;
  font-weight: 500;
  margin-bottom: 16px;
  color: var(--ion-color-dark);
}

.menu-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.menu-item {
  padding: 12px;
  background: var(--ion-color-light);
  border-radius: 8px;
  border-left: 4px solid var(--ion-color-primary);
}

.menu-item h4 {
  margin: 0;
  font-size: 1.1rem;
  font-weight: 500;
}

.offers-section {
  margin-bottom: 24px;
}

.offers-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 16px;
}

.offer-card {
  padding: 16px;
  background: var(--ion-color-light);
  border-radius: 8px;
  border: 1px solid var(--ion-color-medium-tint);
  transition:
    transform 0.2s,
    box-shadow 0.2s;
  position: relative;
}

.offer-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

.tier-badge {
  position: absolute;
  top: 8px;
  right: 8px;
  padding: 4px 10px;
  background: var(--ion-color-primary);
  color: white;
  border-radius: 12px;
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
}

.offer-name {
  font-size: 1.15rem;
  font-weight: 600;
  margin-bottom: 4px;
  color: var(--ion-color-dark);
  padding-right: 80px; /* Make room for tier badge */
}

.offer-subtitle {
  font-size: 0.95rem;
  color: var(--ion-color-medium-shade);
  margin-bottom: 12px;
  font-style: italic;
}

.content-items {
  margin: 12px 0;
  padding: 12px;
  background: rgba(255, 255, 255, 0.7);
  border-radius: 6px;
  border-left: 3px solid var(--ion-color-primary);
}

.content-item {
  font-size: 0.9rem;
  color: var(--ion-color-dark);
  margin-bottom: 4px;
  line-height: 1.4;
}

.more-items {
  font-size: 0.85rem;
  color: var(--ion-color-medium);
  font-style: italic;
  margin-top: 6px;
}

.no-offers {
  text-align: center;
  padding: 32px;
  color: var(--ion-color-medium);
  font-style: italic;
}
</style>