/* components/FilterModal.jsx */
(() => {
const METRIC_LABELS = {
cpo: "CPO",
ctr: "CTR",
cvr: "CVR",
cvCount: "CV数",
cost: "広告費",
click: "クリック",
imp: "IMP",
};
const METRIC_UNITS = {
cpo: "円",
ctr: "%",
cvr: "%",
cvCount: "件",
cost: "円",
click: "",
imp: "",
};
const MetricRow = ({ k, v, onChange }) => {
const label = METRIC_LABELS[k] || k;
const unit = METRIC_UNITS[k] || "";
return (
);
};
function FilterModal(props) {
const { open, onClose, filters, setFilters, matchedCount, totalCount } = props;
if (!open) return null;
const onRowChange = (k, next) => {
setFilters((prev) => ({ ...prev, [k]: next }));
};
const clearAll = () => {
const cleared = {};
Object.keys(filters).forEach((k) => (cleared[k] = { min: "", max: "" }));
setFilters(cleared);
};
// UX: クリエイティブ担当がよく使う「まずCVありに寄せる」ショートカット
const setHasCV = () => {
setFilters((prev) => ({ ...prev, cvCount: { ...(prev.cvCount || { min: "", max: "" }), min: "1" } }));
};
return (
フィルター
{totalCount}件中 {matchedCount}件 を表示
メモ:空欄は無視されます(その指標では絞り込みません)。
{/* よく使う項目を上に */}
{["cpo", "ctr", "cvr", "cvCount"].map((k) => (
))}
その他(任意)
{["cost", "click", "imp"].map((k) => (
))}
);
}
window.Cmp = window.Cmp || {};
window.Cmp.FilterModal = FilterModal;
})();