Skip to content

Tours & Activities - Requirements & Frontend Specification

Overview

Standalone tours and activities search page accessible from Products > Tours & Activities in the admin interface. Integrates with Tiqets to browse experiences and products by country and city, with tag-based filtering and text search.

Files: - tqweb-adm/activities.html - Page structure - tqweb-adm/js/modules/activities-search.js - JavaScript ES6 module - tqweb-adm/css/tqadmin.css - Experience card, product card, dialog, and tag chip styles

Background

The Tiqets integration was previously available in two places: - Public site (tqweb-pub/uae-experiences.html) - hardcoded to UAE, uses Foundation CSS - TripMaker (tqweb-adm/tripmaker-activities.html) - tied to project/itinerary context

This standalone page makes the Tiqets catalog browsable for any country/city without requiring a TripMaker project.

Requirements

Functional Requirements

ID Requirement Status
TA-01 Country selection from Tiqets-supported countries Implemented
TA-02 City selection filtered by selected country (enabled cities only) Implemented
TA-03 Experience card grid with images, ratings, and prices Implemented
TA-04 Tag-based filtering (Activity, Venue, Service categories) Implemented
TA-05 Real-time text search filtering by experience name Implemented
TA-06 Experience detail modal with product listing Implemented
TA-07 Product cards with pricing and discount display Implemented
TA-08 "Book Now" button opening Tiqets product page in new tab Implemented
TA-09 "Add to Cart" button (placeholder for future cart integration) Placeholder
TA-10 Sort experiences by rating (descending), then review count Implemented
TA-11 Tag strip filtered to only show tags present in current results Implemented

Non-Functional Requirements

  • No dependency on TripMaker modules
  • All API calls go through tlinq() directly
  • Authentication required (agent/admin roles)
  • All Tiqets API endpoints already permit guest/agent/admin access

Architecture

activities.html
    ↓ imports
activities-search.js
    ↓ calls via tlinq()
┌──────────────────────────────────┐
│ tiqets/countries    (dropdown)   │
│ tiqets/cities       (dropdown)   │
│ tiqets/experiences  (card grid)  │
│ tiqets/products     (modal)      │
│ tiqets/tags         (tag strip)  │
└──────────────────────────────────┘

API Wrapper

ActivitiesAPI object in activities-search.js:

Method Endpoint Purpose
listCountries() tiqets/countries Populate country dropdown
listCities(countryId) tiqets/cities Populate city dropdown (enabledOnly=true)
listExperiences(cityId) tiqets/experiences Load experience cards for city
listProducts(experienceId) tiqets/products Load products for experience modal
listTags(typeGroupName) tiqets/tags Load tag chips (3 type groups)

User Interface

Filter Panel

Collapsible card with: - Row 1: Country dropdown | City dropdown (disabled until country selected) | Search text input - Row 2: Tag strip — horizontal scrollable chips ("All" + filtered category tags)

Experience Grid

Bootstrap responsive grid (col-6 col-md-4 col-lg-3) of experience cards. Each card shows: - Experience image (or placeholder) - Title (2-line clamp) - Tagline (2-line clamp) - Star rating with numeric value and review count - Price: "Starting from [currency] [amount]" or "Check availability"

Cards are clickable — clicking opens the product modal.

Product Modal

Bootstrap 5 large modal (modal-xl) with: - Hero section: Full-width background image with gradient overlay and experience title - Description: Experience description/summary text - Product cards grid: Each product shows image, title, tagline, rating, price (with discount handling), and two action buttons: - "Book Now" — Opens Tiqets product detail page in new tab - "Add to Cart" — Placeholder with toast notification

Tag Filtering

Tags are loaded from three Tiqets type groups in parallel: 1. Activity categories 2. Venue categories 3. Service categories

After experiences load, the tag strip is filtered to only show tags that appear in the current results. Tag matching checks: tagIds (array or comma-separated), tags array objects, and text search in title/tagline/category.

Price Display

  • Experience cards: "Starting from [currency] [price]" or "Check availability" if no price
  • Product cards: Handles discount display — if prediscountPrice > retailPrice, original price is shown struck-through with discounted price in red. Otherwise, normal price in blue.

CSS Classes

Styles added to tqadmin.css (prefixed exp-card-, product-card-, dialog-, tag-chip):

Class Purpose
.exp-card Experience card container (hover lift, shadow)
.exp-card-image Fixed-height responsive image
.exp-card-content Flex column: title, tagline, rating, price
.exp-card-title / .exp-card-tagline 2-line clamped text
.exp-card-rating Star display with rating number and count
.exp-card-price Price with "Starting from" label
.product-card Product card in modal
.product-card-price Handles original/discount/normal price display
.dialog-hero Background image with gradient overlay
.dialog-description Description text section
.tag-chip Clickable pill badge with active state