CarolinePascal commited on
Commit
ee7725b
·
unverified ·
1 Parent(s): 662810f

fix(layout)

Browse files
Files changed (1) hide show
  1. app.py +93 -56
app.py CHANGED
@@ -37,50 +37,22 @@ async def on_ready():
37
  MIN_DATE = datetime(2025, 7, 9)
38
 
39
 
40
- class MonthSelect(discord.ui.Select):
41
- def __init__(self):
42
- options = [
43
- discord.SelectOption(label=calendar.month_name[i], value=str(i))
44
- for i in range(1, 13)
45
- ]
46
- super().__init__(placeholder="Month", options=options, row=0)
47
-
48
- async def callback(self, interaction: discord.Interaction):
49
- self.view.month = int(self.values[0])
50
- await self.view.refresh(interaction)
51
-
52
-
53
- class YearSelect(discord.ui.Select):
54
- def __init__(self):
55
- options = [
56
- discord.SelectOption(label=str(y), value=str(y))
57
- for y in range(2025, 2027)
58
- ]
59
- super().__init__(placeholder="Year", options=options, row=1)
60
-
61
- async def callback(self, interaction: discord.Interaction):
62
- self.view.year = int(self.values[0])
63
- await self.view.refresh(interaction)
64
-
65
-
66
  class DayButton(discord.ui.Button):
67
- def __init__(self, day: int, row: int):
68
- super().__init__(label=str(day), style=discord.ButtonStyle.secondary, row=row)
 
 
 
 
 
69
  self.day = day
70
 
71
  async def callback(self, interaction: discord.Interaction):
72
  view: DatePickerView = self.view
73
  purchase_date = datetime(view.year, view.month, self.day)
74
 
75
- today = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
76
- if purchase_date < MIN_DATE or purchase_date > today:
77
- await interaction.response.send_message(
78
- f"Date must be between **July 09, 2025** and **{today.strftime('%B %d, %Y')}** (today).",
79
- ephemeral=True,
80
- )
81
- return
82
-
83
  arrival_date = purchase_date + timedelta(days=90)
 
84
  days_until = (arrival_date - today).days
85
 
86
  if days_until < -14:
@@ -102,6 +74,38 @@ class DayButton(discord.ui.Button):
102
  )
103
 
104
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  class DatePickerView(discord.ui.View):
106
  FIRST_PAGE = 14
107
  MID_PAGE = 13
@@ -112,17 +116,57 @@ class DatePickerView(discord.ui.View):
112
  self.year = today.year
113
  self.month = today.month
114
  self.page = 0
115
- self.month_select = MonthSelect()
116
- self.year_select = YearSelect()
117
- self.add_item(self.month_select)
118
- self.add_item(self.year_select)
119
- self.build_day_buttons()
120
 
121
- def build_day_buttons(self):
122
- for item in list(self.children):
123
- if not isinstance(item, discord.ui.Select):
124
- self.remove_item(item)
125
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  num_days = calendar.monthrange(self.year, self.month)[1]
127
 
128
  if self.page == 0:
@@ -135,7 +179,8 @@ class DatePickerView(discord.ui.View):
135
  has_next = end < num_days
136
 
137
  for i, d in enumerate(range(start, end + 1)):
