> ## Documentation Index
> Fetch the complete documentation index at: https://docs.roomdoo.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Change reservation dates

> Change a reservation's check-in and check-out, review the price of the new nights and what to do if the reservation comes from an OTA.

export const Course = ({view, lang = 'es', slug, mod, title, subtitle, totalMin}) => {
  const LESSONS = [{
    slug: 'discover-roomdoo',
    mod: 0,
    min: 7,
    es: 'Descubre Roomdoo en un vistazo',
    en: 'Discover Roomdoo at a glance'
  }, {
    slug: 'how-reservations-work',
    mod: 1,
    min: 4,
    es: 'Cómo funcionan las reservas',
    en: 'How reservations work'
  }, {
    slug: 'create-direct-reservation',
    mod: 1,
    min: 3,
    es: 'Crear una reserva directa',
    en: 'Create a direct reservation'
  }, {
    slug: 'room-change-split-reselling',
    mod: 1,
    min: 2,
    es: 'Cambiar de habitación y reselling',
    en: 'Change rooms and reselling'
  }, {
    slug: 'check-in-check-out',
    mod: 1,
    min: 4,
    es: 'Check-in y check-out',
    en: 'Check-in and check-out'
  }, {
    slug: 'change-dates',
    mod: 1,
    min: 2,
    es: 'Cambiar fechas',
    en: 'Change dates'
  }, {
    slug: 'services-and-board',
    mod: 2,
    min: 4,
    es: 'Servicios y régimen',
    en: 'Services and board'
  }, {
    slug: 'invoices-and-payments',
    mod: 3,
    min: 4,
    es: 'Facturas y cobros',
    en: 'Invoices and payments'
  }, {
    slug: 'cash-register',
    mod: 3,
    min: 2,
    es: 'Control de caja',
    en: 'Cash control'
  }, {
    slug: 'rates-and-restrictions',
    mod: 4,
    min: 9,
    es: 'Tarifas y restricciones',
    en: 'Rates and restrictions'
  }];
  const MODULES = {
    es: ['Introducción', 'Reservas', 'Servicios', 'Facturas y cobros', 'Tarifas y restricciones'],
    en: ['Introduction', 'Reservations', 'Services', 'Invoices and payments', 'Rates and restrictions']
  };
  const TEXT = {
    es: {
      course: 'Curso en vídeo',
      lessons: 'lecciones',
      lesson: 'Lección',
      of: 'de',
      min: 'min',
      start: 'Empezar el curso',
      continue: 'Continuar con la lección',
      review: 'Repasar el curso',
      seen: 'lecciones vistas',
      allSeen: '¡Has visto todo el curso!',
      prev: 'Lección anterior',
      next: 'Siguiente lección',
      nextModule: 'Siguiente módulo',
      back: 'Volver al curso',
      markDone: 'Marcar lección como vista',
      done: 'Lección vista',
      finish: 'Has terminado el curso',
      finishText: 'Repasa cualquier lección cuando quieras o consulta las guías.',
      seenBadge: 'Vista',
      reset: 'Reiniciar progreso',
      prevShort: 'Anterior',
      nextShort: 'Siguiente',
      overview: 'Índice del curso'
    },
    en: {
      course: 'Video course',
      lessons: 'lessons',
      lesson: 'Lesson',
      of: 'of',
      min: 'min',
      start: 'Start the course',
      continue: 'Continue with lesson',
      review: 'Review the course',
      seen: 'lessons seen',
      allSeen: "You've seen the whole course!",
      prev: 'Previous lesson',
      next: 'Next lesson',
      nextModule: 'Next module',
      back: 'Back to the course',
      markDone: 'Mark lesson as seen',
      done: 'Lesson seen',
      finish: "You've finished the course",
      finishText: 'Review any lesson whenever you like or check the guides.',
      seenBadge: 'Seen',
      reset: 'Reset progress',
      prevShort: 'Previous',
      nextShort: 'Next',
      overview: 'Course overview'
    }
  };
  const KEY = 'roomdoo-course-v1';
  const EVENT = 'roomdoo-course';
  const t = TEXT[lang] || TEXT.es;
  const total = LESSONS.length;
  const readSeen = () => {
    try {
      const v = JSON.parse(window.localStorage.getItem(KEY) || '[]');
      return Array.isArray(v) ? v : [];
    } catch (e) {
      return [];
    }
  };
  const writeSeen = list => {
    try {
      window.localStorage.setItem(KEY, JSON.stringify(list));
      window.dispatchEvent(new Event(EVENT));
    } catch (e) {}
  };
  const [seen, setSeen] = useState([]);
  useEffect(() => {
    const load = () => setSeen(readSeen());
    load();
    window.addEventListener(EVENT, load);
    window.addEventListener('storage', load);
    return () => {
      window.removeEventListener(EVENT, load);
      window.removeEventListener('storage', load);
    };
  }, []);
  const svg = (size, width, paths) => <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={width} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      {paths.map(d => <path key={d} d={d} />)}
    </svg>;
  const arrowRight = (size = 18) => svg(size, 2.2, ['M5 12h14', 'm12 5 7 7-7 7']);
  const arrowLeft = (size = 18) => svg(size, 2.2, ['M19 12H5', 'm12 19-7-7 7-7']);
  const checkIcon = (size = 16) => svg(size, 3, ['M20 6 9 17l-5-5']);
  const lessonUrl = l => `/${lang}/course/${l.slug}`;
  const courseUrl = `/${lang}/course`;
  if (view === 'hero') {
    const done = LESSONS.filter(l => seen.includes(l.slug)).length;
    const nextIdx = LESSONS.findIndex(l => !seen.includes(l.slug));
    const target = nextIdx === -1 ? LESSONS[0] : LESSONS[nextIdx];
    const label = done === 0 ? t.start : nextIdx === -1 ? t.review : `${t.continue} ${nextIdx + 1}`;
    const pct = Math.round(done / total * 100);
    return <div className="course-owns-nav not-prose relative overflow-hidden rounded-3xl border border-zinc-950/10 dark:border-white/10 bg-gradient-to-br from-primary/10 via-white to-white dark:from-primary/20 dark:via-zinc-950 dark:to-zinc-950 px-6 py-10 sm:px-10 sm:py-12">
        <p className="text-sm font-semibold uppercase tracking-wide text-primary dark:text-primary-light">
          {t.course} · {total} {t.lessons} · {totalMin} {t.min}
        </p>
        <h2 className="mt-3 text-3xl sm:text-4xl font-bold tracking-tight text-zinc-950 dark:text-white">{title}</h2>
        <p className="mt-4 max-w-2xl text-lg text-zinc-600 dark:text-zinc-400">{subtitle}</p>
        <div className="mt-8 flex flex-wrap items-center gap-4">
          <a href={lessonUrl(target)} className="inline-flex items-center gap-2 rounded-full bg-primary px-7 py-3.5 text-base font-semibold text-white shadow-lg shadow-primary/30 transition hover:opacity-90 no-underline">
            {label} {arrowRight()}
          </a>
          {done > 0 && <button type="button" onClick={() => writeSeen([])} className="text-sm text-zinc-500 underline-offset-4 hover:underline dark:text-zinc-400">
              {t.reset}
            </button>}
        </div>
        {done > 0 && <div className="mt-6 max-w-md">
            <div className="flex justify-between text-sm text-zinc-600 dark:text-zinc-400">
              <span>{done === total ? t.allSeen : `${done} ${t.of} ${total} ${t.seen}`}</span>
              <span>{pct}%</span>
            </div>
            <div className="mt-2 h-2 w-full overflow-hidden rounded-full bg-zinc-950/10 dark:bg-white/10">
              <div className="h-full rounded-full bg-primary transition-all" style={{
      width: `${pct}%`
    }} />
            </div>
          </div>}
      </div>;
  }
  if (view === 'module') {
    return <div className="not-prose grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
        {LESSONS.map((l, i) => ({
      ...l,
      n: i + 1
    })).filter(l => l.mod === mod).map(l => <a key={l.slug} href={lessonUrl(l)} className="group block overflow-hidden rounded-2xl border border-zinc-950/10 bg-white transition hover:border-primary hover:shadow-md dark:border-white/10 dark:bg-zinc-900 dark:hover:border-primary-light no-underline">
            <div className="relative aspect-video overflow-hidden bg-zinc-100 dark:bg-zinc-800">
              <img src={`/images/curso/leccion-${String(l.n).padStart(2, '0')}.webp`} alt="" className="h-full w-full object-cover transition duration-300 group-hover:scale-105" />
              <span className="absolute bottom-2 right-2 rounded-md bg-black/75 px-2 py-0.5 text-xs font-medium text-white">{l.min} {t.min}</span>
              {seen.includes(l.slug) && <span className="absolute left-2 top-2 inline-flex items-center gap-1 rounded-full bg-green-600 px-2.5 py-1 text-xs font-semibold text-white">{checkIcon(12)} {t.seenBadge}</span>}
            </div>
            <div className="p-4">
              <span className="block text-xs font-semibold uppercase tracking-wide text-primary dark:text-primary-light">{t.lesson} {l.n}</span>
              <span className="mt-1 block font-semibold text-zinc-950 group-hover:text-primary dark:text-white dark:group-hover:text-primary-light">{l[lang]}</span>
            </div>
          </a>)}
      </div>;
  }
  const i = LESSONS.findIndex(l => l.slug === slug);
  if (i === -1) return null;
  const cur = LESSONS[i];
  const prev = LESSONS[i - 1];
  const next = LESSONS[i + 1];
  if (view === 'progress') {
    const pct = Math.round((i + 1) / total * 100);
    const pill = 'inline-flex items-center gap-1.5 rounded-full px-3.5 py-1.5 text-sm font-semibold transition no-underline';
    const ghost = `${pill} border border-zinc-950/15 text-zinc-700 hover:border-primary hover:text-primary dark:border-white/15 dark:text-zinc-300 dark:hover:border-primary-light dark:hover:text-primary-light`;
    return <div className="not-prose mb-6">
        <div className="flex flex-wrap items-center justify-between gap-3">
          <span className="text-sm font-semibold text-zinc-700 dark:text-zinc-300">
            {t.lesson} {i + 1} {t.of} {total} <span className="font-normal text-zinc-500 dark:text-zinc-400">· {cur.min} {t.min}</span>
          </span>
          <div className="flex items-center gap-2">
            <a href={prev ? lessonUrl(prev) : courseUrl} className={ghost}>
              {arrowLeft(14)} {prev ? t.prevShort : t.overview}
            </a>
            <a href={next ? lessonUrl(next) : courseUrl} className={`${pill} bg-primary text-white hover:opacity-90`}>
              {next ? t.nextShort : t.overview} {arrowRight(14)}
            </a>
          </div>
        </div>
        <div className="mt-3 h-1.5 w-full overflow-hidden rounded-full bg-zinc-950/10 dark:bg-white/10">
          <div className="h-full rounded-full bg-primary" style={{
      width: `${pct}%`
    }} />
        </div>
      </div>;
  }
  if (view === 'nav') {
    const isDone = seen.includes(slug);
    const toggle = () => writeSeen(isDone ? seen.filter(s => s !== slug) : [...seen, slug]);
    const markAndGo = () => {
      if (!isDone) writeSeen([...seen, slug]);
    };
    const newModule = next && next.mod !== cur.mod;
    return <div className="course-owns-nav not-prose mt-10 space-y-4">
        <button type="button" onClick={toggle} className={`inline-flex items-center gap-2 rounded-full border px-4 py-2 text-sm font-semibold transition ${isDone ? 'border-green-600 bg-green-600 text-white' : 'border-zinc-950/15 text-zinc-700 hover:border-green-600 hover:text-green-700 dark:border-white/15 dark:text-zinc-300'}`}>
          {checkIcon()} {isDone ? t.done : t.markDone}
        </button>
        <div className="grid gap-3 sm:grid-cols-2">
          {prev ? <a href={lessonUrl(prev)} className="group flex items-center gap-3 rounded-2xl border border-zinc-950/10 p-4 transition hover:border-primary dark:border-white/10 dark:hover:border-primary-light no-underline">
              <span className="text-zinc-400 group-hover:text-primary">{arrowLeft()}</span>
              <span>
                <span className="block text-xs font-semibold uppercase tracking-wide text-zinc-500 dark:text-zinc-400">{t.prev}</span>
                <span className="block font-semibold text-zinc-950 dark:text-white">{i}. {prev[lang]}</span>
              </span>
            </a> : <a href={courseUrl} className="group flex items-center gap-3 rounded-2xl border border-zinc-950/10 p-4 transition hover:border-primary dark:border-white/10 no-underline">
              <span className="text-zinc-400 group-hover:text-primary">{arrowLeft()}</span>
              <span className="font-semibold text-zinc-950 dark:text-white">{t.back}</span>
            </a>}
          {next ? <a href={lessonUrl(next)} onClick={markAndGo} className="group flex items-center justify-end gap-3 rounded-2xl bg-primary p-4 text-right text-white shadow-md shadow-primary/30 transition hover:opacity-90 no-underline">
              <span>
                <span className="block text-xs font-semibold uppercase tracking-wide text-white/80">
                  {newModule ? `${t.nextModule} · ${MODULES[lang][next.mod]}` : t.next}
                </span>
                <span className="block font-semibold">{i + 2}. {next[lang]}</span>
              </span>
              {arrowRight()}
            </a> : <a href={courseUrl} onClick={markAndGo} className="group flex items-center justify-end gap-3 rounded-2xl bg-green-600 p-4 text-right text-white shadow-md transition hover:opacity-90 no-underline">
              <span>
                <span className="block font-semibold">{t.finish}</span>
                <span className="block text-sm text-white/85">{t.finishText}</span>
              </span>
              {arrowRight()}
            </a>}
        </div>
        <div className="text-center">
          <a href={courseUrl} className="text-sm font-medium text-zinc-500 hover:text-primary dark:text-zinc-400 no-underline">{t.back}</a>
        </div>
      </div>;
  }
  return null;
};

