PluginProbe ʕ •ᴥ•ʔ
Presto Player / 4.3.2
Presto Player v4.3.2
4.3.2 4.3.1 4.3.0 4.2.4 4.2.3 4.2.2 4.2.0 4.2.1 trunk 1.10.0 1.10.1 1.10.2 1.11.0 1.12.0 1.13.0 1.14.0 1.14.1 1.5.10 1.5.11 1.5.12 1.5.13 1.5.14 1.5.15 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.10 1.6.11 1.6.12 1.6.13 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.13 2.0.14 2.0.15 2.0.16 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.2.0 2.2.1 2.2.2 2.2.3 2.2.3-beta1 2.3.0 2.3.1 2.3.2 2.3.3 3.0.0 3.0.0-beta1 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.1.0 3.1.1 3.1.2 3.1.3 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4
presto-player / src / admin / dashboard / components / ChooseDate.js
presto-player / src / admin / dashboard / components Last commit date
Emails 1 month ago EngagementChart 2 months ago MediaHub 1 month ago Onboarding 2 months ago Popup 2 months ago Skeletons 1 month ago WhatsNew 2 months ago charts 2 months ago test 2 months ago AdminMenuSync.js 2 months ago ChartEmptyState.js 2 months ago ChooseDate.js 2 months ago ColorPicker.js 2 months ago ExtendPlugins.js 2 months ago Filters.js 2 months ago Link.js 2 months ago Navbar.js 1 month ago NoFound.js 2 months ago PageHeader.js 2 months ago PluginRecommendations.js 2 months ago PostScheduleField.js 2 months ago PrestoPlayerIcon.js 2 months ago ProGateOverlay.js 2 months ago QuickAccess.js 2 months ago RankedTable.js 2 months ago StatCard.js 2 months ago TopMedia.js 2 months ago TopPerformingMedia.js 2 months ago TopUsers.js 2 months ago TruncatedTitle.js 2 months ago UpgradeNotice.js 2 months ago UpgradeToPro.js 2 months ago VideoModal.js 2 months ago WelcomeBanner.js 2 months ago
ChooseDate.js
135 lines
1 import React, { useRef, useState, useEffect } from 'react';
2 import { __ } from '@wordpress/i18n';
3 import { DatePicker, Input } from '@bsf/force-ui';
4 import { Calendar, Trash2, ChevronDown } from 'lucide-react';
5 import { format } from '../utils/dateUtils';
6
7 function parseToDate(value) {
8 if (!value) return null;
9 if (value instanceof Date) return isNaN(value.getTime()) ? null : value;
10 const d = new Date(String(value).replace(' ', 'T'));
11 return isNaN(d.getTime()) ? null : d;
12 }
13
14 export default function ChooseDate({
15 chosenDate,
16 onPickDate,
17 placeholder,
18 className = '',
19 size = 'md',
20 }) {
21 const [isOpen, setIsOpen] = useState(false);
22 const [dropdownStyle, setDropdownStyle] = useState({});
23 const wrapperRef = useRef(null);
24 const triggerRef = useRef(null);
25
26 const selectedDate = parseToDate(chosenDate);
27
28 useEffect(() => {
29 function handleClickOutside(e) {
30 if (wrapperRef.current && !wrapperRef.current.contains(e.target)) {
31 setIsOpen(false);
32 }
33 }
34 if (isOpen) {
35 document.addEventListener('mousedown', handleClickOutside);
36 }
37 return () => document.removeEventListener('mousedown', handleClickOutside);
38 }, [isOpen]);
39
40 const displayValue = selectedDate
41 ? format(selectedDate, 'MMM dd, yyyy')
42 : '';
43
44 const handleDateSelect = (date) => {
45 if (!date) return;
46 const d = date instanceof Date ? date : new Date(date);
47 if (isNaN(d.getTime())) return;
48 const year = d.getFullYear();
49 const month = String(d.getMonth() + 1).padStart(2, '0');
50 const day = String(d.getDate()).padStart(2, '0');
51 if (typeof onPickDate === 'function') {
52 onPickDate(`${year}-${month}-${day}`);
53 }
54 setIsOpen(false);
55 };
56
57 const clearDate = (e) => {
58 e.preventDefault();
59 e.stopPropagation();
60 if (typeof onPickDate === 'function') {
61 onPickDate('');
62 }
63 setIsOpen(false);
64 };
65
66 return (
67 <div ref={wrapperRef} className={`relative ${className}`}>
68 <div className="flex items-center gap-1">
69 <div
70 className="flex-1 cursor-pointer"
71 ref={triggerRef}
72 onClick={() => {
73 if (!isOpen && triggerRef.current) {
74 const rect = triggerRef.current.getBoundingClientRect();
75 // DatePicker is ~340px tall; pad to 360 so we flip before the
76 // last row clips against the viewport.
77 const POPOVER_HEIGHT = 360;
78 const GAP = 4;
79 const spaceBelow = window.innerHeight - rect.bottom;
80 const spaceAbove = rect.top;
81 const flipUp =
82 spaceBelow < POPOVER_HEIGHT + GAP &&
83 spaceAbove > spaceBelow;
84 const style = {
85 position: 'fixed',
86 left: rect.left,
87 zIndex: 99999,
88 };
89 if (flipUp) {
90 style.bottom = window.innerHeight - rect.top + GAP;
91 } else {
92 style.top = rect.bottom + GAP;
93 }
94 setDropdownStyle(style);
95 }
96 setIsOpen((prev) => !prev);
97 }}
98 >
99 <Input
100 size={size}
101 value={displayValue}
102 readOnly
103 placeholder={placeholder || __('Select date', 'presto-player')}
104 prefix={<Calendar size={16} />}
105 suffix={<ChevronDown size={16} />}
106 className="cursor-pointer"
107 />
108 </div>
109 {selectedDate && (
110 <button
111 type="button"
112 onClick={clearDate}
113 className="p-1.5 text-gray-400 hover:text-red-500 transition-colors border-0 bg-transparent outline-none shrink-0"
114 title={__('Clear Date', 'presto-player')}
115 aria-label={__('Clear Date', 'presto-player')}
116 >
117 <Trash2 size={16} aria-hidden="true" />
118 </button>
119 )}
120 </div>
121
122 {isOpen && (
123 <div style={dropdownStyle} className="rounded-lg shadow-lg">
124 <DatePicker
125 selectionType="single"
126 selected={selectedDate}
127 onDateSelect={handleDateSelect}
128 isFooter={false}
129 />
130 </div>
131 )}
132 </div>
133 );
134 }
135