138
- self.add_item(DayButton(d, row=2 + i // 5))
 
139
 
140
  day_count = end - start + 1
141
  last_row = 2 + (day_count - 1) // 5
@@ -155,22 +200,14 @@ class DatePickerView(discord.ui.View):
155
  btn.callback = self._next_page
156
  self.add_item(btn)
157
 
158
- async def refresh(self, interaction: discord.Interaction):
159
- self.page = 0
160
- self.build_day_buttons()
161
- await interaction.response.edit_message(
162
- content=f"Pick a day in **{calendar.month_name[self.month]} {self.year}**:",
163
- view=self,
164
- )
165
-
166
  async def _next_page(self, interaction: discord.Interaction):
167
  self.page += 1
168
- self.build_day_buttons()
169
  await interaction.response.edit_message(view=self)
170
 
171
  async def _prev_page(self, interaction: discord.Interaction):
172
  self.page -= 1
173
- self.build_day_buttons()
174
  await interaction.response.edit_message(view=self)
175
 
176
 
 
37
  MIN_DATE = datetime(2025, 7, 9)
38
 
39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  class DayButton(discord.ui.Button):
41
+ def __init__(self, day: int, row: int, disabled: bool = False):
42
+ super().__init__(
43
+ label=str(day),
44
+ style=discord.ButtonStyle.secondary,
45
+ row=row,
46
+ disabled=disabled,
47
+ )
48
  self.day = day
49
 
50
  async def callback(self, interaction: discord.Interaction):
51
  view: DatePickerView = self.view
52
  purchase_date = datetime(view.year, view.month, self.day)
53
 
 
 
 
 
 
 
 
 
54
  arrival_date = purchase_date + timedelta(days=90)
55
+ today = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
56
  days_until = (arrival_date - today).days
57
 
58
  if days_until < -14:
 
74
  )
75
 
76
 
77
+ def valid_months(year: int) -> list[int]:
78
+ today = datetime.now()
79
+ months = []
80
+ for m in range(1, 13):
81
+ if (year, m) < (MIN_DATE.year, MIN_DATE.month):
82
+ continue
83
+ if (year, m) > (today.year, today.month):
84
+ continue
85
+ months.append(m)
86
+ return months
87
+
88
+
89
+ def valid_years() -> list[int]:
90
+ today = datetime.now()
91
+ return [y for y in range(MIN_DATE.year, today.year + 1)]
92
+
93
+
94
+ def clamp_month(year: int, month: int) -> int:
95
+ months = valid_months(year)
96
+ if month in months:
97
+ return month
98
+ if month < months[0]:
99
+ return months[0]
100
+ return months[-1]
101
+
102
+
103
+ def is_day_disabled(year: int, month: int, day: int) -> bool:
104
+ today = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
105
+ dt = datetime(year, month, day)
106
+ return dt < MIN_DATE or dt > today
107
+
108
+
109
  class DatePickerView(discord.ui.View):
110
  FIRST_PAGE = 14
111
  MID_PAGE = 13
 
116
  self.year = today.year
117
  self.month = today.month
118
  self.page = 0
119
+ self.rebuild()
 
 
 
 
120
 
121
+ def rebuild(self):
122
+ self.clear_items()
123
+ self._build_selects()
124
+ self._build_day_buttons()
125
 
126
+ def _build_selects(self):
127
+ today = datetime.now()
128
+
129
+ year_options = [
130
+ discord.SelectOption(
131
+ label=str(y), value=str(y), default=(y == self.year)
132
+ )
133
+ for y in valid_years()
134
+ ]
135
+ year_select = discord.ui.Select(placeholder="Year", options=year_options, row=1)
136
+ year_select.callback = self._on_year
137
+ self.add_item(year_select)
138
+
139
+ months = valid_months(self.year)
140
+ month_options = [
141
+ discord.SelectOption(
142
+ label=calendar.month_name[m], value=str(m), default=(m == self.month)
143
+ )
144
+ for m in months
145
+ ]
146
+ month_select = discord.ui.Select(placeholder="Month", options=month_options, row=0)
147
+ month_select.callback = self._on_month
148
+ self.add_item(month_select)
149
+
150
+ async def _on_year(self, interaction: discord.Interaction):
151
+ self.year = int(interaction.data["values"][0])
152
+ self.month = clamp_month(self.year, self.month)
153
+ self.page = 0
154
+ self.rebuild()
155
+ await interaction.response.edit_message(
156
+ content=f"Pick a day in **{calendar.month_name[self.month]} {self.year}**:",
157
+ view=self,
158
+ )
159
+
160
+ async def _on_month(self, interaction: discord.Interaction):
161
+ self.month = int(interaction.data["values"][0])
162
+ self.page = 0
163
+ self.rebuild()
164
+ await interaction.response.edit_message(
165
+ content=f"Pick a day in **{calendar.month_name[self.month]} {self.year}**:",
166
+ view=self,
167
+ )
168
+
169
+ def _build_day_buttons(self):
170
  num_days = calendar.monthrange(self.year, self.month)[1]
171
 
172
  if self.page == 0:
 
179
  has_next = end < num_days
180
 
181
  for i, d in enumerate(range(start, end + 1)):
182
+ disabled = is_day_disabled(self.year, self.month, d)
183
+ self.add_item(DayButton(d, row=2 + i // 5, disabled=disabled))
184
 
185
  day_count = end - start + 1
186
  last_row = 2 + (day_count - 1) // 5
 
200
  btn.callback = self._next_page
201
  self.add_item(btn)
202
 
 
 
 
 
 
 
 
 
203
  async def _next_page(self, interaction: discord.Interaction):
204
  self.page += 1
205
+ self.rebuild()
206
  await interaction.response.edit_message(view=self)
207
 
208
  async def _prev_page(self, interaction: discord.Interaction):
209
  self.page -= 1
210
+ self.rebuild()
211
  await interaction.response.edit_message(view=self)
212
 
213