<Course view="progress" lang="en" slug="change-dates" />

<Badge color="surface">Video in Spanish</Badge>

How to move a reservation to other dates, what happens with the price and why you can't change OTA reservations.

<Frame>
  <iframe width="100%" style={{ aspectRatio: "16 / 9" }} src="https://www.youtube.com/embed/dcliggksfi8?rel=0" title="Video: Change reservation dates" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowFullScreen />
</Frame>

## What you'll see in the video

* **0:00** · Check availability first
* **0:20** · Open Change dates
* **0:45** · The price before and after the change
* **1:05** · Locked OTA reservations

<Note>
  In the video, **Change dates** is a button at the bottom of the folio. It's now on the reservation's **Details** tab, in the **Reservation dates** section.
</Note>

## Key points

* Open the reservation and, in **Details → Reservation dates**, click **Change dates**.
* New nights take the rate's price; you can keep the previous price with **Fixed price per night** or night by night.
* OTA reservations are locked: the change is made in the OTA and updates in Roomdoo on its own.

## Learn more

<CardGroup cols={2}>
  <Card title="Change the dates of a reservation" icon="calendar" href="/en/reservations/change-dates">
    The full process, the price and early departure.
  </Card>

  <Card title="OTA sync" icon="arrows-rotate-reverse" href="/en/channel-manager/ota-sync">
    What travels between Roomdoo and the OTAs.
  </Card>
</CardGroup>

<Course view="nav" lang="en" slug="change-dates" />


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.