← back to geinersito__paris-luxe-journey

Function bodies 202 total

All specs Real LLM only Function bodies
check_file function · python · L5-L33 (29 LOC)
check_encoding.py
def check_file(filepath):
    """Report all non-ASCII characters."""
    path = Path(filepath)
    data = path.read_bytes()
    
    non_ascii = []
    for i, byte in enumerate(data):
        if byte > 127:
            non_ascii.append((i, byte))
    
    if not non_ascii:
        print(f"[OK] {filepath}: pure ASCII")
        return
    
    print(f"[INFO] {filepath}: found {len(non_ascii)} non-ASCII bytes")
    
    # Group by byte value
    byte_counts = {}
    for pos, byte in non_ascii:
        byte_counts[byte] = byte_counts.get(byte, 0) + 1
    
    print(f"  Byte distribution:")
    for byte, count in sorted(byte_counts.items()):
        try:
            # Try to decode as UTF-8 continuation
            char_hex = f"0x{byte:02X}"
            print(f"    {char_hex}: {count}x")
        except:
            print(f"    0x{byte:02X}: {count}x")
normalize_char function · python · L40-L54 (15 LOC)
clean_unicode.py
def normalize_char(ch):
    if ch in IGNORE_CONTROLS:
        return ch, False
    cp = ord(ch)
    if (0xFE00 <= cp <= 0xFE0F) or (0xE0100 <= cp <= 0xE01EF):
        # Variation selectors are default-ignorable and can trigger GitHub warnings.
        return '', True
    if cp in REPLACEMENTS:
        return REPLACEMENTS[cp], True
    cat = unicodedata.category(ch)
    if cat == 'Zs':
        return ' ' if ch != ' ' else ch, ch != ' '
    if cat in SUSPICIOUS_CATEGORIES:
        return '', True
    return ch, False
clean_file function · python · L57-L99 (43 LOC)
clean_unicode.py
def clean_file(filepath):
    """Remove suspicious Unicode chars from file."""
    path = Path(filepath)
    if not path.exists():
        print(f"[ERROR] File not found: {filepath}")
        return False
    
    # Read file as bytes to preserve line endings
    try:
        data = path.read_bytes()
        content = data.decode('utf-8')
    except Exception as e:
        print(f"[ERROR] Error reading {filepath}: {e}")
        return False
    
    # Normalize content
    found = {}
    normalized = []
    for ch in content:
        replacement, changed = normalize_char(ch)
        if changed:
            cp = ord(ch)
            cat = unicodedata.category(ch)
            name = unicodedata.name(ch, 'UNKNOWN')
            key = (cp, cat, name)
            found[key] = found.get(key, 0) + 1
        normalized.append(replacement)
    normalized_text = ''.join(normalized)

    if not found:
        print(f"[OK] {filepath}: clean (no suspicious chars)")
        return False
    
    # Wri
