polish(compose): 截止时间控件改为分栏与快捷芯片
指定时刻用日期/时刻分栏与常用芯片替代原生 datetime-local,并收紧布局与左对齐模式切换。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -700,6 +700,12 @@ body {
|
|||||||
.j13-deadline-picker {
|
.j13-deadline-picker {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
.j13-deadline-picker-head {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
.j13-deadline-picker-label {
|
.j13-deadline-picker-label {
|
||||||
@@ -709,11 +715,12 @@ body {
|
|||||||
}
|
}
|
||||||
.j13-deadline-picker-modes {
|
.j13-deadline-picker-modes {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
gap: 4px;
|
|
||||||
padding: 3px;
|
|
||||||
border-radius: 10px;
|
|
||||||
background: var(--tint);
|
|
||||||
align-self: flex-start;
|
align-self: flex-start;
|
||||||
|
gap: 2px;
|
||||||
|
padding: 3px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: var(--tint);
|
||||||
|
border: 1px solid color-mix(in srgb, var(--line) 80%, transparent);
|
||||||
}
|
}
|
||||||
.j13-deadline-mode {
|
.j13-deadline-mode {
|
||||||
border: 0;
|
border: 0;
|
||||||
@@ -721,32 +728,179 @@ body {
|
|||||||
color: var(--ink-2);
|
color: var(--ink-2);
|
||||||
font-size: 12.5px;
|
font-size: 12.5px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
padding: 5px 10px;
|
padding: 5px 12px;
|
||||||
border-radius: 8px;
|
border-radius: 999px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
transition: background 0.12s ease, color 0.12s ease, box-shadow 0.12s ease;
|
||||||
}
|
}
|
||||||
.j13-deadline-mode.is-on {
|
.j13-deadline-mode.is-on {
|
||||||
background: var(--panel);
|
background: var(--panel);
|
||||||
color: var(--ink);
|
color: var(--ink);
|
||||||
box-shadow: var(--shadow-sm);
|
box-shadow: var(--shadow-sm);
|
||||||
}
|
}
|
||||||
|
.j13-deadline-mode:hover:not(:disabled):not(.is-on) {
|
||||||
|
color: var(--ink);
|
||||||
|
}
|
||||||
.j13-deadline-mode:disabled {
|
.j13-deadline-mode:disabled {
|
||||||
opacity: 0.55;
|
opacity: 0.55;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
.j13-deadline-presets {
|
.j13-deadline-presets,
|
||||||
|
.j13-deadline-quick-chips {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 8px;
|
gap: 7px;
|
||||||
|
}
|
||||||
|
.j13-deadline-chip {
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 13px;
|
||||||
|
border-radius: 999px;
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
background: var(--panel);
|
||||||
|
color: var(--ink-2);
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
|
||||||
|
}
|
||||||
|
.j13-deadline-chip-sm {
|
||||||
|
height: 28px;
|
||||||
|
padding: 0 10px;
|
||||||
|
font-size: 12.5px;
|
||||||
|
}
|
||||||
|
.j13-deadline-chip:hover:not(:disabled) {
|
||||||
|
border-color: color-mix(in srgb, var(--accent) 35%, var(--line));
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
.j13-deadline-chip.is-on {
|
||||||
|
background: var(--accent-soft);
|
||||||
|
border-color: color-mix(in srgb, var(--accent) 40%, var(--line));
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
.j13-deadline-chip:disabled {
|
||||||
|
opacity: 0.45;
|
||||||
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
.j13-deadline-custom {
|
.j13-deadline-custom {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 6px;
|
gap: 10px;
|
||||||
max-width: 22rem;
|
|
||||||
}
|
}
|
||||||
.j13-deadline-datetime {
|
.j13-deadline-fields {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: stretch;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
.j13-deadline-field {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
/* 合适宽度:比半行窄、比内容贴边宽,留一点点击余量 */
|
||||||
|
width: 11.75rem;
|
||||||
|
max-width: 100%;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
min-width: 0;
|
||||||
|
padding: 8px 10px;
|
||||||
|
border-radius: 12px;
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
background: var(--panel);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: border-color 0.12s ease, box-shadow 0.12s ease;
|
||||||
|
}
|
||||||
|
.j13-deadline-field:last-child {
|
||||||
|
width: 8.75rem;
|
||||||
|
}
|
||||||
|
.j13-deadline-field:focus-within {
|
||||||
|
border-color: color-mix(in srgb, var(--accent) 45%, var(--line));
|
||||||
|
box-shadow: 0 0 0 3px var(--accent-soft);
|
||||||
|
}
|
||||||
|
.j13-deadline-field-icon {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
border-radius: 8px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
color: var(--accent);
|
||||||
|
background: var(--accent-soft);
|
||||||
|
}
|
||||||
|
.j13-deadline-field-meta {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1px;
|
||||||
|
min-width: 0;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.j13-deadline-field-label {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 650;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
color: var(--ink-3);
|
||||||
|
}
|
||||||
|
.j13-deadline-field-input {
|
||||||
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
border: 0;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--ink);
|
||||||
|
font-size: 13.5px;
|
||||||
|
font-weight: 600;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
font-family: var(--font-sans);
|
||||||
|
outline: none;
|
||||||
|
color-scheme: light dark;
|
||||||
|
}
|
||||||
|
.j13-deadline-field-input:disabled {
|
||||||
|
opacity: 0.55;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
/* 左侧已有图标:隐藏原生指示器,避免双图标与多余空白 */
|
||||||
|
.j13-deadline-field-input::-webkit-calendar-picker-indicator {
|
||||||
|
opacity: 0;
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.j13-deadline-quick {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px 10px;
|
||||||
|
}
|
||||||
|
.j13-deadline-quick-label {
|
||||||
|
flex-shrink: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 650;
|
||||||
|
color: var(--ink-3);
|
||||||
|
min-width: 2em;
|
||||||
|
}
|
||||||
|
.j13-deadline-preview {
|
||||||
|
margin: 0;
|
||||||
|
padding: 9px 12px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: color-mix(in srgb, var(--accent-soft) 70%, var(--panel));
|
||||||
|
border: 1px solid color-mix(in srgb, var(--accent) 18%, var(--line));
|
||||||
|
color: var(--ink-2);
|
||||||
|
font-size: 12.5px;
|
||||||
|
line-height: 1.45;
|
||||||
|
}
|
||||||
|
.j13-deadline-preview strong {
|
||||||
|
color: var(--ink);
|
||||||
|
font-weight: 650;
|
||||||
|
}
|
||||||
|
.j13-deadline-hint {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.45;
|
||||||
|
color: var(--ink-3);
|
||||||
}
|
}
|
||||||
/* 奖品 / 中奖者:横向排布,放不下换行 */
|
/* 奖品 / 中奖者:横向排布,放不下换行 */
|
||||||
.j13-lottery-prize-row,
|
.j13-lottery-prize-row,
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
/** 发帖截止时间:快捷天数 + 自定义时刻 */
|
import { CalendarDays, Clock3 } from "lucide-react";
|
||||||
|
|
||||||
|
/** 发帖截止时间:快捷天数 + 指定时刻(分栏 + 快捷芯片) */
|
||||||
|
|
||||||
export type DeadlineMode = "preset" | "custom";
|
export type DeadlineMode = "preset" | "custom";
|
||||||
|
|
||||||
@@ -17,7 +19,7 @@ export function toLocalInputValue(d: Date): string {
|
|||||||
export function defaultCustomLocal(days = 7): string {
|
export function defaultCustomLocal(days = 7): string {
|
||||||
const d = new Date();
|
const d = new Date();
|
||||||
d.setDate(d.getDate() + days);
|
d.setDate(d.getDate() + days);
|
||||||
d.setSeconds(0, 0);
|
d.setHours(18, 0, 0, 0);
|
||||||
return toLocalInputValue(d);
|
return toLocalInputValue(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,12 +34,95 @@ export function formatLocalPreview(local: string): string {
|
|||||||
const t = Date.parse(local);
|
const t = Date.parse(local);
|
||||||
if (!Number.isFinite(t)) return "";
|
if (!Number.isFinite(t)) return "";
|
||||||
try {
|
try {
|
||||||
return new Date(t).toLocaleString("zh-CN");
|
return new Date(t).toLocaleString("zh-CN", {
|
||||||
|
year: "numeric",
|
||||||
|
month: "long",
|
||||||
|
day: "numeric",
|
||||||
|
weekday: "short",
|
||||||
|
hour: "2-digit",
|
||||||
|
minute: "2-digit",
|
||||||
|
hour12: false,
|
||||||
|
});
|
||||||
} catch {
|
} catch {
|
||||||
return local;
|
return local;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function splitLocal(v: string): { date: string; time: string } {
|
||||||
|
const [date = "", rawTime = ""] = (v || "").split("T");
|
||||||
|
const time = (rawTime || "18:00").slice(0, 5);
|
||||||
|
return { date, time: /^\d{2}:\d{2}$/.test(time) ? time : "18:00" };
|
||||||
|
}
|
||||||
|
|
||||||
|
function joinLocal(date: string, time: string): string {
|
||||||
|
if (!date) return "";
|
||||||
|
const t = /^\d{2}:\d{2}$/.test(time) ? time : "18:00";
|
||||||
|
return `${date}T${t}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function startOfDay(d: Date): Date {
|
||||||
|
const x = new Date(d);
|
||||||
|
x.setHours(0, 0, 0, 0);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
function withTime(base: Date, hours: number, minutes: number): Date {
|
||||||
|
const d = new Date(base);
|
||||||
|
d.setHours(hours, minutes, 0, 0);
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 至少晚于当前 1 小时;不满足则推到合法时刻 */
|
||||||
|
function ensureMinLead(d: Date): Date {
|
||||||
|
const min = new Date(Date.now() + 60 * 60 * 1000);
|
||||||
|
min.setSeconds(0, 0);
|
||||||
|
return d.getTime() < min.getTime() ? min : d;
|
||||||
|
}
|
||||||
|
|
||||||
|
type QuickSet = { id: string; label: string; build: () => Date };
|
||||||
|
|
||||||
|
function buildQuickSets(): QuickSet[] {
|
||||||
|
const now = new Date();
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
id: "tonight",
|
||||||
|
label: "今晚 22:00",
|
||||||
|
build: () => ensureMinLead(withTime(now, 22, 0)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "tomorrow-noon",
|
||||||
|
label: "明天中午",
|
||||||
|
build: () => {
|
||||||
|
const d = new Date(now);
|
||||||
|
d.setDate(d.getDate() + 1);
|
||||||
|
return withTime(d, 12, 0);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "plus3-eve",
|
||||||
|
label: "3 天后晚",
|
||||||
|
build: () => {
|
||||||
|
const d = new Date(now);
|
||||||
|
d.setDate(d.getDate() + 3);
|
||||||
|
return withTime(d, 21, 0);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "sunday-eve",
|
||||||
|
label: "本周日晚",
|
||||||
|
build: () => {
|
||||||
|
const d = startOfDay(now);
|
||||||
|
const day = d.getDay(); // 0=日
|
||||||
|
const add = day === 0 ? 7 : 7 - day;
|
||||||
|
d.setDate(d.getDate() + add);
|
||||||
|
return ensureMinLead(withTime(d, 21, 0));
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
const TIME_CHIPS = ["09:00", "12:00", "18:00", "21:00", "22:00", "23:59"] as const;
|
||||||
|
|
||||||
export default function DeadlinePicker({
|
export default function DeadlinePicker({
|
||||||
label = "截止时间",
|
label = "截止时间",
|
||||||
presets,
|
presets,
|
||||||
@@ -61,11 +146,32 @@ export default function DeadlinePicker({
|
|||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
hint?: string;
|
hint?: string;
|
||||||
}) {
|
}) {
|
||||||
const minLocal = toLocalInputValue(new Date(Date.now() + 60 * 60 * 1000));
|
const minDate = toLocalInputValue(new Date()).slice(0, 10);
|
||||||
const maxLocal = toLocalInputValue(new Date(Date.now() + 90 * 24 * 60 * 60 * 1000));
|
const maxDate = toLocalInputValue(new Date(Date.now() + 90 * 24 * 60 * 60 * 1000)).slice(0, 10);
|
||||||
|
const { date, time } = splitLocal(customLocal);
|
||||||
|
const quickSets = buildQuickSets();
|
||||||
|
|
||||||
|
const applyCustom = (next: Date) => {
|
||||||
|
onCustomLocalChange(toLocalInputValue(ensureMinLead(next)));
|
||||||
|
};
|
||||||
|
|
||||||
|
const patchDate = (nextDate: string) => {
|
||||||
|
onCustomLocalChange(joinLocal(nextDate, time || "18:00"));
|
||||||
|
};
|
||||||
|
|
||||||
|
const patchTime = (nextTime: string) => {
|
||||||
|
const baseDate = date || toLocalInputValue(new Date()).slice(0, 10);
|
||||||
|
onCustomLocalChange(joinLocal(baseDate, nextTime));
|
||||||
|
};
|
||||||
|
|
||||||
|
const enterCustom = () => {
|
||||||
|
onModeChange("custom");
|
||||||
|
if (!customLocal) onCustomLocalChange(defaultCustomLocal(days || 7));
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="j13-deadline-picker">
|
<div className="j13-deadline-picker">
|
||||||
|
<div className="j13-deadline-picker-head">
|
||||||
<div className="j13-deadline-picker-label">{label}</div>
|
<div className="j13-deadline-picker-label">{label}</div>
|
||||||
<div className="j13-deadline-picker-modes" role="tablist" aria-label={label}>
|
<div className="j13-deadline-picker-modes" role="tablist" aria-label={label}>
|
||||||
<button
|
<button
|
||||||
@@ -84,23 +190,22 @@ export default function DeadlinePicker({
|
|||||||
aria-selected={mode === "custom"}
|
aria-selected={mode === "custom"}
|
||||||
className={`j13-deadline-mode${mode === "custom" ? " is-on" : ""}`}
|
className={`j13-deadline-mode${mode === "custom" ? " is-on" : ""}`}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onClick={() => {
|
onClick={enterCustom}
|
||||||
onModeChange("custom");
|
|
||||||
if (!customLocal) onCustomLocalChange(defaultCustomLocal(days || 7));
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
指定时刻
|
指定时刻
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{mode === "preset" ? (
|
{mode === "preset" ? (
|
||||||
<div className="j13-deadline-presets">
|
<div className="j13-deadline-presets" role="group" aria-label="快捷天数">
|
||||||
{presets.map((d) => (
|
{presets.map((d) => (
|
||||||
<button
|
<button
|
||||||
key={d}
|
key={d}
|
||||||
type="button"
|
type="button"
|
||||||
className={`btn btn-sm ${days === d ? "btn-primary" : "btn-line"}`}
|
className={`j13-deadline-chip${days === d ? " is-on" : ""}`}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
aria-pressed={days === d}
|
||||||
onClick={() => onDaysChange(d)}
|
onClick={() => onDaysChange(d)}
|
||||||
>
|
>
|
||||||
{d} 天
|
{d} 天
|
||||||
@@ -109,22 +214,86 @@ export default function DeadlinePicker({
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="j13-deadline-custom">
|
<div className="j13-deadline-custom">
|
||||||
|
<div className="j13-deadline-fields">
|
||||||
|
<label className="j13-deadline-field">
|
||||||
|
<span className="j13-deadline-field-icon" aria-hidden>
|
||||||
|
<CalendarDays size={15} strokeWidth={2} />
|
||||||
|
</span>
|
||||||
|
<span className="j13-deadline-field-meta">
|
||||||
|
<span className="j13-deadline-field-label">日期</span>
|
||||||
<input
|
<input
|
||||||
type="datetime-local"
|
type="date"
|
||||||
className="j13-compose-field j13-deadline-datetime"
|
className="j13-deadline-field-input"
|
||||||
value={customLocal}
|
value={date}
|
||||||
min={minLocal}
|
min={minDate}
|
||||||
max={maxLocal}
|
max={maxDate}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onChange={(e) => onCustomLocalChange(e.target.value)}
|
onChange={(e) => patchDate(e.target.value)}
|
||||||
aria-label="指定截止时刻"
|
aria-label="截止日期"
|
||||||
/>
|
/>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label className="j13-deadline-field">
|
||||||
|
<span className="j13-deadline-field-icon" aria-hidden>
|
||||||
|
<Clock3 size={15} strokeWidth={2} />
|
||||||
|
</span>
|
||||||
|
<span className="j13-deadline-field-meta">
|
||||||
|
<span className="j13-deadline-field-label">时刻</span>
|
||||||
|
<input
|
||||||
|
type="time"
|
||||||
|
className="j13-deadline-field-input"
|
||||||
|
value={time}
|
||||||
|
disabled={disabled}
|
||||||
|
onChange={(e) => patchTime(e.target.value)}
|
||||||
|
aria-label="截止时刻"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="j13-deadline-quick" role="group" aria-label="快捷设到">
|
||||||
|
<span className="j13-deadline-quick-label">快捷</span>
|
||||||
|
<div className="j13-deadline-quick-chips">
|
||||||
|
{quickSets.map((q) => (
|
||||||
|
<button
|
||||||
|
key={q.id}
|
||||||
|
type="button"
|
||||||
|
className="j13-deadline-chip j13-deadline-chip-sm"
|
||||||
|
disabled={disabled}
|
||||||
|
onClick={() => applyCustom(q.build())}
|
||||||
|
>
|
||||||
|
{q.label}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="j13-deadline-quick" role="group" aria-label="常用时刻">
|
||||||
|
<span className="j13-deadline-quick-label">时刻</span>
|
||||||
|
<div className="j13-deadline-quick-chips">
|
||||||
|
{TIME_CHIPS.map((t) => (
|
||||||
|
<button
|
||||||
|
key={t}
|
||||||
|
type="button"
|
||||||
|
className={`j13-deadline-chip j13-deadline-chip-sm${time === t ? " is-on" : ""}`}
|
||||||
|
disabled={disabled || !date}
|
||||||
|
aria-pressed={time === t}
|
||||||
|
onClick={() => patchTime(t)}
|
||||||
|
>
|
||||||
|
{t}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{customLocal ? (
|
{customLocal ? (
|
||||||
<p className="meta text-[12.5px] !mb-0">将于 {formatLocalPreview(customLocal)} 截止</p>
|
<p className="j13-deadline-preview">
|
||||||
|
将于 <strong>{formatLocalPreview(customLocal)}</strong> 截止
|
||||||
|
</p>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{hint ? <p className="meta text-[12px] !mb-0">{hint}</p> : null}
|
{hint ? <p className="j13-deadline-hint">{hint}</p> : null}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user