File size: 5,793 Bytes
cd99321
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import { useState } from 'react'
import { GripVertical, ArrowUp, ArrowDown, Plus } from 'lucide-react'
import Modal from '../shared/Modal'
import type { Day } from '../../types'

interface DayReorderPopupProps {
  isOpen: boolean
  days: Day[]
  t: (key: string, params?: Record<string, any>) => string
  locale: string
  onReorder: (orderedIds: number[]) => void
  onAddDay: () => void
  onClose: () => void
}

/**
 * Modal for moving whole days around: drag a row by its grip or use the up/down
 * arrows, and add a day at the end. Day headers stay untouched — this is the
 * single surface for ordering. Reorders are applied optimistically by the store,
 * so the list reflects each move immediately.
 */
export function DayReorderPopup({ isOpen, days, t, locale, onReorder, onAddDay, onClose }: DayReorderPopupProps) {
  const [dragIndex, setDragIndex] = useState<number | null>(null)
  const [overIndex, setOverIndex] = useState<number | null>(null)

  const ordered = [...days].sort((a, b) => (a.day_number ?? 0) - (b.day_number ?? 0))

  const label = (day: Day, index: number) => {
    if (day.title) return day.title
    if (day.date) {
      const d = new Date(day.date + 'T00:00:00')
      return d.toLocaleDateString(locale, { weekday: 'short', day: 'numeric', month: 'short' })
    }
    return t('dayplan.dayN', { n: index + 1 })
  }

  const move = (from: number, to: number) => {
    if (to < 0 || to >= ordered.length || from === to) return
    const ids = ordered.map(d => d.id)
    const [moved] = ids.splice(from, 1)
    ids.splice(to, 0, moved)
    onReorder(ids)
  }

  const cellBtn = {
    display: 'grid', placeItems: 'center', width: 28, height: 28,
    border: '1px solid var(--border-faint)', borderRadius: 7,
    background: 'none', cursor: 'pointer', color: 'var(--text-muted)', padding: 0,
  } as const

  return (
    <Modal
      isOpen={isOpen}
      onClose={onClose}
      title={t('dayplan.reorderTitle')}
      size="md"
      footer={
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12 }}>
          <button
            onClick={onClose}
            style={{
              padding: '8px 16px', borderRadius: 8, fontSize: 13, fontWeight: 500,
              border: '1px solid var(--border-primary)', background: 'none',
              color: 'var(--text-muted)', cursor: 'pointer', fontFamily: 'inherit',
            }}
          >
            {t('common.close')}
          </button>
          <button
            onClick={onAddDay}
            className="bg-accent text-accent-text"
            style={{
              display: 'flex', alignItems: 'center', gap: 6, padding: '8px 16px',
              borderRadius: 8, border: 'none', fontSize: 13, fontWeight: 500,
              cursor: 'pointer', fontFamily: 'inherit',
            }}
          >
            <Plus size={15} strokeWidth={2} />
            {t('dayplan.addDay')}
          </button>
        </div>
      }
    >
      <p style={{ margin: '0 0 14px', fontSize: 12.5, color: 'var(--text-faint)', lineHeight: 1.4 }}>
        {t('dayplan.reorderHint')}
      </p>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
        {ordered.map((day, index) => (
          <div
            key={day.id}
            draggable
            onDragStart={() => setDragIndex(index)}
            onDragEnd={() => { setDragIndex(null); setOverIndex(null) }}
            onDragOver={e => { e.preventDefault(); if (overIndex !== index) setOverIndex(index) }}
            onDrop={e => {
              e.preventDefault()
              if (dragIndex !== null && dragIndex !== index) move(dragIndex, index)
              setDragIndex(null); setOverIndex(null)
            }}
            style={{
              display: 'flex', alignItems: 'center', gap: 10, padding: '8px 10px',
              borderRadius: 9,
              border: '1px solid var(--border-faint)',
              background: overIndex === index && dragIndex !== null && dragIndex !== index ? 'var(--bg-hover)' : 'var(--bg-card, white)',
              opacity: dragIndex === index ? 0.5 : 1,
              outline: overIndex === index && dragIndex !== null && dragIndex !== index ? '2px dashed var(--border-primary)' : 'none',
              outlineOffset: -2,
            }}
          >
            <GripVertical size={15} strokeWidth={1.8} style={{ cursor: 'grab', color: 'var(--text-faint)', flexShrink: 0 }} />
            <span style={{
              flexShrink: 0, width: 24, height: 24, borderRadius: '50%',
              background: 'var(--bg-hover)', color: 'var(--text-muted)',
              display: 'grid', placeItems: 'center', fontSize: 11, fontWeight: 700,
            }}>
              {index + 1}
            </span>
            <span style={{ flex: 1, minWidth: 0, fontSize: 13.5, fontWeight: 500, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
              {label(day, index)}
            </span>
            <button
              onClick={() => move(index, index - 1)}
              disabled={index === 0}
              aria-label={t('dayplan.moveUp')}
              style={{ ...cellBtn, opacity: index === 0 ? 0.35 : 1, cursor: index === 0 ? 'default' : 'pointer' }}
            >
              <ArrowUp size={14} strokeWidth={2} />
            </button>
            <button
              onClick={() => move(index, index + 1)}
              disabled={index === ordered.length - 1}
              aria-label={t('dayplan.moveDown')}
              style={{ ...cellBtn, opacity: index === ordered.length - 1 ? 0.35 : 1, cursor: index === ordered.length - 1 ? 'default' : 'pointer' }}
            >
              <ArrowDown size={14} strokeWidth={2} />
            </button>
          </div>
        ))}
      </div>
    </Modal>
  )
}