parseDotEnvFile function · javascript · L50-L84 (35 LOC)
scripts/generate-seo.mjs
function parseDotEnvFile(filePath) {
  const parsed = {};
  if (!existsSync(filePath)) {
    return parsed;
  }

  const content = readFileSync(filePath, "utf8");
  const lines = content.split(/\r?\n/);

  for (const line of lines) {
    const trimmed = line.trim();
    if (!trimmed || trimmed.startsWith("#")) {
      continue;
    }

    const equalsIndex = trimmed.indexOf("=");
    if (equalsIndex <= 0) {
      continue;
    }

    const key = trimmed.slice(0, equalsIndex).trim();
    let value = trimmed.slice(equalsIndex + 1).trim();

    if (
      (value.startsWith('"') && value.endsWith('"')) ||
      (value.startsWith("'") && value.endsWith("'"))
    ) {
      value = value.slice(1, -1);
    }

    parsed[key] = value;
  }

  return parsed;
}
loadBuildEnvFromFiles function · javascript · L86-L93 (8 LOC)
scripts/generate-seo.mjs
function loadBuildEnvFromFiles() {
  const merged = {};
  for (const envFile of ENV_FILES_IN_PRECEDENCE) {
    const envPath = resolve(process.cwd(), envFile);
    Object.assign(merged, parseDotEnvFile(envPath));
  }
  return merged;
}
normalizeBaseUrl function · javascript · L95-L105 (11 LOC)
scripts/generate-seo.mjs
function normalizeBaseUrl(rawValue) {
  try {
    const parsed = new URL(rawValue);
    return parsed.origin;
  } catch {
    console.error(
      `ERROR: ${REQUIRED_SITE_URL_ENV} must be a valid absolute URL, got "${rawValue}".`,
    );
    process.exit(1);
  }
}
resolveBaseUrl function · javascript · L107-L131 (25 LOC)
scripts/generate-seo.mjs
function resolveBaseUrl() {
  const fileEnv = loadBuildEnvFromFiles();
  const rawSiteUrl =
    process.env[REQUIRED_SITE_URL_ENV] ?? fileEnv[REQUIRED_SITE_URL_ENV] ?? "";
  const trimmed = rawSiteUrl.trim();

  const fallback = "http://localhost:8082";

  if (!trimmed) {
    console.warn(
      `⚠️  WARNING: ${REQUIRED_SITE_URL_ENV} not set. Using fallback: ${fallback}`,
    );
    console.warn(
      `   For production builds, set ${REQUIRED_SITE_URL_ENV} in CI or .env.production (e.g. https://eliteparistransfer.com).`,
    );
    return normalizeBaseUrl(fallback);
  }

  // Basic scheme validation to avoid malformed canonicals like "eliteparistransfer.com"
  if (!/^https?:\/\//i.test(trimmed)) {
    console.warn(
      `⚠️  WARNING: ${REQUIRED_SITE_URL_ENV} is invalid (missing http/https): "${trimmed}". Using fallback: ${fallback}`,
    );
    return normalizeBaseUrl(fallback);
  }
Want fix-PRs on findings? Install Repobility's GitHub App · github.com/apps/repobility-bot
xmlEscape function · javascript · L136-L143 (8 LOC)
scripts/generate-seo.mjs
function xmlEscape(value) {
  return value
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&apos;");
}
safeIsoDate function · javascript · L145-L154 (10 LOC)
scripts/generate-seo.mjs
function safeIsoDate(value) {
  if (!value) {
    return null;
  }
  const parsed = new Date(value);
  if (Number.isNaN(parsed.getTime())) {
    return null;
  }
  return parsed.toISOString().slice(0, 10);
}
isIndexableBlogSlug function · javascript · L156-L161 (6 LOC)
scripts/generate-seo.mjs
function isIndexableBlogSlug(slug) {
  if (!slug) {
    return false;
  }
  return !BLOG_SLUG_EXCLUSIONS.some((pattern) => pattern.test(slug));
}
extractBlogCategories function · javascript · L196-L211 (16 LOC)
scripts/generate-seo.mjs
function extractBlogCategories() {
  const categoriesPath = join(
    process.cwd(),
    "src",
    "data",
    "blog",
    "categories.ts",
  );
  if (!existsSync(categoriesPath)) {
    return [];
  }

  const content = readFileSync(categoriesPath, "utf8");
  const slugRegex = /slug:\s*["']([^"']+)["']/g;
  return [...content.matchAll(slugRegex)].map((match) => match[1]);
}
dedupeUrlEntries function · javascript · L213-L222 (10 LOC)
scripts/generate-seo.mjs
function dedupeUrlEntries(entries) {
  const seen = new Set();
  return entries.filter((entry) => {
    if (seen.has(entry.loc)) {
      return false;
    }
    seen.add(entry.loc);
    return true;
  });
}
buildSitemapEntries function · javascript · L224-L239 (16 LOC)
scripts/generate-seo.mjs
function buildSitemapEntries(baseUrl) {
  const staticEntries = STATIC_ROUTES.map((path) => ({
    loc: `${baseUrl}${path}`,
  }));

  const categoryEntries = extractBlogCategories().map((categorySlug) => ({
    loc: `${baseUrl}/blog/${encodeURIComponent(categorySlug)}`,
  }));

  const postEntries = extractBlogPosts().map((post) => ({
    loc: `${baseUrl}/blog/${encodeURIComponent(post.category)}/${encodeURIComponent(post.slug)}`,
    lastmod: post.lastmod,
  }));

  return dedupeUrlEntries([...staticEntries, ...categoryEntries, ...postEntries]);
}
buildSitemapXml function · javascript · L241-L256 (16 LOC)
scripts/generate-seo.mjs
function buildSitemapXml(entries) {
  const urlBlocks = entries.map((entry) => {
    const lines = ["  <url>", `    <loc>${xmlEscape(entry.loc)}</loc>`];
    if (entry.lastmod) {
      lines.push(`    <lastmod>${entry.lastmod}</lastmod>`);
    }
    lines.push("  </url>");
    return lines.join("\n");
  });

  return `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${urlBlocks.join("\n")}
</urlset>
`;
}
buildRobotsTxt function · javascript · L258-L270 (13 LOC)
scripts/generate-seo.mjs
function buildRobotsTxt(baseUrl) {
  if (process.env[ROBOTS_NOINDEX_ENV] === "1") {
    return `User-agent: *
Disallow: /
`;
  }

  return `User-agent: *
Allow: /

Sitemap: ${baseUrl}/sitemap.xml
`;
}
Provenance: Repobility (https://repobility.com) — every score reproducible from /scan/
main function · javascript · L272-L292 (21 LOC)
scripts/generate-seo.mjs
function main() {
  const distDir = join(process.cwd(), "dist");
  if (!existsSync(distDir)) {
    console.error("ERROR: dist/ not found. Run `vite build` first.");
    process.exit(1);
  }

  const baseUrl = resolveBaseUrl();
  const sitemapEntries = buildSitemapEntries(baseUrl);
  const sitemapXml = buildSitemapXml(sitemapEntries);
  const robotsTxt = buildRobotsTxt(baseUrl);

  writeFileSync(join(distDir, "sitemap.xml"), sitemapXml, "utf8");
  writeFileSync(join(distDir, "robots.txt"), robotsTxt, "utf8");

  console.log(
    `sitemap.xml: ${sitemapEntries.length} URLs written to dist/sitemap.xml`,
  );
  console.log("robots.txt: written to dist/robots.txt");
  console.log(`Base URL: ${baseUrl}`);
}
App function · typescript · L343-L357 (15 LOC)
src/App.tsx
export default function App() {
  return (
    <HelmetProvider>
      <QueryClientProvider client={queryClient}>
        <LanguageProvider>
          <AuthProvider>
            <BookingProvider>
              <RouterProvider router={router} />
            </BookingProvider>
          </AuthProvider>
        </LanguageProvider>
      </QueryClientProvider>
    </HelmetProvider>
  );
}
AuthorBox function · typescript · L8-L37 (30 LOC)
src/components/blog/AuthorBox.tsx
export default function AuthorBox({ author }: AuthorBoxProps) {
  const { i18n } = useTranslation()
  const currentLang = i18n.language as 'en' | 'es' | 'fr' | 'pt'

  return (
    <div className="border-t border-b border-border py-6 my-8">
      <div className="flex items-start gap-4">
        {/* Avatar */}
        <img
          src={author.avatar}
          alt={author.name}
          className="w-16 h-16 rounded-full object-cover flex-shrink-0"
        />

        {/* Author Info */}
        <div className="flex-1">
          <h3 className="text-lg font-semibold text-foreground mb-1">
            {author.name}
          </h3>
          <p className="text-sm text-muted-foreground mb-2">
            {author.role[currentLang]}
          </p>
          <p className="text-sm text-foreground/80">
            {author.bio[currentLang]}
          </p>
        </div>
      </div>
    </div>
  )
}
BlogCard function · typescript · L15-L109 (95 LOC)
src/components/blog/BlogCard.tsx
export default function BlogCard({ post, featured = false }: BlogCardProps) {
  const { i18n } = useTranslation()
  const currentLang = i18n.language as 'en' | 'fr' | 'es' | 'pt'

  const category = getCategoryBySlug(post.category)

  return (
    <Card className={`group overflow-hidden glass-card-premium hover:shadow-luxury-hover transition-all duration-500 border-2 border-primary/20 hover:border-primary/40 hover:-translate-y-2 ${
      featured ? 'md:col-span-2 md:row-span-2' : ''
    }`}>
      <Link to={`/blog/${post.category}/${post.slug}`} className="block">
        {/* Cover Image */}
        <div className="relative overflow-hidden aspect-video">
          <img
            src={post.image.url}
            alt={post.image.alt[currentLang]}
            className="w-full h-full object-cover group-hover:scale-110 transition-transform duration-700"
          />
          {/* Gradient overlay on hover */}
          <div className="absolute inset-0 bg-gradient-to-br from-primary/5 via
BlogContent function · typescript · L8-L68 (61 LOC)
src/components/blog/BlogContent.tsx
export default function BlogContent({ content, children }: BlogContentProps) {
  const contentRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    if (!contentRef.current) return

    // Add IDs to headings for table of contents navigation
    const headings = contentRef.current.querySelectorAll('h2, h3')
    headings.forEach((heading) => {
      const id = heading.textContent
        ?.toLowerCase()
        .replace(/[^a-z0-9]+/g, '-')
        .replace(/(^-|-$)/g, '')

      if (id) {
        heading.id = id
      }
    })
  }, [content, children])

  // Convert markdown to HTML (basic implementation)
  const renderMarkdown = (markdown: string) => {
    let html = markdown

    // Headers
    html = html.replace(/^### (.*$)/gim, '<h3 class="text-xl font-bold mt-8 mb-4 text-foreground">$1</h3>')
    html = html.replace(/^## (.*$)/gim, '<h2 class="text-2xl font-bold mt-10 mb-6 text-foreground">$1</h2>')
    html = html.replace(/^# (.*$)/gim, '<h1 class="text-3xl font-bold mt-12 m
BlogHeader function · typescript · L14-L137 (124 LOC)
src/components/blog/BlogHeader.tsx
export default function BlogHeader({ post }: BlogHeaderProps) {
  const { i18n } = useTranslation();
  const currentLang = i18n.language as "en" | "fr" | "es" | "pt";

  const category = getCategoryBySlug(post.category);

  const handleShare = async () => {
    const shareData = {
      title: post.title[currentLang],
      text: post.description[currentLang],
      url: window.location.href,
    };

    try {
      if (navigator.share) {
        await navigator.share(shareData);
      } else {
        // Fallback: copy to clipboard
        await navigator.clipboard.writeText(window.location.href);
        toast({
          title: "Link copied!",
          description: "The article link has been copied to your clipboard.",
        });
      }
    } catch (error) {
      console.error("Error sharing:", error);
    }
  };

  return (
    <div className="relative">
      {/* Cover Image */}
      <div className="relative w-full aspect-[16/9] max-h-[420px] md:max-h-[500px] overflow-hidden 
BlogSidebar function · typescript · L23-L146 (124 LOC)
src/components/blog/BlogSidebar.tsx
export default function BlogSidebar() {
  const { t } = useTranslation();
  const navigate = useNavigate();
  const [selectedRoute, setSelectedRoute] = useState<string | null>(null);

  const popularRoutes: PopularRoute[] = [
    { from: 'CDG Airport', to: 'Paris Center', price: 85, href: '/airports/cdg' },
    { from: 'Orly Airport', to: 'Paris Center', price: 70, href: '/airports/orly' },
    { from: 'CDG Airport', to: 'Disneyland', price: 105, href: '/booking' },
    { from: 'Paris Center', to: 'Versailles', price: 85, href: '/booking' },
  ];

  const handleQuickQuote = () => {
    navigate('/booking');
  };

  const handleWhatsApp = () => {
    const message = encodeURIComponent('Hi! I need a quote for a transfer in Paris.');
    window.open(`https://wa.me/33668251102?text=${message}`, '_blank');
  };

  return (
    <aside className="space-y-6">
      {/* Quick Quote Card */}
      <Card className="border-2 border-primary/20 shadow-lg">
        <CardHeader className="bg-gradient-
Breadcrumb function · typescript · L13-L53 (41 LOC)
src/components/blog/Breadcrumb.tsx
export default function Breadcrumb({ items }: BreadcrumbProps) {
  return (
    <nav aria-label="Breadcrumb" className="py-4">
      <ol className="flex items-center flex-wrap gap-2 text-sm">
        {/* Home Icon */}
        <li>
          <Link
            to="/"
            className="flex items-center text-muted-foreground hover:text-foreground transition-colors"
          >
            <Home className="w-4 h-4" />
            <span className="sr-only">Home</span>
          </Link>
        </li>

        {/* Breadcrumb Items */}
        {items.map((item, index) => {
          const isLast = index === items.length - 1

          return (
            <li key={index} className="flex items-center gap-2">
              <ChevronRight className="w-4 h-4 text-muted-foreground" />
              {isLast || !item.href ? (
                <span className="font-medium text-foreground">
                  {item.label}
                </span>
              ) : (
                <Link
             
Generated by Repobility's multi-pass static-analysis pipeline (https://repobility.com)
CategoryFilter function · typescript · L13-L66 (54 LOC)
src/components/blog/CategoryFilter.tsx
export default function CategoryFilter({
  selectedCategory,
  onCategoryChange,
}: CategoryFilterProps) {
  const { i18n } = useTranslation()
  const currentLang = i18n.language as 'en' | 'fr' | 'es' | 'pt'

  const allCategoriesText = {
    en: 'All Articles',
    fr: 'Tous les Articles',
    es: 'Todos los Artículos',
    pt: 'Todos os Artigos',
  }

  return (
    <div className="flex flex-wrap gap-3 justify-center">
      {/* All Categories Button - Premium Style */}
      <Button
        variant={selectedCategory === 'all' ? 'default' : 'outline'}
        onClick={() => onCategoryChange('all')}
        className={cn(
          'transition-all duration-300 font-semibold',
          selectedCategory === 'all'
            ? 'silk-button shadow-lg'
            : 'button-outline-gold hover:scale-105'
        )}
      >
        {allCategoriesText[currentLang]}
      </Button>

      {/* Category Buttons - Premium Style */}
      {blogCategories.map((category) => {
        const IconCom
FinalCTA function · typescript · L7-L76 (70 LOC)
src/components/blog/FinalCTA.tsx
export default function FinalCTA() {
  const { t } = useTranslation();
  const [isModalOpen, setIsModalOpen] = useState(false);

  const benefits = [
    t("blog.professionalService") || "Professional chauffeur service",
    t("blog.freeCancellation") || "Free cancellation up to 24h",
    t("blog.flightMonitoring") || "Flight monitoring included",
    t("blog.premiumVehicles") || "Premium vehicles (Mercedes, BMW)",
  ];

  return (
    <>
      <div className="bg-gradient-to-br from-primary/10 via-primary/5 to-transparent border border-primary/20 rounded-2xl p-8 md:p-12 my-12">
        <div className="grid md:grid-cols-2 gap-8 items-center">
          {/* Text Content */}
          <div>
            <h2 className="text-3xl md:text-4xl font-bold text-foreground mb-4">
              {t("blog.readyToBook") || "Ready to Book Your Transfer?"}
            </h2>
            <p className="text-muted-foreground mb-6">
              Experience hassle-free airport transfers with our professional
InlineBookingCTA function · typescript · L7-L49 (43 LOC)
src/components/blog/InlineBookingCTA.tsx
export default function InlineBookingCTA() {
  const { t } = useTranslation();
  const [isModalOpen, setIsModalOpen] = useState(false);

  return (
    <>
      <div className="bg-secondary/10 border border-primary/20 rounded-lg p-6 my-8">
        <div className="flex items-center gap-4">
          <div className="flex-shrink-0">
            <div className="w-12 h-12 bg-primary/10 rounded-full flex items-center justify-center">
              <Car className="w-6 h-6 text-primary" />
            </div>
          </div>
          <div className="flex-1">
            <h3 className="text-lg font-semibold text-foreground mb-1">
              {t("blog.needTransfer") || "Need a transfer?"}
            </h3>
            <p className="text-sm text-muted-foreground">
              {t("blog.calculatePrice") ||
                "Get an instant quote for your airport transfer"}
            </p>
          </div>
          <Button
            onClick={() => setIsModalOpen(true)}
            className="
NewsletterCTA function · typescript · L8-L137 (130 LOC)
src/components/blog/NewsletterCTA.tsx
export default function NewsletterCTA() {
  const { t, i18n } = useTranslation()
  const { toast } = useToast()
  const [email, setEmail] = useState('')
  const [isLoading, setIsLoading] = useState(false)

  const handleSubmit = async (e: FormEvent) => {
    e.preventDefault()

    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
    if (!email || !emailRegex.test(email)) {
      toast({
        title: t('exitPopup.invalidEmail'),
        variant: 'destructive',
      })
      return
    }

    setIsLoading(true)

    try {
      const supabaseUrl = import.meta.env.VITE_SUPABASE_URL
      const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY

      const isConfigured =
        supabaseUrl &&
        supabaseAnonKey &&
        !supabaseAnonKey.includes('temporary') &&
        !supabaseAnonKey.includes('your_')

      if (!isConfigured) {
        console.warn('⚠️ Supabase not configured. Using demo mode.')
        toast({
          title: t('exitPopup.success'),
          descrip
RelatedPosts function · typescript · L12-L45 (34 LOC)
src/components/blog/RelatedPosts.tsx
export default function RelatedPosts({ currentPostId, category, maxPosts = 3 }: RelatedPostsProps) {
  const { t } = useTranslation()

  // Get posts from same category, excluding current post
  const categoryPosts = getPostsByCategory(category)
    .filter((post) => post.id !== currentPostId)
    .slice(0, maxPosts)

  // If not enough posts in category, fill with other posts
  const relatedPosts = categoryPosts.length < maxPosts
    ? [
        ...categoryPosts,
        ...blogPosts
          .filter((post) => post.id !== currentPostId && post.category !== category)
          .slice(0, maxPosts - categoryPosts.length),
      ]
    : categoryPosts

  if (relatedPosts.length === 0) return null

  return (
    <section className="py-16 mt-16 border-t">
      <h2 className="text-3xl font-bold text-foreground mb-8">
        {t('blog.relatedArticles') || 'Related Articles'}
      </h2>

      <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
        {relatedPosts.map((
ShareButtons function · typescript · L12-L105 (94 LOC)
src/components/blog/ShareButtons.tsx
export default function ShareButtons({ title, url }: ShareButtonsProps) {
  const { t } = useTranslation()
  const { toast } = useToast()
  const [isOpen, setIsOpen] = useState(false)

  const shareUrl = url || window.location.href
  const encodedUrl = encodeURIComponent(shareUrl)
  const encodedTitle = encodeURIComponent(title)

  const handleCopyLink = async () => {
    try {
      await navigator.clipboard.writeText(shareUrl)
      toast({
        title: t('blog.linkCopied') || 'Link copied!',
        description: t('blog.copySuccess') || 'The link has been copied to your clipboard.',
        duration: 3000,
      })
    } catch (error) {
      toast({
        title: t('blog.copyError') || 'Error',
        description: 'Failed to copy link. Please try again.',
        variant: 'destructive',
      })
    }
  }

  const shareLinks = [
    {
      name: 'WhatsApp',
      icon: MessageCircle,
      url: `https://wa.me/?text=${encodedTitle}%20${encodedUrl}`,
      color: 'hover:bg-green
TableOfContents function · typescript · L10-L118 (109 LOC)
src/components/blog/TableOfContents.tsx
export default function TableOfContents({ items: propItems }: TableOfContentsProps) {
  const [activeId, setActiveId] = useState<string>('')
  const [items, setItems] = useState<TableOfContentsItem[]>(propItems || [])

  // Auto-generate TOC from DOM if items not provided
  useEffect(() => {
    if (propItems && propItems.length > 0) {
      setItems(propItems)
      return
    }

    // Generate TOC from headings in the document
    const headings = document.querySelectorAll('article h2, article h3, main h2, main h3')
    const generatedItems: TableOfContentsItem[] = []

    headings.forEach((heading) => {
      const id = heading.id || heading.textContent
        ?.toLowerCase()
        .replace(/[^a-z0-9]+/g, '-')
        .replace(/(^-|-$)/g, '') || ''

      if (!heading.id && id) {
        heading.id = id
      }

      if (id) {
        generatedItems.push({
          id,
          title: heading.textContent || '',
          level: parseInt(heading.tagName.substring(1)),
        
BookingConfirmation function · typescript · L11-L21 (11 LOC)
src/components/BookingConfirmation.tsx
export function BookingConfirmation({ bookingId, bookingData, tourData }: BookingConfirmationProps) {
  const { t } = useLanguage();

  return (
    <div className="space-y-6">
      <h2 className="text-2xl font-bold">{t.booking.success.title}</h2>
      <p>{t.booking.success.description}</p>
      {/* Add more booking confirmation details */}
    </div>
  );
}
Methodology: Repobility · https://repobility.com/research/state-of-ai-code-2026/
CouponInput function · typescript · L9-L103 (95 LOC)
src/components/booking/CouponInput.tsx
export default function CouponInput() {
  const { t } = useTranslation()
  const { coupon, validateCoupon, removeCoupon } = useBooking()
  const [code, setCode] = useState('')
  const [isValidating, setIsValidating] = useState(false)

  const handleApply = async () => {
    if (!code.trim()) return

    setIsValidating(true)
    await validateCoupon(code.trim())
    setIsValidating(false)
    setCode('') // Clear input after validation
  }

  const handleKeyPress = (e: React.KeyboardEvent) => {
    if (e.key === 'Enter') {
      e.preventDefault()
      handleApply()
    }
  }

  // If coupon is already applied, show it
  if (coupon?.valid) {
    return (
      <div className="space-y-2">
        <label className="text-sm font-medium text-foreground flex items-center gap-2">
          <Tag className="w-4 h-4" />
          {t('booking.coupon.label')}
        </label>
        <div className="flex items-center gap-2 p-3 bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-
DestinationContent function · typescript · L15-L25 (11 LOC)
src/components/destination/DestinationContent.tsx
export function DestinationContent({ activeSection, content }: DestinationContentProps) {
  return (
    <div className="py-8">
      {activeSection === 'description' && content.description}
      {activeSection === 'tours' && content.tours}
      {activeSection === 'map' && content.map}
      {activeSection === 'events' && content.events}
      {activeSection === 'faq' && content.faq}
    </div>
  );
}
DestinationHeader function · typescript · L12-L31 (20 LOC)
src/components/destination/DestinationHeader.tsx
export function DestinationHeader({ title, image, distance, duration, currentPath }: DestinationHeaderProps) {
  return (
    <header className="relative h-[60vh] min-h-[400px] w-full">
      <div className="absolute inset-0">
        <img src={image} alt={title} className="w-full h-full object-cover" />
        <div className="absolute inset-0 bg-black/50" />
      </div>
      <div className="absolute inset-0 flex items-center justify-center text-white">
        <div className="text-center">
          <h1 className="text-4xl md:text-5xl font-display mb-4">{title}</h1>
          <div className="flex items-center justify-center gap-4 text-sm">
            <span>{distance}</span>
            <span>•</span>
            <span>{duration}</span>
          </div>
        </div>
      </div>
    </header>
  );
}
DestinationNavigation function · typescript · L10-L32 (23 LOC)
src/components/destination/DestinationNavigation.tsx
export function DestinationNavigation({ items, activeSection, onSectionChange }: DestinationNavigationProps) {
  return (
    <nav className="sticky top-0 z-10 bg-white dark:bg-gray-800 border-b border-border">
      <div className="container mx-auto px-4">
        <div className="flex overflow-x-auto">
          {items.map((item) => (
            <button
              key={item.id}
              onClick={() => onSectionChange(item.id)}
              className={`px-4 py-3 text-sm whitespace-nowrap border-b-2 transition-colors ${
                activeSection === item.id
                  ? 'border-primary text-primary'
                  : 'border-transparent text-muted-foreground hover:text-primary'
              }`}
            >
              {item.label}
            </button>
          ))}
        </div>
      </div>
    </nav>
  );
}
DestinationSidebar function · typescript · L9-L18 (10 LOC)
src/components/destination/DestinationSidebar.tsx
export function DestinationSidebar({ children, tours }: DestinationSidebarProps) {
  return (
    <aside className="space-y-8">
      {children}
      <div className="sticky top-24">
        {tours}
      </div>
    </aside>
  );
}
ExcursionCard function · typescript · L16-L52 (37 LOC)
src/components/excursions/ExcursionCard.tsx
export function ExcursionCard({
  title,
  description,
  image,
  duration,
  price,
  link
}: ExcursionCardProps) {
  const { t } = useLanguage();

  return (
    <Card className="overflow-hidden">
      <div className="relative h-48 overflow-hidden">
        <img
          src={image}
          alt={title}
          className="w-full h-full object-cover"
        />
      </div>
      <CardContent className="p-4">
        <h3 className="text-xl font-semibold mb-2">{title}</h3>
        <p className="text-muted-foreground text-sm mb-4">{description}</p>
        <div className="flex justify-between items-center">
          <span className="text-sm">{duration}</span>
          <span className="font-semibold">{`€${price}`}</span>
        </div>
      </CardContent>
      <CardFooter className="p-4 pt-0">
        <Link to={link} className="w-full">
          <Button className="w-full">
            {t.excursions.viewDetails}
          </Button>
        </Link>
      </CardFooter>
    </Card
ExcursionFilters function · typescript · L22-L93 (72 LOC)
src/components/excursions/ExcursionFilters.tsx
export function ExcursionFilters({
  searchQuery,
  setSearchQuery,
  selectedDuration,
  setSelectedDuration,
  selectedType,
  setSelectedType
}: ExcursionFiltersProps) {
  const { t } = useLanguage();
  
  const handleClearFilters = () => {
    setSearchQuery("");
    setSelectedDuration(null);
    setSelectedType(null);
  };
  
  return (
    <div className="flex flex-col md:flex-row gap-4 p-4 bg-white rounded-lg shadow-sm">
      <div className="flex-1">
        <Input
          type="text"
          placeholder={t.excursions.searchPlaceholder}
          value={searchQuery}
          onChange={(e) => setSearchQuery(e.target.value)}
          className="w-full"
        />
      </div>

      <div className="w-full md:w-48">
        <Select
          value={selectedDuration ?? ""}
          onValueChange={(value) => setSelectedDuration(value as DurationType || null)}
        >
          <SelectTrigger>
            <SelectValue placeholder={t.excursions.filters.allDurations} />
     
HashScroll function · typescript · L4-L32 (29 LOC)
src/components/HashScroll.tsx
export function HashScroll() {
  const location = useLocation();

  useEffect(() => {
    if (!location.hash) return;

    const id = location.hash.slice(1);

    // Use requestAnimationFrame for SPA-safe scroll after DOM paint
    requestAnimationFrame(() => {
      const element = document.getElementById(id);
      if (!element) return;

      // Get navbar height for proper offset
      const navbar = document.querySelector("nav");
      const headerOffset = navbar?.getBoundingClientRect().height ?? 80;
      const elementPosition = element.getBoundingClientRect().top;
      const offsetPosition =
        elementPosition + window.scrollY - headerOffset - 8;

      window.scrollTo({
        top: offsetPosition,
        behavior: "smooth",
      });
    });
  }, [location.hash, location.pathname]);

  return null;
}
Want fix-PRs on findings? Install Repobility's GitHub App · github.com/apps/repobility-bot
LanguageChangeNotification function · typescript · L5-L24 (20 LOC)
src/components/LanguageChangeNotification.tsx
export function LanguageChangeNotification() {
  const { language, t } = useLanguage();
  const prevLanguageRef = React.useRef(language);

  React.useEffect(() => {
    if (prevLanguageRef.current !== language) {
      const message = t.toast?.languageChanged || 'Language changed successfully';
      // Usar setTimeout para asegurar que el toast se muestre después de que el DOM se actualice
      setTimeout(() => {
        toast({
          title: message,
          duration: 2000,
        });
      }, 0);
      prevLanguageRef.current = language;
    }
  }, [language, t.toast?.languageChanged]);

  return null;
}
LanguageSelector function · typescript · L20-L63 (44 LOC)
src/components/LanguageSelector.tsx
export function LanguageSelector() {
  const { i18n } = useTranslation();
  const { setLanguage } = useLanguage();

  const handleLanguageChange = (value: Language) => {
    setLanguage(value);
  };

  const currentLanguage = useMemo(
    () => languages.find((lang) => lang.code === i18n.language),
    [i18n.language],
  );

  if (!currentLanguage) return null;

  return (
    <Select value={i18n.language} onValueChange={handleLanguageChange}>
      <SelectTrigger className="w-[110px] h-10 px-3">
        <SelectValue>
          <span className="flex items-center gap-2">
            <span className="text-base">{currentLanguage.flag}</span>
            <span className="font-medium uppercase text-xs tracking-wide">
              {currentLanguage.code}
            </span>
          </span>
        </SelectValue>
      </SelectTrigger>
      <SelectContent>
        {languages.map((language) => (
          <SelectItem
            key={language.code}
            value={language.code}
        
Layout function · typescript · L10-L24 (15 LOC)
src/components/Layout.tsx
export function Layout() {
  return (
    <div className="min-h-screen flex flex-col bg-background text-foreground antialiased transition-colors duration-300">
      <HashScroll />
      <Navbar />
      <main className="flex-1 pt-16 pb-20 lg:pb-0">
        <Outlet />
      </main>
      <Footer />
      <FloatingWhatsApp />
      <CookieConsent />
      <ExitIntentPopup />
    </div>
  );
}
MobileStickyCTA function · typescript · L10-L33 (24 LOC)
src/components/MobileStickyCTA.tsx
export default function MobileStickyCTA({
  label,
  onClick,
  isVisible,
}: MobileStickyCTAProps) {
  if (!isVisible) return null;

  return (
    <div
      className="fixed bottom-0 left-0 right-0 z-40 lg:hidden border-t border-primary/20 bg-white/95 backdrop-blur-sm"
      style={{ paddingBottom: "env(safe-area-inset-bottom, 0px)" }}
    >
      <div className="px-4 py-3">
        <button
          onClick={onClick}
          className="silk-button w-full flex items-center justify-center gap-2 min-h-[48px] text-sm"
        >
          {label}
          <ArrowRight className="w-4 h-4" />
        </button>
      </div>
    </div>
  );
}
PaymentForm function · typescript · L13-L32 (20 LOC)
src/components/PaymentForm.tsx
export function PaymentForm({ bookingData, onSubmit, isProcessing, error }: FormProps) {
  const { t } = useLanguage();

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    onSubmit(bookingData);
  };

  return (
    <form onSubmit={handleSubmit} className="space-y-6">
      {/* Payment form content */}
      {error && (
        <div className="text-red-500">{error}</div>
      )}
      <Button type="submit" disabled={isProcessing}>
        {isProcessing ? t.common.processing : t.booking.payment.title}
      </Button>
    </form>
  );
}
RouteHighlights function · typescript · L13-L170 (158 LOC)
src/components/RouteHighlights.tsx
export default function RouteHighlights() {
  const { t } = useLanguage();

  const popularRoutes = [
    {
      icon: Plane,
      title: t.routes?.cdg || "CDG Airport",
      description: t.routes?.cdgDesc || "Paris ⇄ Charles de Gaulle",
      priceFrom: "70",
      bgGradient: "from-primary/5 to-primary/10",
    },
    {
      icon: Plane,
      title: t.routes?.orly || "Orly Airport",
      description: t.routes?.orlyDesc || "Paris ⇄ Orly",
      priceFrom: "60",
      bgGradient: "from-primary/5 to-primary/10",
    },
    {
      icon: Castle,
      title: t.routes?.disney || "Disneyland Paris",
      description: t.routes?.disneyDesc || "Magical day trip",
      priceFrom: "95",
      bgGradient: "from-primary/5 to-primary/10",
    },
    {
      icon: Crown,
      title: t.routes?.versailles || "Versailles",
      description: t.routes?.versaillesDesc || "Royal palace tour",
      priceFrom: "75",
      bgGradient: "from-primary/5 to-primary/10",
    },
  ];

  const handleRout
JsonLd function · typescript · L10-L18 (9 LOC)
src/components/seo/JsonLd.tsx
export default function JsonLd({ data }: JsonLdProps) {
  return (
    <Helmet>
      <script type="application/ld+json">
        {JSON.stringify(data)}
      </script>
    </Helmet>
  )
}
ServiceCard function · typescript · L13-L48 (36 LOC)
src/components/ServiceCard.tsx
export default function ServiceCard({ 
  title, 
  description, 
  icon: Icon, 
  price,
  className 
}: ServiceCardProps) {
  return (
    <div className={cn(
      "group relative overflow-hidden rounded-lg bg-white/80 dark:bg-gray-800/80 backdrop-blur-lg shadow-lg hover:shadow-xl transition-all duration-300 p-8 border border-primary/10",
      className
    )}>
      <div className="absolute inset-0 bg-gradient-to-b from-primary/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
      
      <div className="relative z-10 flex flex-col items-center">
        <div className="w-14 h-14 bg-primary/10 rounded-full flex items-center justify-center mb-6 group-hover:scale-110 transition-transform duration-300">
          <Icon className="h-7 w-7 text-primary" />
        </div>
        
        <h3 className="text-xl font-semibold text-primary dark:text-primary-foreground mb-4 text-center group-hover:text-primary/90 transition-colors">
          {title}
  
Provenance: Repobility (https://repobility.com) — every score reproducible from /scan/
TestEmail function · typescript · L21-L121 (101 LOC)
src/components/TestEmail.tsx
export function TestEmail() {
  const [response, setResponse] = useState<EmailResponse | null>(null);
  const [loading, setLoading] = useState(false);
  const { toast } = useToast();

  const handleTestEmail = async () => {
    setLoading(true);
    try {
      const { data, error } = await supabase.functions.invoke('send-booking-emails', {
        body: {
          customerName: "Geiner Boris",
          customerEmail: "[email protected]",
          bookingId: "TEST-" + new Date().getTime(),
          pickupLocation: "Charles de Gaulle Airport (CDG)",
          dropoffLocation: "Eiffel Tower",
          pickupDateTime: new Date().toISOString(),
          passengers: 2,
          vehicleType: "Luxury Sedan",
          totalPrice: 150,
          flightNumber: "AF123"
        }
      });

      if (error) {
        console.error('Error details:', error);
        throw error;
      }

      setResponse(data);
      toast({
        title: "Email enviado",
        description: "El email
TourCard function · typescript · L14-L38 (25 LOC)
src/components/TourCard.tsx
export function TourCard({ title, description, duration, price, includes, onBook }: TourCardProps) {
  return (
    <div className="bg-white dark:bg-gray-800 rounded-lg shadow-lg p-6">
      <h3 className="text-xl font-display text-primary dark:text-primary-foreground mb-2">{title}</h3>
      <p className="text-muted-foreground mb-4">{description}</p>
      <div className="flex items-center justify-between mb-4">
        <span className="text-sm text-muted-foreground">{duration}</span>
        <span className="text-lg font-semibold">€{price}</span>
      </div>
      <div className="space-y-2 mb-4">
        {includes.map((item, index) => (
          <div key={index} className="flex items-center text-sm text-muted-foreground">
            <span className="mr-2">•</span>
            {item}
          </div>
        ))}
      </div>
      {onBook && (
        <Button onClick={onBook} className="w-full">
          Book Now
        </Button>
      )}
    </div>
  );
}
TrustBar function · typescript · L10-L65 (56 LOC)
src/components/TrustBar.tsx
export default function TrustBar() {
  const { t } = useLanguage();

  const trustItems = [
    {
      icon: ShieldCheck,
      label: t.trustBar?.securePayment || "Secure Payment",
      description: t.trustBar?.securePaymentDesc || "SSL encrypted",
    },
    {
      icon: Award,
      label: t.trustBar?.licensed || "Licensed & Insured",
      description: t.trustBar?.licensedDesc || "Official VTC license",
    },
    {
      icon: Clock,
      label: t.trustBar?.available || "24/7 Available",
      description: t.trustBar?.availableDesc || "Always at your service",
    },
    {
      icon: Shield,
      label: t.trustBar?.insurance || "Full Insurance",
      description: t.trustBar?.insuranceDesc || "Complete coverage",
    },
  ];

  return (
    <div className="w-full bg-accent/50 border-t border-b border-border py-6 px-4">
      <div className="container max-w-4xl mx-auto">
        <div className="grid grid-cols-2 md:grid-cols-4 gap-4 md:gap-6">
          {trustItems.map((item, 
page 1 / 5next ›