← back to Designerrepresentatives

routes/public.js

109 lines

const express = require('express');
const router = express.Router();

const { pool } = require('../lib/db');
const { sortReps, SORTS } = require('../lib/sort');

const SITE_TITLE = 'Designer Representatives';
const META_DESC = 'Designer Representatives — the canonical directory of independent sales reps serving interior designers, showrooms, contract specifiers, and the trade. Filter by territory, line, and vertical.';

router.use((req, res, next) => {
  res.locals.site_title = SITE_TITLE;
  res.locals.meta_desc = META_DESC;
  res.locals.canonical = `https://designerrepresentatives.com${req.path}`;
  res.locals.path = req.path;
  next();
});

async function fetchReps(filter) {
  const where = ['is_published = TRUE'];
  const args = [];
  if (filter && filter.territory) {
    args.push(filter.territory.toUpperCase());
    where.push(`$${args.length} = ANY(territories)`);
  }
  if (filter && filter.vertical) {
    args.push(filter.vertical);
    where.push(`$${args.length} = ANY(vertical)`);
  }
  if (filter && filter.q) {
    args.push(`%${filter.q.toLowerCase()}%`);
    where.push(
      `(LOWER(name) LIKE $${args.length} OR LOWER(agency) LIKE $${args.length} OR LOWER(city) LIKE $${args.length})`
    );
  }
  const { rows } = await pool.query(
    `SELECT id, slug, name, agency, city, territories, lines, vertical, contact_url
       FROM designer_reps
       WHERE ${where.join(' AND ')}
       ORDER BY id DESC
       LIMIT 500`,
    args
  );
  return rows;
}

router.get('/', async (req, res, next) => {
  try {
    const reps = await fetchReps({});
    const sortKey = SORTS[req.query.sort] ? req.query.sort : 'newest';
    res.render('public/home', {
      title: 'Designer Representatives — Sales Reps for Designers, Showrooms, and Contract Specifiers',
      reps: sortReps(reps, sortKey),
      total: reps.length,
      filter: {},
      sortKey,
    });
  } catch (e) { next(e); }
});

router.get('/reps', async (req, res, next) => {
  try {
    const filter = {
      territory: req.query.territory,
      vertical:  req.query.vertical,
      q:         req.query.q,
    };
    const reps = await fetchReps(filter);
    const sortKey = SORTS[req.query.sort] ? req.query.sort : 'newest';
    res.render('public/reps', {
      title: 'Browse Sales Reps — Designer Representatives',
      reps: sortReps(reps, sortKey),
      total: reps.length,
      filter,
      sortKey,
    });
  } catch (e) { next(e); }
});

router.get('/reps/:slug', async (req, res, next) => {
  try {
    const { rows } = await pool.query(
      `SELECT * FROM designer_reps WHERE slug = $1 AND is_published = TRUE LIMIT 1`,
      [req.params.slug]
    );
    if (!rows.length) return res.status(404).render('public/404', { title: 'Not found' });
    const rep = rows[0];
    res.render('public/rep', {
      title: `${rep.agency} — ${rep.name} | Designer Representatives`,
      rep,
    });
  } catch (e) { next(e); }
});

router.get('/about', (req, res) => {
  res.render('public/about', {
    title: 'About — Designer Representatives',
  });
});

router.get('/claim', (req, res) => {
  res.render('public/claim', {
    title: 'Claim or list your rep agency — Designer Representatives',
  });
});

router.get('/healthz', (req, res) => res.type('text').send('ok'));

module.exports = router;