docs-combiner 0.1.12 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/renderer.js +2334 -498
- package/dist/renderer.js.map +1 -1
- package/package.json +1 -1
package/dist/renderer.js
CHANGED
|
@@ -2757,6 +2757,29 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
2757
2757
|
|
|
2758
2758
|
/***/ }),
|
|
2759
2759
|
|
|
2760
|
+
/***/ "./node_modules/@mui/icons-material/esm/AttachMoney.js":
|
|
2761
|
+
/*!*************************************************************!*\
|
|
2762
|
+
!*** ./node_modules/@mui/icons-material/esm/AttachMoney.js ***!
|
|
2763
|
+
\*************************************************************/
|
|
2764
|
+
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
2765
|
+
|
|
2766
|
+
"use strict";
|
|
2767
|
+
__webpack_require__.r(__webpack_exports__);
|
|
2768
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
2769
|
+
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
|
|
2770
|
+
/* harmony export */ });
|
|
2771
|
+
/* harmony import */ var _utils_createSvgIcon_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils/createSvgIcon.js */ "./node_modules/@mui/material/esm/utils/createSvgIcon.js");
|
|
2772
|
+
/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react/jsx-runtime */ "./node_modules/react/jsx-runtime.js");
|
|
2773
|
+
"use client";
|
|
2774
|
+
|
|
2775
|
+
|
|
2776
|
+
|
|
2777
|
+
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ((0,_utils_createSvgIcon_js__WEBPACK_IMPORTED_MODULE_0__["default"])(/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)("path", {
|
|
2778
|
+
d: "M11.8 10.9c-2.27-.59-3-1.2-3-2.15 0-1.09 1.01-1.85 2.7-1.85 1.78 0 2.44.85 2.5 2.1h2.21c-.07-1.72-1.12-3.3-3.21-3.81V3h-3v2.16c-1.94.42-3.5 1.68-3.5 3.61 0 2.31 1.91 3.46 4.7 4.13 2.5.6 3 1.48 3 2.41 0 .69-.49 1.79-2.7 1.79-2.06 0-2.87-.92-2.98-2.1h-2.2c.12 2.19 1.76 3.42 3.68 3.83V21h3v-2.15c1.95-.37 3.5-1.5 3.5-3.55 0-2.84-2.43-3.81-4.7-4.4"
|
|
2779
|
+
}), 'AttachMoney'));
|
|
2780
|
+
|
|
2781
|
+
/***/ }),
|
|
2782
|
+
|
|
2760
2783
|
/***/ "./node_modules/@mui/icons-material/esm/AutoAwesome.js":
|
|
2761
2784
|
/*!*************************************************************!*\
|
|
2762
2785
|
!*** ./node_modules/@mui/icons-material/esm/AutoAwesome.js ***!
|
|
@@ -2964,6 +2987,29 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
2964
2987
|
|
|
2965
2988
|
/***/ }),
|
|
2966
2989
|
|
|
2990
|
+
/***/ "./node_modules/@mui/icons-material/esm/DeleteOutline.js":
|
|
2991
|
+
/*!***************************************************************!*\
|
|
2992
|
+
!*** ./node_modules/@mui/icons-material/esm/DeleteOutline.js ***!
|
|
2993
|
+
\***************************************************************/
|
|
2994
|
+
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
2995
|
+
|
|
2996
|
+
"use strict";
|
|
2997
|
+
__webpack_require__.r(__webpack_exports__);
|
|
2998
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
2999
|
+
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
|
|
3000
|
+
/* harmony export */ });
|
|
3001
|
+
/* harmony import */ var _utils_createSvgIcon_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils/createSvgIcon.js */ "./node_modules/@mui/material/esm/utils/createSvgIcon.js");
|
|
3002
|
+
/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react/jsx-runtime */ "./node_modules/react/jsx-runtime.js");
|
|
3003
|
+
"use client";
|
|
3004
|
+
|
|
3005
|
+
|
|
3006
|
+
|
|
3007
|
+
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ((0,_utils_createSvgIcon_js__WEBPACK_IMPORTED_MODULE_0__["default"])(/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)("path", {
|
|
3008
|
+
d: "M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6zM8 9h8v10H8zm7.5-5-1-1h-5l-1 1H5v2h14V4z"
|
|
3009
|
+
}), 'DeleteOutline'));
|
|
3010
|
+
|
|
3011
|
+
/***/ }),
|
|
3012
|
+
|
|
2967
3013
|
/***/ "./node_modules/@mui/icons-material/esm/Edit.js":
|
|
2968
3014
|
/*!******************************************************!*\
|
|
2969
3015
|
!*** ./node_modules/@mui/icons-material/esm/Edit.js ***!
|
|
@@ -8295,6 +8341,206 @@ function getCircularProgressUtilityClass(slot) {
|
|
|
8295
8341
|
const circularProgressClasses = (0,_mui_utils_generateUtilityClasses__WEBPACK_IMPORTED_MODULE_0__["default"])('MuiCircularProgress', ['root', 'determinate', 'indeterminate', 'colorPrimary', 'colorSecondary', 'svg', 'track', 'circle', 'circleDeterminate', 'circleIndeterminate', 'circleDisableShrink']);
|
|
8296
8342
|
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (circularProgressClasses);
|
|
8297
8343
|
|
|
8344
|
+
/***/ }),
|
|
8345
|
+
|
|
8346
|
+
/***/ "./node_modules/@mui/material/esm/ClickAwayListener/ClickAwayListener.js":
|
|
8347
|
+
/*!*******************************************************************************!*\
|
|
8348
|
+
!*** ./node_modules/@mui/material/esm/ClickAwayListener/ClickAwayListener.js ***!
|
|
8349
|
+
\*******************************************************************************/
|
|
8350
|
+
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
8351
|
+
|
|
8352
|
+
"use strict";
|
|
8353
|
+
__webpack_require__.r(__webpack_exports__);
|
|
8354
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
8355
|
+
/* harmony export */ ClickAwayListener: () => (/* binding */ ClickAwayListener)
|
|
8356
|
+
/* harmony export */ });
|
|
8357
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "./node_modules/react/index.js");
|
|
8358
|
+
/* harmony import */ var prop_types__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! prop-types */ "./node_modules/prop-types/index.js");
|
|
8359
|
+
/* harmony import */ var _mui_utils_ownerDocument__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @mui/utils/ownerDocument */ "./node_modules/@mui/utils/esm/ownerDocument/ownerDocument.js");
|
|
8360
|
+
/* harmony import */ var _mui_utils_useForkRef__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @mui/utils/useForkRef */ "./node_modules/@mui/utils/esm/useForkRef/useForkRef.js");
|
|
8361
|
+
/* harmony import */ var _mui_utils_useEventCallback__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @mui/utils/useEventCallback */ "./node_modules/@mui/utils/esm/useEventCallback/useEventCallback.js");
|
|
8362
|
+
/* harmony import */ var _mui_utils_elementAcceptingRef__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @mui/utils/elementAcceptingRef */ "./node_modules/@mui/utils/esm/elementAcceptingRef/elementAcceptingRef.js");
|
|
8363
|
+
/* harmony import */ var _mui_utils_exactProp__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @mui/utils/exactProp */ "./node_modules/@mui/utils/esm/exactProp/exactProp.js");
|
|
8364
|
+
/* harmony import */ var _mui_utils_getReactElementRef__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @mui/utils/getReactElementRef */ "./node_modules/@mui/utils/esm/getReactElementRef/getReactElementRef.js");
|
|
8365
|
+
'use client';
|
|
8366
|
+
|
|
8367
|
+
|
|
8368
|
+
|
|
8369
|
+
|
|
8370
|
+
|
|
8371
|
+
|
|
8372
|
+
|
|
8373
|
+
|
|
8374
|
+
|
|
8375
|
+
|
|
8376
|
+
// TODO: return `EventHandlerName extends `on${infer EventName}` ? Lowercase<EventName> : never` once generatePropTypes runs with TS 4.1
|
|
8377
|
+
function mapEventPropToEvent(eventProp) {
|
|
8378
|
+
return eventProp.substring(2).toLowerCase();
|
|
8379
|
+
}
|
|
8380
|
+
function clickedRootScrollbar(event, doc) {
|
|
8381
|
+
return doc.documentElement.clientWidth < event.clientX || doc.documentElement.clientHeight < event.clientY;
|
|
8382
|
+
}
|
|
8383
|
+
/**
|
|
8384
|
+
* Listen for click events that occur somewhere in the document, outside of the element itself.
|
|
8385
|
+
* For instance, if you need to hide a menu when people click anywhere else on your page.
|
|
8386
|
+
*
|
|
8387
|
+
* Demos:
|
|
8388
|
+
*
|
|
8389
|
+
* - [Click-Away Listener](https://mui.com/material-ui/react-click-away-listener/)
|
|
8390
|
+
* - [Menu](https://mui.com/material-ui/react-menu/)
|
|
8391
|
+
*
|
|
8392
|
+
* API:
|
|
8393
|
+
*
|
|
8394
|
+
* - [ClickAwayListener API](https://mui.com/material-ui/api/click-away-listener/)
|
|
8395
|
+
*/
|
|
8396
|
+
function ClickAwayListener(props) {
|
|
8397
|
+
const {
|
|
8398
|
+
children,
|
|
8399
|
+
disableReactTree = false,
|
|
8400
|
+
mouseEvent = 'onClick',
|
|
8401
|
+
onClickAway,
|
|
8402
|
+
touchEvent = 'onTouchEnd'
|
|
8403
|
+
} = props;
|
|
8404
|
+
const movedRef = react__WEBPACK_IMPORTED_MODULE_0__.useRef(false);
|
|
8405
|
+
const nodeRef = react__WEBPACK_IMPORTED_MODULE_0__.useRef(null);
|
|
8406
|
+
const activatedRef = react__WEBPACK_IMPORTED_MODULE_0__.useRef(false);
|
|
8407
|
+
const syntheticEventRef = react__WEBPACK_IMPORTED_MODULE_0__.useRef(false);
|
|
8408
|
+
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
|
|
8409
|
+
// Ensure that this component is not "activated" synchronously.
|
|
8410
|
+
// https://github.com/facebook/react/issues/20074
|
|
8411
|
+
setTimeout(() => {
|
|
8412
|
+
activatedRef.current = true;
|
|
8413
|
+
}, 0);
|
|
8414
|
+
return () => {
|
|
8415
|
+
activatedRef.current = false;
|
|
8416
|
+
};
|
|
8417
|
+
}, []);
|
|
8418
|
+
const handleRef = (0,_mui_utils_useForkRef__WEBPACK_IMPORTED_MODULE_3__["default"])((0,_mui_utils_getReactElementRef__WEBPACK_IMPORTED_MODULE_7__["default"])(children), nodeRef);
|
|
8419
|
+
|
|
8420
|
+
// The handler doesn't take event.defaultPrevented into account:
|
|
8421
|
+
//
|
|
8422
|
+
// event.preventDefault() is meant to stop default behaviors like
|
|
8423
|
+
// clicking a checkbox to check it, hitting a button to submit a form,
|
|
8424
|
+
// and hitting left arrow to move the cursor in a text input etc.
|
|
8425
|
+
// Only special HTML elements have these default behaviors.
|
|
8426
|
+
const handleClickAway = (0,_mui_utils_useEventCallback__WEBPACK_IMPORTED_MODULE_4__["default"])(event => {
|
|
8427
|
+
// Given developers can stop the propagation of the synthetic event,
|
|
8428
|
+
// we can only be confident with a positive value.
|
|
8429
|
+
const insideReactTree = syntheticEventRef.current;
|
|
8430
|
+
syntheticEventRef.current = false;
|
|
8431
|
+
const doc = (0,_mui_utils_ownerDocument__WEBPACK_IMPORTED_MODULE_2__["default"])(nodeRef.current);
|
|
8432
|
+
|
|
8433
|
+
// 1. IE11 support, which trigger the handleClickAway even after the unbind
|
|
8434
|
+
// 2. The child might render null.
|
|
8435
|
+
// 3. Behave like a blur listener.
|
|
8436
|
+
if (!activatedRef.current || !nodeRef.current || 'clientX' in event && clickedRootScrollbar(event, doc)) {
|
|
8437
|
+
return;
|
|
8438
|
+
}
|
|
8439
|
+
|
|
8440
|
+
// Do not act if user performed touchmove
|
|
8441
|
+
if (movedRef.current) {
|
|
8442
|
+
movedRef.current = false;
|
|
8443
|
+
return;
|
|
8444
|
+
}
|
|
8445
|
+
let insideDOM;
|
|
8446
|
+
|
|
8447
|
+
// If not enough, can use https://github.com/DieterHolvoet/event-propagation-path/blob/master/propagationPath.js
|
|
8448
|
+
if (event.composedPath) {
|
|
8449
|
+
insideDOM = event.composedPath().includes(nodeRef.current);
|
|
8450
|
+
} else {
|
|
8451
|
+
insideDOM = !doc.documentElement.contains(
|
|
8452
|
+
// @ts-expect-error returns `false` as intended when not dispatched from a Node
|
|
8453
|
+
event.target) || nodeRef.current.contains(
|
|
8454
|
+
// @ts-expect-error returns `false` as intended when not dispatched from a Node
|
|
8455
|
+
event.target);
|
|
8456
|
+
}
|
|
8457
|
+
if (!insideDOM && (disableReactTree || !insideReactTree)) {
|
|
8458
|
+
onClickAway(event);
|
|
8459
|
+
}
|
|
8460
|
+
});
|
|
8461
|
+
|
|
8462
|
+
// Keep track of mouse/touch events that bubbled up through the portal.
|
|
8463
|
+
const createHandleSynthetic = handlerName => event => {
|
|
8464
|
+
syntheticEventRef.current = true;
|
|
8465
|
+
const childrenPropsHandler = children.props[handlerName];
|
|
8466
|
+
if (childrenPropsHandler) {
|
|
8467
|
+
childrenPropsHandler(event);
|
|
8468
|
+
}
|
|
8469
|
+
};
|
|
8470
|
+
const childrenProps = {
|
|
8471
|
+
ref: handleRef
|
|
8472
|
+
};
|
|
8473
|
+
if (touchEvent !== false) {
|
|
8474
|
+
childrenProps[touchEvent] = createHandleSynthetic(touchEvent);
|
|
8475
|
+
}
|
|
8476
|
+
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
|
|
8477
|
+
if (touchEvent !== false) {
|
|
8478
|
+
const mappedTouchEvent = mapEventPropToEvent(touchEvent);
|
|
8479
|
+
const doc = (0,_mui_utils_ownerDocument__WEBPACK_IMPORTED_MODULE_2__["default"])(nodeRef.current);
|
|
8480
|
+
const handleTouchMove = () => {
|
|
8481
|
+
movedRef.current = true;
|
|
8482
|
+
};
|
|
8483
|
+
doc.addEventListener(mappedTouchEvent, handleClickAway);
|
|
8484
|
+
doc.addEventListener('touchmove', handleTouchMove);
|
|
8485
|
+
return () => {
|
|
8486
|
+
doc.removeEventListener(mappedTouchEvent, handleClickAway);
|
|
8487
|
+
doc.removeEventListener('touchmove', handleTouchMove);
|
|
8488
|
+
};
|
|
8489
|
+
}
|
|
8490
|
+
return undefined;
|
|
8491
|
+
}, [handleClickAway, touchEvent]);
|
|
8492
|
+
if (mouseEvent !== false) {
|
|
8493
|
+
childrenProps[mouseEvent] = createHandleSynthetic(mouseEvent);
|
|
8494
|
+
}
|
|
8495
|
+
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
|
|
8496
|
+
if (mouseEvent !== false) {
|
|
8497
|
+
const mappedMouseEvent = mapEventPropToEvent(mouseEvent);
|
|
8498
|
+
const doc = (0,_mui_utils_ownerDocument__WEBPACK_IMPORTED_MODULE_2__["default"])(nodeRef.current);
|
|
8499
|
+
doc.addEventListener(mappedMouseEvent, handleClickAway);
|
|
8500
|
+
return () => {
|
|
8501
|
+
doc.removeEventListener(mappedMouseEvent, handleClickAway);
|
|
8502
|
+
};
|
|
8503
|
+
}
|
|
8504
|
+
return undefined;
|
|
8505
|
+
}, [handleClickAway, mouseEvent]);
|
|
8506
|
+
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.cloneElement(children, childrenProps);
|
|
8507
|
+
}
|
|
8508
|
+
true ? ClickAwayListener.propTypes /* remove-proptypes */ = {
|
|
8509
|
+
// ┌────────────────────────────── Warning ──────────────────────────────┐
|
|
8510
|
+
// │ These PropTypes are generated from the TypeScript type definitions. │
|
|
8511
|
+
// │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
|
|
8512
|
+
// └─────────────────────────────────────────────────────────────────────┘
|
|
8513
|
+
/**
|
|
8514
|
+
* The wrapped element.
|
|
8515
|
+
*/
|
|
8516
|
+
children: _mui_utils_elementAcceptingRef__WEBPACK_IMPORTED_MODULE_5__["default"].isRequired,
|
|
8517
|
+
/**
|
|
8518
|
+
* If `true`, the React tree is ignored and only the DOM tree is considered.
|
|
8519
|
+
* This prop changes how portaled elements are handled.
|
|
8520
|
+
* @default false
|
|
8521
|
+
*/
|
|
8522
|
+
disableReactTree: prop_types__WEBPACK_IMPORTED_MODULE_1__.bool,
|
|
8523
|
+
/**
|
|
8524
|
+
* The mouse event to listen to. You can disable the listener by providing `false`.
|
|
8525
|
+
* @default 'onClick'
|
|
8526
|
+
*/
|
|
8527
|
+
mouseEvent: prop_types__WEBPACK_IMPORTED_MODULE_1__.oneOf(['onClick', 'onMouseDown', 'onMouseUp', 'onPointerDown', 'onPointerUp', false]),
|
|
8528
|
+
/**
|
|
8529
|
+
* Callback fired when a "click away" event is detected.
|
|
8530
|
+
*/
|
|
8531
|
+
onClickAway: prop_types__WEBPACK_IMPORTED_MODULE_1__.func.isRequired,
|
|
8532
|
+
/**
|
|
8533
|
+
* The touch event to listen to. You can disable the listener by providing `false`.
|
|
8534
|
+
* @default 'onTouchEnd'
|
|
8535
|
+
*/
|
|
8536
|
+
touchEvent: prop_types__WEBPACK_IMPORTED_MODULE_1__.oneOf(['onTouchEnd', 'onTouchStart', false])
|
|
8537
|
+
} : 0;
|
|
8538
|
+
if (true) {
|
|
8539
|
+
// eslint-disable-next-line
|
|
8540
|
+
ClickAwayListener['propTypes' + ''] = (0,_mui_utils_exactProp__WEBPACK_IMPORTED_MODULE_6__["default"])(ClickAwayListener.propTypes);
|
|
8541
|
+
}
|
|
8542
|
+
|
|
8543
|
+
|
|
8298
8544
|
/***/ }),
|
|
8299
8545
|
|
|
8300
8546
|
/***/ "./node_modules/@mui/material/esm/Collapse/Collapse.js":
|
|
@@ -13768,6 +14014,243 @@ const inputClasses = {
|
|
|
13768
14014
|
|
|
13769
14015
|
/***/ }),
|
|
13770
14016
|
|
|
14017
|
+
/***/ "./node_modules/@mui/material/esm/InputAdornment/InputAdornment.js":
|
|
14018
|
+
/*!*************************************************************************!*\
|
|
14019
|
+
!*** ./node_modules/@mui/material/esm/InputAdornment/InputAdornment.js ***!
|
|
14020
|
+
\*************************************************************************/
|
|
14021
|
+
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
14022
|
+
|
|
14023
|
+
"use strict";
|
|
14024
|
+
__webpack_require__.r(__webpack_exports__);
|
|
14025
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
14026
|
+
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
|
|
14027
|
+
/* harmony export */ });
|
|
14028
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "./node_modules/react/index.js");
|
|
14029
|
+
/* harmony import */ var prop_types__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! prop-types */ "./node_modules/prop-types/index.js");
|
|
14030
|
+
/* harmony import */ var clsx__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! clsx */ "./node_modules/clsx/dist/clsx.mjs");
|
|
14031
|
+
/* harmony import */ var _mui_utils_composeClasses__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @mui/utils/composeClasses */ "./node_modules/@mui/utils/esm/composeClasses/composeClasses.js");
|
|
14032
|
+
/* harmony import */ var _utils_capitalize_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../utils/capitalize.js */ "./node_modules/@mui/material/esm/utils/capitalize.js");
|
|
14033
|
+
/* harmony import */ var _Typography_index_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../Typography/index.js */ "./node_modules/@mui/material/esm/Typography/Typography.js");
|
|
14034
|
+
/* harmony import */ var _FormControl_FormControlContext_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../FormControl/FormControlContext.js */ "./node_modules/@mui/material/esm/FormControl/FormControlContext.js");
|
|
14035
|
+
/* harmony import */ var _FormControl_useFormControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../FormControl/useFormControl.js */ "./node_modules/@mui/material/esm/FormControl/useFormControl.js");
|
|
14036
|
+
/* harmony import */ var _zero_styled_index_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../zero-styled/index.js */ "./node_modules/@mui/material/esm/styles/styled.js");
|
|
14037
|
+
/* harmony import */ var _utils_memoTheme_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../utils/memoTheme.js */ "./node_modules/@mui/material/esm/utils/memoTheme.js");
|
|
14038
|
+
/* harmony import */ var _DefaultPropsProvider_index_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../DefaultPropsProvider/index.js */ "./node_modules/@mui/material/esm/DefaultPropsProvider/DefaultPropsProvider.js");
|
|
14039
|
+
/* harmony import */ var _inputAdornmentClasses_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./inputAdornmentClasses.js */ "./node_modules/@mui/material/esm/InputAdornment/inputAdornmentClasses.js");
|
|
14040
|
+
/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! react/jsx-runtime */ "./node_modules/react/jsx-runtime.js");
|
|
14041
|
+
'use client';
|
|
14042
|
+
|
|
14043
|
+
var _span;
|
|
14044
|
+
|
|
14045
|
+
|
|
14046
|
+
|
|
14047
|
+
|
|
14048
|
+
|
|
14049
|
+
|
|
14050
|
+
|
|
14051
|
+
|
|
14052
|
+
|
|
14053
|
+
|
|
14054
|
+
|
|
14055
|
+
|
|
14056
|
+
|
|
14057
|
+
const overridesResolver = (props, styles) => {
|
|
14058
|
+
const {
|
|
14059
|
+
ownerState
|
|
14060
|
+
} = props;
|
|
14061
|
+
return [styles.root, styles[`position${(0,_utils_capitalize_js__WEBPACK_IMPORTED_MODULE_4__["default"])(ownerState.position)}`], ownerState.disablePointerEvents === true && styles.disablePointerEvents, styles[ownerState.variant]];
|
|
14062
|
+
};
|
|
14063
|
+
const useUtilityClasses = ownerState => {
|
|
14064
|
+
const {
|
|
14065
|
+
classes,
|
|
14066
|
+
disablePointerEvents,
|
|
14067
|
+
hiddenLabel,
|
|
14068
|
+
position,
|
|
14069
|
+
size,
|
|
14070
|
+
variant
|
|
14071
|
+
} = ownerState;
|
|
14072
|
+
const slots = {
|
|
14073
|
+
root: ['root', disablePointerEvents && 'disablePointerEvents', position && `position${(0,_utils_capitalize_js__WEBPACK_IMPORTED_MODULE_4__["default"])(position)}`, variant, hiddenLabel && 'hiddenLabel', size && `size${(0,_utils_capitalize_js__WEBPACK_IMPORTED_MODULE_4__["default"])(size)}`]
|
|
14074
|
+
};
|
|
14075
|
+
return (0,_mui_utils_composeClasses__WEBPACK_IMPORTED_MODULE_3__["default"])(slots, _inputAdornmentClasses_js__WEBPACK_IMPORTED_MODULE_11__.getInputAdornmentUtilityClass, classes);
|
|
14076
|
+
};
|
|
14077
|
+
const InputAdornmentRoot = (0,_zero_styled_index_js__WEBPACK_IMPORTED_MODULE_8__["default"])('div', {
|
|
14078
|
+
name: 'MuiInputAdornment',
|
|
14079
|
+
slot: 'Root',
|
|
14080
|
+
overridesResolver
|
|
14081
|
+
})((0,_utils_memoTheme_js__WEBPACK_IMPORTED_MODULE_9__["default"])(({
|
|
14082
|
+
theme
|
|
14083
|
+
}) => ({
|
|
14084
|
+
display: 'flex',
|
|
14085
|
+
maxHeight: '2em',
|
|
14086
|
+
alignItems: 'center',
|
|
14087
|
+
whiteSpace: 'nowrap',
|
|
14088
|
+
color: (theme.vars || theme).palette.action.active,
|
|
14089
|
+
variants: [{
|
|
14090
|
+
props: {
|
|
14091
|
+
variant: 'filled'
|
|
14092
|
+
},
|
|
14093
|
+
style: {
|
|
14094
|
+
[`&.${_inputAdornmentClasses_js__WEBPACK_IMPORTED_MODULE_11__["default"].positionStart}&:not(.${_inputAdornmentClasses_js__WEBPACK_IMPORTED_MODULE_11__["default"].hiddenLabel})`]: {
|
|
14095
|
+
marginTop: 16
|
|
14096
|
+
}
|
|
14097
|
+
}
|
|
14098
|
+
}, {
|
|
14099
|
+
props: {
|
|
14100
|
+
position: 'start'
|
|
14101
|
+
},
|
|
14102
|
+
style: {
|
|
14103
|
+
marginRight: 8
|
|
14104
|
+
}
|
|
14105
|
+
}, {
|
|
14106
|
+
props: {
|
|
14107
|
+
position: 'end'
|
|
14108
|
+
},
|
|
14109
|
+
style: {
|
|
14110
|
+
marginLeft: 8
|
|
14111
|
+
}
|
|
14112
|
+
}, {
|
|
14113
|
+
props: {
|
|
14114
|
+
disablePointerEvents: true
|
|
14115
|
+
},
|
|
14116
|
+
style: {
|
|
14117
|
+
pointerEvents: 'none'
|
|
14118
|
+
}
|
|
14119
|
+
}]
|
|
14120
|
+
})));
|
|
14121
|
+
const InputAdornment = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.forwardRef(function InputAdornment(inProps, ref) {
|
|
14122
|
+
const props = (0,_DefaultPropsProvider_index_js__WEBPACK_IMPORTED_MODULE_10__.useDefaultProps)({
|
|
14123
|
+
props: inProps,
|
|
14124
|
+
name: 'MuiInputAdornment'
|
|
14125
|
+
});
|
|
14126
|
+
const {
|
|
14127
|
+
children,
|
|
14128
|
+
className,
|
|
14129
|
+
component = 'div',
|
|
14130
|
+
disablePointerEvents = false,
|
|
14131
|
+
disableTypography = false,
|
|
14132
|
+
position,
|
|
14133
|
+
variant: variantProp,
|
|
14134
|
+
...other
|
|
14135
|
+
} = props;
|
|
14136
|
+
const muiFormControl = (0,_FormControl_useFormControl_js__WEBPACK_IMPORTED_MODULE_7__["default"])() || {};
|
|
14137
|
+
let variant = variantProp;
|
|
14138
|
+
if (variantProp && muiFormControl.variant) {
|
|
14139
|
+
if (true) {
|
|
14140
|
+
if (variantProp === muiFormControl.variant) {
|
|
14141
|
+
console.error('MUI: The `InputAdornment` variant infers the variant prop ' + 'you do not have to provide one.');
|
|
14142
|
+
}
|
|
14143
|
+
}
|
|
14144
|
+
}
|
|
14145
|
+
if (muiFormControl && !variant) {
|
|
14146
|
+
variant = muiFormControl.variant;
|
|
14147
|
+
}
|
|
14148
|
+
const ownerState = {
|
|
14149
|
+
...props,
|
|
14150
|
+
hiddenLabel: muiFormControl.hiddenLabel,
|
|
14151
|
+
size: muiFormControl.size,
|
|
14152
|
+
disablePointerEvents,
|
|
14153
|
+
position,
|
|
14154
|
+
variant
|
|
14155
|
+
};
|
|
14156
|
+
const classes = useUtilityClasses(ownerState);
|
|
14157
|
+
return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_12__.jsx)(_FormControl_FormControlContext_js__WEBPACK_IMPORTED_MODULE_6__["default"].Provider, {
|
|
14158
|
+
value: null,
|
|
14159
|
+
children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_12__.jsx)(InputAdornmentRoot, {
|
|
14160
|
+
as: component,
|
|
14161
|
+
ownerState: ownerState,
|
|
14162
|
+
className: (0,clsx__WEBPACK_IMPORTED_MODULE_2__["default"])(classes.root, className),
|
|
14163
|
+
ref: ref,
|
|
14164
|
+
...other,
|
|
14165
|
+
children: typeof children === 'string' && !disableTypography ? /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_12__.jsx)(_Typography_index_js__WEBPACK_IMPORTED_MODULE_5__["default"], {
|
|
14166
|
+
color: "textSecondary",
|
|
14167
|
+
children: children
|
|
14168
|
+
}) : /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_12__.jsxs)(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, {
|
|
14169
|
+
children: [position === 'start' ? (/* notranslate needed while Google Translate will not fix zero-width space issue */_span || (_span = /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_12__.jsx)("span", {
|
|
14170
|
+
className: "notranslate",
|
|
14171
|
+
"aria-hidden": true,
|
|
14172
|
+
children: "\u200B"
|
|
14173
|
+
}))) : null, children]
|
|
14174
|
+
})
|
|
14175
|
+
})
|
|
14176
|
+
});
|
|
14177
|
+
});
|
|
14178
|
+
true ? InputAdornment.propTypes /* remove-proptypes */ = {
|
|
14179
|
+
// ┌────────────────────────────── Warning ──────────────────────────────┐
|
|
14180
|
+
// │ These PropTypes are generated from the TypeScript type definitions. │
|
|
14181
|
+
// │ To update them, edit the d.ts file and run `pnpm proptypes`. │
|
|
14182
|
+
// └─────────────────────────────────────────────────────────────────────┘
|
|
14183
|
+
/**
|
|
14184
|
+
* The content of the component, normally an `IconButton` or string.
|
|
14185
|
+
*/
|
|
14186
|
+
children: prop_types__WEBPACK_IMPORTED_MODULE_1__.node,
|
|
14187
|
+
/**
|
|
14188
|
+
* Override or extend the styles applied to the component.
|
|
14189
|
+
*/
|
|
14190
|
+
classes: prop_types__WEBPACK_IMPORTED_MODULE_1__.object,
|
|
14191
|
+
/**
|
|
14192
|
+
* @ignore
|
|
14193
|
+
*/
|
|
14194
|
+
className: prop_types__WEBPACK_IMPORTED_MODULE_1__.string,
|
|
14195
|
+
/**
|
|
14196
|
+
* The component used for the root node.
|
|
14197
|
+
* Either a string to use a HTML element or a component.
|
|
14198
|
+
*/
|
|
14199
|
+
component: prop_types__WEBPACK_IMPORTED_MODULE_1__.elementType,
|
|
14200
|
+
/**
|
|
14201
|
+
* Disable pointer events on the root.
|
|
14202
|
+
* This allows for the content of the adornment to focus the `input` on click.
|
|
14203
|
+
* @default false
|
|
14204
|
+
*/
|
|
14205
|
+
disablePointerEvents: prop_types__WEBPACK_IMPORTED_MODULE_1__.bool,
|
|
14206
|
+
/**
|
|
14207
|
+
* If children is a string then disable wrapping in a Typography component.
|
|
14208
|
+
* @default false
|
|
14209
|
+
*/
|
|
14210
|
+
disableTypography: prop_types__WEBPACK_IMPORTED_MODULE_1__.bool,
|
|
14211
|
+
/**
|
|
14212
|
+
* The position this adornment should appear relative to the `Input`.
|
|
14213
|
+
*/
|
|
14214
|
+
position: prop_types__WEBPACK_IMPORTED_MODULE_1__.oneOf(['end', 'start']).isRequired,
|
|
14215
|
+
/**
|
|
14216
|
+
* The system prop that allows defining system overrides as well as additional CSS styles.
|
|
14217
|
+
*/
|
|
14218
|
+
sx: prop_types__WEBPACK_IMPORTED_MODULE_1__.oneOfType([prop_types__WEBPACK_IMPORTED_MODULE_1__.arrayOf(prop_types__WEBPACK_IMPORTED_MODULE_1__.oneOfType([prop_types__WEBPACK_IMPORTED_MODULE_1__.func, prop_types__WEBPACK_IMPORTED_MODULE_1__.object, prop_types__WEBPACK_IMPORTED_MODULE_1__.bool])), prop_types__WEBPACK_IMPORTED_MODULE_1__.func, prop_types__WEBPACK_IMPORTED_MODULE_1__.object]),
|
|
14219
|
+
/**
|
|
14220
|
+
* The variant to use.
|
|
14221
|
+
* Note: If you are using the `TextField` component or the `FormControl` component
|
|
14222
|
+
* you do not have to set this manually.
|
|
14223
|
+
*/
|
|
14224
|
+
variant: prop_types__WEBPACK_IMPORTED_MODULE_1__.oneOf(['filled', 'outlined', 'standard'])
|
|
14225
|
+
} : 0;
|
|
14226
|
+
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (InputAdornment);
|
|
14227
|
+
|
|
14228
|
+
/***/ }),
|
|
14229
|
+
|
|
14230
|
+
/***/ "./node_modules/@mui/material/esm/InputAdornment/inputAdornmentClasses.js":
|
|
14231
|
+
/*!********************************************************************************!*\
|
|
14232
|
+
!*** ./node_modules/@mui/material/esm/InputAdornment/inputAdornmentClasses.js ***!
|
|
14233
|
+
\********************************************************************************/
|
|
14234
|
+
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
14235
|
+
|
|
14236
|
+
"use strict";
|
|
14237
|
+
__webpack_require__.r(__webpack_exports__);
|
|
14238
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
14239
|
+
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__),
|
|
14240
|
+
/* harmony export */ getInputAdornmentUtilityClass: () => (/* binding */ getInputAdornmentUtilityClass)
|
|
14241
|
+
/* harmony export */ });
|
|
14242
|
+
/* harmony import */ var _mui_utils_generateUtilityClasses__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @mui/utils/generateUtilityClasses */ "./node_modules/@mui/utils/esm/generateUtilityClasses/generateUtilityClasses.js");
|
|
14243
|
+
/* harmony import */ var _mui_utils_generateUtilityClass__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @mui/utils/generateUtilityClass */ "./node_modules/@mui/utils/esm/generateUtilityClass/generateUtilityClass.js");
|
|
14244
|
+
|
|
14245
|
+
|
|
14246
|
+
function getInputAdornmentUtilityClass(slot) {
|
|
14247
|
+
return (0,_mui_utils_generateUtilityClass__WEBPACK_IMPORTED_MODULE_1__["default"])('MuiInputAdornment', slot);
|
|
14248
|
+
}
|
|
14249
|
+
const inputAdornmentClasses = (0,_mui_utils_generateUtilityClasses__WEBPACK_IMPORTED_MODULE_0__["default"])('MuiInputAdornment', ['root', 'filled', 'standard', 'outlined', 'positionStart', 'positionEnd', 'disablePointerEvents', 'hiddenLabel', 'sizeSmall']);
|
|
14250
|
+
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (inputAdornmentClasses);
|
|
14251
|
+
|
|
14252
|
+
/***/ }),
|
|
14253
|
+
|
|
13771
14254
|
/***/ "./node_modules/@mui/material/esm/InputBase/InputBase.js":
|
|
13772
14255
|
/*!***************************************************************!*\
|
|
13773
14256
|
!*** ./node_modules/@mui/material/esm/InputBase/InputBase.js ***!
|
|
@@ -20813,6 +21296,799 @@ const selectClasses = (0,_mui_utils_generateUtilityClasses__WEBPACK_IMPORTED_MOD
|
|
|
20813
21296
|
|
|
20814
21297
|
/***/ }),
|
|
20815
21298
|
|
|
21299
|
+
/***/ "./node_modules/@mui/material/esm/Snackbar/Snackbar.js":
|
|
21300
|
+
/*!*************************************************************!*\
|
|
21301
|
+
!*** ./node_modules/@mui/material/esm/Snackbar/Snackbar.js ***!
|
|
21302
|
+
\*************************************************************/
|
|
21303
|
+
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
21304
|
+
|
|
21305
|
+
"use strict";
|
|
21306
|
+
__webpack_require__.r(__webpack_exports__);
|
|
21307
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
21308
|
+
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
|
|
21309
|
+
/* harmony export */ });
|
|
21310
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "./node_modules/react/index.js");
|
|
21311
|
+
/* harmony import */ var prop_types__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! prop-types */ "./node_modules/prop-types/index.js");
|
|
21312
|
+
/* harmony import */ var _mui_utils_composeClasses__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @mui/utils/composeClasses */ "./node_modules/@mui/utils/esm/composeClasses/composeClasses.js");
|
|
21313
|
+
/* harmony import */ var _useSnackbar_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./useSnackbar.js */ "./node_modules/@mui/material/esm/Snackbar/useSnackbar.js");
|
|
21314
|
+
/* harmony import */ var _ClickAwayListener_index_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../ClickAwayListener/index.js */ "./node_modules/@mui/material/esm/ClickAwayListener/ClickAwayListener.js");
|
|
21315
|
+
/* harmony import */ var _zero_styled_index_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../zero-styled/index.js */ "./node_modules/@mui/material/esm/styles/useTheme.js");
|
|
21316
|
+
/* harmony import */ var _zero_styled_index_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../zero-styled/index.js */ "./node_modules/@mui/material/esm/styles/styled.js");
|
|
21317
|
+
/* harmony import */ var _utils_memoTheme_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../utils/memoTheme.js */ "./node_modules/@mui/material/esm/utils/memoTheme.js");
|
|
21318
|
+
/* harmony import */ var _DefaultPropsProvider_index_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../DefaultPropsProvider/index.js */ "./node_modules/@mui/material/esm/DefaultPropsProvider/DefaultPropsProvider.js");
|
|
21319
|
+
/* harmony import */ var _utils_capitalize_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../utils/capitalize.js */ "./node_modules/@mui/material/esm/utils/capitalize.js");
|
|
21320
|
+
/* harmony import */ var _Grow_index_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../Grow/index.js */ "./node_modules/@mui/material/esm/Grow/Grow.js");
|
|
21321
|
+
/* harmony import */ var _SnackbarContent_index_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../SnackbarContent/index.js */ "./node_modules/@mui/material/esm/SnackbarContent/SnackbarContent.js");
|
|
21322
|
+
/* harmony import */ var _snackbarClasses_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./snackbarClasses.js */ "./node_modules/@mui/material/esm/Snackbar/snackbarClasses.js");
|
|
21323
|
+
/* harmony import */ var _utils_useSlot_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../utils/useSlot.js */ "./node_modules/@mui/material/esm/utils/useSlot.js");
|
|
21324
|
+
/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! react/jsx-runtime */ "./node_modules/react/jsx-runtime.js");
|
|
21325
|
+
'use client';
|
|
21326
|
+
|
|
21327
|
+
|
|
21328
|
+
|
|
21329
|
+
|
|
21330
|
+
|
|
21331
|
+
|
|
21332
|
+
|
|
21333
|
+
|
|
21334
|
+
|
|
21335
|
+
|
|
21336
|
+
|
|
21337
|
+
|
|
21338
|
+
|
|
21339
|
+
|
|
21340
|
+
|
|
21341
|
+
const useUtilityClasses = ownerState => {
|
|
21342
|
+
const {
|
|
21343
|
+
classes,
|
|
21344
|
+
anchorOrigin
|
|
21345
|
+
} = ownerState;
|
|
21346
|
+
const slots = {
|
|
21347
|
+
root: ['root', `anchorOrigin${(0,_utils_capitalize_js__WEBPACK_IMPORTED_MODULE_9__["default"])(anchorOrigin.vertical)}${(0,_utils_capitalize_js__WEBPACK_IMPORTED_MODULE_9__["default"])(anchorOrigin.horizontal)}`]
|
|
21348
|
+
};
|
|
21349
|
+
return (0,_mui_utils_composeClasses__WEBPACK_IMPORTED_MODULE_2__["default"])(slots, _snackbarClasses_js__WEBPACK_IMPORTED_MODULE_12__.getSnackbarUtilityClass, classes);
|
|
21350
|
+
};
|
|
21351
|
+
const SnackbarRoot = (0,_zero_styled_index_js__WEBPACK_IMPORTED_MODULE_6__["default"])('div', {
|
|
21352
|
+
name: 'MuiSnackbar',
|
|
21353
|
+
slot: 'Root',
|
|
21354
|
+
overridesResolver: (props, styles) => {
|
|
21355
|
+
const {
|
|
21356
|
+
ownerState
|
|
21357
|
+
} = props;
|
|
21358
|
+
return [styles.root, styles[`anchorOrigin${(0,_utils_capitalize_js__WEBPACK_IMPORTED_MODULE_9__["default"])(ownerState.anchorOrigin.vertical)}${(0,_utils_capitalize_js__WEBPACK_IMPORTED_MODULE_9__["default"])(ownerState.anchorOrigin.horizontal)}`]];
|
|
21359
|
+
}
|
|
21360
|
+
})((0,_utils_memoTheme_js__WEBPACK_IMPORTED_MODULE_7__["default"])(({
|
|
21361
|
+
theme
|
|
21362
|
+
}) => ({
|
|
21363
|
+
zIndex: (theme.vars || theme).zIndex.snackbar,
|
|
21364
|
+
position: 'fixed',
|
|
21365
|
+
display: 'flex',
|
|
21366
|
+
left: 8,
|
|
21367
|
+
right: 8,
|
|
21368
|
+
justifyContent: 'center',
|
|
21369
|
+
alignItems: 'center',
|
|
21370
|
+
variants: [{
|
|
21371
|
+
props: ({
|
|
21372
|
+
ownerState
|
|
21373
|
+
}) => ownerState.anchorOrigin.vertical === 'top',
|
|
21374
|
+
style: {
|
|
21375
|
+
top: 8,
|
|
21376
|
+
[theme.breakpoints.up('sm')]: {
|
|
21377
|
+
top: 24
|
|
21378
|
+
}
|
|
21379
|
+
}
|
|
21380
|
+
}, {
|
|
21381
|
+
props: ({
|
|
21382
|
+
ownerState
|
|
21383
|
+
}) => ownerState.anchorOrigin.vertical !== 'top',
|
|
21384
|
+
style: {
|
|
21385
|
+
bottom: 8,
|
|
21386
|
+
[theme.breakpoints.up('sm')]: {
|
|
21387
|
+
bottom: 24
|
|
21388
|
+
}
|
|
21389
|
+
}
|
|
21390
|
+
}, {
|
|
21391
|
+
props: ({
|
|
21392
|
+
ownerState
|
|
21393
|
+
}) => ownerState.anchorOrigin.horizontal === 'left',
|
|
21394
|
+
style: {
|
|
21395
|
+
justifyContent: 'flex-start',
|
|
21396
|
+
[theme.breakpoints.up('sm')]: {
|
|
21397
|
+
left: 24,
|
|
21398
|
+
right: 'auto'
|
|
21399
|
+
}
|
|
21400
|
+
}
|
|
21401
|
+
}, {
|
|
21402
|
+
props: ({
|
|
21403
|
+
ownerState
|
|
21404
|
+
}) => ownerState.anchorOrigin.horizontal === 'right',
|
|
21405
|
+
style: {
|
|
21406
|
+
justifyContent: 'flex-end',
|
|
21407
|
+
[theme.breakpoints.up('sm')]: {
|
|
21408
|
+
right: 24,
|
|
21409
|
+
left: 'auto'
|
|
21410
|
+
}
|
|
21411
|
+
}
|
|
21412
|
+
}, {
|
|
21413
|
+
props: ({
|
|
21414
|
+
ownerState
|
|
21415
|
+
}) => ownerState.anchorOrigin.horizontal === 'center',
|
|
21416
|
+
style: {
|
|
21417
|
+
[theme.breakpoints.up('sm')]: {
|
|
21418
|
+
left: '50%',
|
|
21419
|
+
right: 'auto',
|
|
21420
|
+
transform: 'translateX(-50%)'
|
|
21421
|
+
}
|
|
21422
|
+
}
|
|
21423
|
+
}]
|
|
21424
|
+
})));
|
|
21425
|
+
const Snackbar = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.forwardRef(function Snackbar(inProps, ref) {
|
|
21426
|
+
const props = (0,_DefaultPropsProvider_index_js__WEBPACK_IMPORTED_MODULE_8__.useDefaultProps)({
|
|
21427
|
+
props: inProps,
|
|
21428
|
+
name: 'MuiSnackbar'
|
|
21429
|
+
});
|
|
21430
|
+
const theme = (0,_zero_styled_index_js__WEBPACK_IMPORTED_MODULE_5__["default"])();
|
|
21431
|
+
const defaultTransitionDuration = {
|
|
21432
|
+
enter: theme.transitions.duration.enteringScreen,
|
|
21433
|
+
exit: theme.transitions.duration.leavingScreen
|
|
21434
|
+
};
|
|
21435
|
+
const {
|
|
21436
|
+
action,
|
|
21437
|
+
anchorOrigin: {
|
|
21438
|
+
vertical,
|
|
21439
|
+
horizontal
|
|
21440
|
+
} = {
|
|
21441
|
+
vertical: 'bottom',
|
|
21442
|
+
horizontal: 'left'
|
|
21443
|
+
},
|
|
21444
|
+
autoHideDuration = null,
|
|
21445
|
+
children,
|
|
21446
|
+
className,
|
|
21447
|
+
ClickAwayListenerProps: ClickAwayListenerPropsProp,
|
|
21448
|
+
ContentProps: ContentPropsProp,
|
|
21449
|
+
disableWindowBlurListener = false,
|
|
21450
|
+
message,
|
|
21451
|
+
onBlur,
|
|
21452
|
+
onClose,
|
|
21453
|
+
onFocus,
|
|
21454
|
+
onMouseEnter,
|
|
21455
|
+
onMouseLeave,
|
|
21456
|
+
open,
|
|
21457
|
+
resumeHideDuration,
|
|
21458
|
+
slots = {},
|
|
21459
|
+
slotProps = {},
|
|
21460
|
+
TransitionComponent: TransitionComponentProp,
|
|
21461
|
+
transitionDuration = defaultTransitionDuration,
|
|
21462
|
+
TransitionProps: {
|
|
21463
|
+
onEnter,
|
|
21464
|
+
onExited,
|
|
21465
|
+
...TransitionPropsProp
|
|
21466
|
+
} = {},
|
|
21467
|
+
...other
|
|
21468
|
+
} = props;
|
|
21469
|
+
const ownerState = {
|
|
21470
|
+
...props,
|
|
21471
|
+
anchorOrigin: {
|
|
21472
|
+
vertical,
|
|
21473
|
+
horizontal
|
|
21474
|
+
},
|
|
21475
|
+
autoHideDuration,
|
|
21476
|
+
disableWindowBlurListener,
|
|
21477
|
+
TransitionComponent: TransitionComponentProp,
|
|
21478
|
+
transitionDuration
|
|
21479
|
+
};
|
|
21480
|
+
const classes = useUtilityClasses(ownerState);
|
|
21481
|
+
const {
|
|
21482
|
+
getRootProps,
|
|
21483
|
+
onClickAway
|
|
21484
|
+
} = (0,_useSnackbar_js__WEBPACK_IMPORTED_MODULE_3__["default"])({
|
|
21485
|
+
...ownerState
|
|
21486
|
+
});
|
|
21487
|
+
const [exited, setExited] = react__WEBPACK_IMPORTED_MODULE_0__.useState(true);
|
|
21488
|
+
const handleExited = node => {
|
|
21489
|
+
setExited(true);
|
|
21490
|
+
if (onExited) {
|
|
21491
|
+
onExited(node);
|
|
21492
|
+
}
|
|
21493
|
+
};
|
|
21494
|
+
const handleEnter = (node, isAppearing) => {
|
|
21495
|
+
setExited(false);
|
|
21496
|
+
if (onEnter) {
|
|
21497
|
+
onEnter(node, isAppearing);
|
|
21498
|
+
}
|
|
21499
|
+
};
|
|
21500
|
+
const externalForwardedProps = {
|
|
21501
|
+
slots: {
|
|
21502
|
+
transition: TransitionComponentProp,
|
|
21503
|
+
...slots
|
|
21504
|
+
},
|
|
21505
|
+
slotProps: {
|
|
21506
|
+
content: ContentPropsProp,
|
|
21507
|
+
clickAwayListener: ClickAwayListenerPropsProp,
|
|
21508
|
+
transition: TransitionPropsProp,
|
|
21509
|
+
...slotProps
|
|
21510
|
+
}
|
|
21511
|
+
};
|
|
21512
|
+
const [Root, rootProps] = (0,_utils_useSlot_js__WEBPACK_IMPORTED_MODULE_13__["default"])('root', {
|
|
21513
|
+
ref,
|
|
21514
|
+
className: [classes.root, className],
|
|
21515
|
+
elementType: SnackbarRoot,
|
|
21516
|
+
getSlotProps: getRootProps,
|
|
21517
|
+
externalForwardedProps: {
|
|
21518
|
+
...externalForwardedProps,
|
|
21519
|
+
...other
|
|
21520
|
+
},
|
|
21521
|
+
ownerState
|
|
21522
|
+
});
|
|
21523
|
+
const [ClickAwaySlot, {
|
|
21524
|
+
ownerState: clickAwayOwnerStateProp,
|
|
21525
|
+
...clickAwayListenerProps
|
|
21526
|
+
}] = (0,_utils_useSlot_js__WEBPACK_IMPORTED_MODULE_13__["default"])('clickAwayListener', {
|
|
21527
|
+
elementType: _ClickAwayListener_index_js__WEBPACK_IMPORTED_MODULE_4__.ClickAwayListener,
|
|
21528
|
+
externalForwardedProps,
|
|
21529
|
+
getSlotProps: handlers => ({
|
|
21530
|
+
onClickAway: (...params) => {
|
|
21531
|
+
const event = params[0];
|
|
21532
|
+
handlers.onClickAway?.(...params);
|
|
21533
|
+
if (event?.defaultMuiPrevented) {
|
|
21534
|
+
return;
|
|
21535
|
+
}
|
|
21536
|
+
onClickAway(...params);
|
|
21537
|
+
}
|
|
21538
|
+
}),
|
|
21539
|
+
ownerState
|
|
21540
|
+
});
|
|
21541
|
+
const [ContentSlot, contentSlotProps] = (0,_utils_useSlot_js__WEBPACK_IMPORTED_MODULE_13__["default"])('content', {
|
|
21542
|
+
elementType: _SnackbarContent_index_js__WEBPACK_IMPORTED_MODULE_11__["default"],
|
|
21543
|
+
shouldForwardComponentProp: true,
|
|
21544
|
+
externalForwardedProps,
|
|
21545
|
+
additionalProps: {
|
|
21546
|
+
message,
|
|
21547
|
+
action
|
|
21548
|
+
},
|
|
21549
|
+
ownerState
|
|
21550
|
+
});
|
|
21551
|
+
const [TransitionSlot, transitionProps] = (0,_utils_useSlot_js__WEBPACK_IMPORTED_MODULE_13__["default"])('transition', {
|
|
21552
|
+
elementType: _Grow_index_js__WEBPACK_IMPORTED_MODULE_10__["default"],
|
|
21553
|
+
externalForwardedProps,
|
|
21554
|
+
getSlotProps: handlers => ({
|
|
21555
|
+
onEnter: (...params) => {
|
|
21556
|
+
handlers.onEnter?.(...params);
|
|
21557
|
+
handleEnter(...params);
|
|
21558
|
+
},
|
|
21559
|
+
onExited: (...params) => {
|
|
21560
|
+
handlers.onExited?.(...params);
|
|
21561
|
+
handleExited(...params);
|
|
21562
|
+
}
|
|
21563
|
+
}),
|
|
21564
|
+
additionalProps: {
|
|
21565
|
+
appear: true,
|
|
21566
|
+
in: open,
|
|
21567
|
+
timeout: transitionDuration,
|
|
21568
|
+
direction: vertical === 'top' ? 'down' : 'up'
|
|
21569
|
+
},
|
|
21570
|
+
ownerState
|
|
21571
|
+
});
|
|
21572
|
+
|
|
21573
|
+
// So we only render active snackbars.
|
|
21574
|
+
if (!open && exited) {
|
|
21575
|
+
return null;
|
|
21576
|
+
}
|
|
21577
|
+
return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_14__.jsx)(ClickAwaySlot, {
|
|
21578
|
+
...clickAwayListenerProps,
|
|
21579
|
+
...(slots.clickAwayListener && {
|
|
21580
|
+
ownerState: clickAwayOwnerStateProp
|
|
21581
|
+
}),
|
|
21582
|
+
children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_14__.jsx)(Root, {
|
|
21583
|
+
...rootProps,
|
|
21584
|
+
children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_14__.jsx)(TransitionSlot, {
|
|
21585
|
+
...transitionProps,
|
|
21586
|
+
children: children || /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_14__.jsx)(ContentSlot, {
|
|
21587
|
+
...contentSlotProps
|
|
21588
|
+
})
|
|
21589
|
+
})
|
|
21590
|
+
})
|
|
21591
|
+
});
|
|
21592
|
+
});
|
|
21593
|
+
true ? Snackbar.propTypes /* remove-proptypes */ = {
|
|
21594
|
+
// ┌────────────────────────────── Warning ──────────────────────────────┐
|
|
21595
|
+
// │ These PropTypes are generated from the TypeScript type definitions. │
|
|
21596
|
+
// │ To update them, edit the d.ts file and run `pnpm proptypes`. │
|
|
21597
|
+
// └─────────────────────────────────────────────────────────────────────┘
|
|
21598
|
+
/**
|
|
21599
|
+
* The action to display. It renders after the message, at the end of the snackbar.
|
|
21600
|
+
*/
|
|
21601
|
+
action: prop_types__WEBPACK_IMPORTED_MODULE_1__.node,
|
|
21602
|
+
/**
|
|
21603
|
+
* The anchor of the `Snackbar`.
|
|
21604
|
+
* On smaller screens, the component grows to occupy all the available width,
|
|
21605
|
+
* the horizontal alignment is ignored.
|
|
21606
|
+
* @default { vertical: 'bottom', horizontal: 'left' }
|
|
21607
|
+
*/
|
|
21608
|
+
anchorOrigin: prop_types__WEBPACK_IMPORTED_MODULE_1__.shape({
|
|
21609
|
+
horizontal: prop_types__WEBPACK_IMPORTED_MODULE_1__.oneOf(['center', 'left', 'right']).isRequired,
|
|
21610
|
+
vertical: prop_types__WEBPACK_IMPORTED_MODULE_1__.oneOf(['bottom', 'top']).isRequired
|
|
21611
|
+
}),
|
|
21612
|
+
/**
|
|
21613
|
+
* The number of milliseconds to wait before automatically calling the
|
|
21614
|
+
* `onClose` function. `onClose` should then set the state of the `open`
|
|
21615
|
+
* prop to hide the Snackbar. This behavior is disabled by default with
|
|
21616
|
+
* the `null` value.
|
|
21617
|
+
* @default null
|
|
21618
|
+
*/
|
|
21619
|
+
autoHideDuration: prop_types__WEBPACK_IMPORTED_MODULE_1__.number,
|
|
21620
|
+
/**
|
|
21621
|
+
* Replace the `SnackbarContent` component.
|
|
21622
|
+
*/
|
|
21623
|
+
children: prop_types__WEBPACK_IMPORTED_MODULE_1__.element,
|
|
21624
|
+
/**
|
|
21625
|
+
* Override or extend the styles applied to the component.
|
|
21626
|
+
*/
|
|
21627
|
+
classes: prop_types__WEBPACK_IMPORTED_MODULE_1__.object,
|
|
21628
|
+
/**
|
|
21629
|
+
* @ignore
|
|
21630
|
+
*/
|
|
21631
|
+
className: prop_types__WEBPACK_IMPORTED_MODULE_1__.string,
|
|
21632
|
+
/**
|
|
21633
|
+
* Props applied to the `ClickAwayListener` element.
|
|
21634
|
+
* @deprecated Use `slotProps.clickAwayListener` instead. This prop will be removed in a future major release. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details.
|
|
21635
|
+
*/
|
|
21636
|
+
ClickAwayListenerProps: prop_types__WEBPACK_IMPORTED_MODULE_1__.object,
|
|
21637
|
+
/**
|
|
21638
|
+
* Props applied to the [`SnackbarContent`](https://mui.com/material-ui/api/snackbar-content/) element.
|
|
21639
|
+
* @deprecated Use `slotProps.content` instead. This prop will be removed in a future major release. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details.
|
|
21640
|
+
*/
|
|
21641
|
+
ContentProps: prop_types__WEBPACK_IMPORTED_MODULE_1__.object,
|
|
21642
|
+
/**
|
|
21643
|
+
* If `true`, the `autoHideDuration` timer will expire even if the window is not focused.
|
|
21644
|
+
* @default false
|
|
21645
|
+
*/
|
|
21646
|
+
disableWindowBlurListener: prop_types__WEBPACK_IMPORTED_MODULE_1__.bool,
|
|
21647
|
+
/**
|
|
21648
|
+
* When displaying multiple consecutive snackbars using a single parent-rendered
|
|
21649
|
+
* `<Snackbar/>`, add the `key` prop to ensure independent treatment of each message.
|
|
21650
|
+
* For instance, use `<Snackbar key={message} />`. Otherwise, messages might update
|
|
21651
|
+
* in place, and features like `autoHideDuration` could be affected.
|
|
21652
|
+
*/
|
|
21653
|
+
key: () => null,
|
|
21654
|
+
/**
|
|
21655
|
+
* The message to display.
|
|
21656
|
+
*/
|
|
21657
|
+
message: prop_types__WEBPACK_IMPORTED_MODULE_1__.node,
|
|
21658
|
+
/**
|
|
21659
|
+
* @ignore
|
|
21660
|
+
*/
|
|
21661
|
+
onBlur: prop_types__WEBPACK_IMPORTED_MODULE_1__.func,
|
|
21662
|
+
/**
|
|
21663
|
+
* Callback fired when the component requests to be closed.
|
|
21664
|
+
* Typically `onClose` is used to set state in the parent component,
|
|
21665
|
+
* which is used to control the `Snackbar` `open` prop.
|
|
21666
|
+
* The `reason` parameter can optionally be used to control the response to `onClose`,
|
|
21667
|
+
* for example ignoring `clickaway`.
|
|
21668
|
+
*
|
|
21669
|
+
* @param {React.SyntheticEvent<any> | Event} event The event source of the callback.
|
|
21670
|
+
* @param {string} reason Can be: `"timeout"` (`autoHideDuration` expired), `"clickaway"`, or `"escapeKeyDown"`.
|
|
21671
|
+
*/
|
|
21672
|
+
onClose: prop_types__WEBPACK_IMPORTED_MODULE_1__.func,
|
|
21673
|
+
/**
|
|
21674
|
+
* @ignore
|
|
21675
|
+
*/
|
|
21676
|
+
onFocus: prop_types__WEBPACK_IMPORTED_MODULE_1__.func,
|
|
21677
|
+
/**
|
|
21678
|
+
* @ignore
|
|
21679
|
+
*/
|
|
21680
|
+
onMouseEnter: prop_types__WEBPACK_IMPORTED_MODULE_1__.func,
|
|
21681
|
+
/**
|
|
21682
|
+
* @ignore
|
|
21683
|
+
*/
|
|
21684
|
+
onMouseLeave: prop_types__WEBPACK_IMPORTED_MODULE_1__.func,
|
|
21685
|
+
/**
|
|
21686
|
+
* If `true`, the component is shown.
|
|
21687
|
+
*/
|
|
21688
|
+
open: prop_types__WEBPACK_IMPORTED_MODULE_1__.bool,
|
|
21689
|
+
/**
|
|
21690
|
+
* The number of milliseconds to wait before dismissing after user interaction.
|
|
21691
|
+
* If `autoHideDuration` prop isn't specified, it does nothing.
|
|
21692
|
+
* If `autoHideDuration` prop is specified but `resumeHideDuration` isn't,
|
|
21693
|
+
* we default to `autoHideDuration / 2` ms.
|
|
21694
|
+
*/
|
|
21695
|
+
resumeHideDuration: prop_types__WEBPACK_IMPORTED_MODULE_1__.number,
|
|
21696
|
+
/**
|
|
21697
|
+
* The props used for each slot inside.
|
|
21698
|
+
* @default {}
|
|
21699
|
+
*/
|
|
21700
|
+
slotProps: prop_types__WEBPACK_IMPORTED_MODULE_1__.shape({
|
|
21701
|
+
clickAwayListener: prop_types__WEBPACK_IMPORTED_MODULE_1__.oneOfType([prop_types__WEBPACK_IMPORTED_MODULE_1__.func, prop_types__WEBPACK_IMPORTED_MODULE_1__.object]),
|
|
21702
|
+
content: prop_types__WEBPACK_IMPORTED_MODULE_1__.oneOfType([prop_types__WEBPACK_IMPORTED_MODULE_1__.func, prop_types__WEBPACK_IMPORTED_MODULE_1__.object]),
|
|
21703
|
+
root: prop_types__WEBPACK_IMPORTED_MODULE_1__.oneOfType([prop_types__WEBPACK_IMPORTED_MODULE_1__.func, prop_types__WEBPACK_IMPORTED_MODULE_1__.object]),
|
|
21704
|
+
transition: prop_types__WEBPACK_IMPORTED_MODULE_1__.oneOfType([prop_types__WEBPACK_IMPORTED_MODULE_1__.func, prop_types__WEBPACK_IMPORTED_MODULE_1__.object])
|
|
21705
|
+
}),
|
|
21706
|
+
/**
|
|
21707
|
+
* The components used for each slot inside.
|
|
21708
|
+
* @default {}
|
|
21709
|
+
*/
|
|
21710
|
+
slots: prop_types__WEBPACK_IMPORTED_MODULE_1__.shape({
|
|
21711
|
+
clickAwayListener: prop_types__WEBPACK_IMPORTED_MODULE_1__.elementType,
|
|
21712
|
+
content: prop_types__WEBPACK_IMPORTED_MODULE_1__.elementType,
|
|
21713
|
+
root: prop_types__WEBPACK_IMPORTED_MODULE_1__.elementType,
|
|
21714
|
+
transition: prop_types__WEBPACK_IMPORTED_MODULE_1__.elementType
|
|
21715
|
+
}),
|
|
21716
|
+
/**
|
|
21717
|
+
* The system prop that allows defining system overrides as well as additional CSS styles.
|
|
21718
|
+
*/
|
|
21719
|
+
sx: prop_types__WEBPACK_IMPORTED_MODULE_1__.oneOfType([prop_types__WEBPACK_IMPORTED_MODULE_1__.arrayOf(prop_types__WEBPACK_IMPORTED_MODULE_1__.oneOfType([prop_types__WEBPACK_IMPORTED_MODULE_1__.func, prop_types__WEBPACK_IMPORTED_MODULE_1__.object, prop_types__WEBPACK_IMPORTED_MODULE_1__.bool])), prop_types__WEBPACK_IMPORTED_MODULE_1__.func, prop_types__WEBPACK_IMPORTED_MODULE_1__.object]),
|
|
21720
|
+
/**
|
|
21721
|
+
* The component used for the transition.
|
|
21722
|
+
* [Follow this guide](https://mui.com/material-ui/transitions/#transitioncomponent-prop) to learn more about the requirements for this component.
|
|
21723
|
+
* @deprecated Use `slots.transition` instead. This prop will be removed in a future major release. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details.
|
|
21724
|
+
* @default Grow
|
|
21725
|
+
*/
|
|
21726
|
+
TransitionComponent: prop_types__WEBPACK_IMPORTED_MODULE_1__.elementType,
|
|
21727
|
+
/**
|
|
21728
|
+
* The duration for the transition, in milliseconds.
|
|
21729
|
+
* You may specify a single timeout for all transitions, or individually with an object.
|
|
21730
|
+
* @default {
|
|
21731
|
+
* enter: theme.transitions.duration.enteringScreen,
|
|
21732
|
+
* exit: theme.transitions.duration.leavingScreen,
|
|
21733
|
+
* }
|
|
21734
|
+
*/
|
|
21735
|
+
transitionDuration: prop_types__WEBPACK_IMPORTED_MODULE_1__.oneOfType([prop_types__WEBPACK_IMPORTED_MODULE_1__.number, prop_types__WEBPACK_IMPORTED_MODULE_1__.shape({
|
|
21736
|
+
appear: prop_types__WEBPACK_IMPORTED_MODULE_1__.number,
|
|
21737
|
+
enter: prop_types__WEBPACK_IMPORTED_MODULE_1__.number,
|
|
21738
|
+
exit: prop_types__WEBPACK_IMPORTED_MODULE_1__.number
|
|
21739
|
+
})]),
|
|
21740
|
+
/**
|
|
21741
|
+
* Props applied to the transition element.
|
|
21742
|
+
* By default, the element is based on this [`Transition`](https://reactcommunity.org/react-transition-group/transition/) component.
|
|
21743
|
+
* @deprecated Use `slotProps.transition` instead. This prop will be removed in a future major release. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details.
|
|
21744
|
+
* @default {}
|
|
21745
|
+
*/
|
|
21746
|
+
TransitionProps: prop_types__WEBPACK_IMPORTED_MODULE_1__.object
|
|
21747
|
+
} : 0;
|
|
21748
|
+
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Snackbar);
|
|
21749
|
+
|
|
21750
|
+
/***/ }),
|
|
21751
|
+
|
|
21752
|
+
/***/ "./node_modules/@mui/material/esm/Snackbar/snackbarClasses.js":
|
|
21753
|
+
/*!********************************************************************!*\
|
|
21754
|
+
!*** ./node_modules/@mui/material/esm/Snackbar/snackbarClasses.js ***!
|
|
21755
|
+
\********************************************************************/
|
|
21756
|
+
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
21757
|
+
|
|
21758
|
+
"use strict";
|
|
21759
|
+
__webpack_require__.r(__webpack_exports__);
|
|
21760
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
21761
|
+
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__),
|
|
21762
|
+
/* harmony export */ getSnackbarUtilityClass: () => (/* binding */ getSnackbarUtilityClass)
|
|
21763
|
+
/* harmony export */ });
|
|
21764
|
+
/* harmony import */ var _mui_utils_generateUtilityClasses__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @mui/utils/generateUtilityClasses */ "./node_modules/@mui/utils/esm/generateUtilityClasses/generateUtilityClasses.js");
|
|
21765
|
+
/* harmony import */ var _mui_utils_generateUtilityClass__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @mui/utils/generateUtilityClass */ "./node_modules/@mui/utils/esm/generateUtilityClass/generateUtilityClass.js");
|
|
21766
|
+
|
|
21767
|
+
|
|
21768
|
+
function getSnackbarUtilityClass(slot) {
|
|
21769
|
+
return (0,_mui_utils_generateUtilityClass__WEBPACK_IMPORTED_MODULE_1__["default"])('MuiSnackbar', slot);
|
|
21770
|
+
}
|
|
21771
|
+
const snackbarClasses = (0,_mui_utils_generateUtilityClasses__WEBPACK_IMPORTED_MODULE_0__["default"])('MuiSnackbar', ['root', 'anchorOriginTopCenter', 'anchorOriginBottomCenter', 'anchorOriginTopRight', 'anchorOriginBottomRight', 'anchorOriginTopLeft', 'anchorOriginBottomLeft']);
|
|
21772
|
+
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (snackbarClasses);
|
|
21773
|
+
|
|
21774
|
+
/***/ }),
|
|
21775
|
+
|
|
21776
|
+
/***/ "./node_modules/@mui/material/esm/Snackbar/useSnackbar.js":
|
|
21777
|
+
/*!****************************************************************!*\
|
|
21778
|
+
!*** ./node_modules/@mui/material/esm/Snackbar/useSnackbar.js ***!
|
|
21779
|
+
\****************************************************************/
|
|
21780
|
+
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
21781
|
+
|
|
21782
|
+
"use strict";
|
|
21783
|
+
__webpack_require__.r(__webpack_exports__);
|
|
21784
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
21785
|
+
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
|
|
21786
|
+
/* harmony export */ });
|
|
21787
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "./node_modules/react/index.js");
|
|
21788
|
+
/* harmony import */ var _mui_utils_useEventCallback__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @mui/utils/useEventCallback */ "./node_modules/@mui/utils/esm/useEventCallback/useEventCallback.js");
|
|
21789
|
+
/* harmony import */ var _mui_utils_useTimeout__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @mui/utils/useTimeout */ "./node_modules/@mui/utils/esm/useTimeout/useTimeout.js");
|
|
21790
|
+
/* harmony import */ var _mui_utils_extractEventHandlers__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @mui/utils/extractEventHandlers */ "./node_modules/@mui/utils/esm/extractEventHandlers/extractEventHandlers.js");
|
|
21791
|
+
'use client';
|
|
21792
|
+
|
|
21793
|
+
|
|
21794
|
+
|
|
21795
|
+
|
|
21796
|
+
|
|
21797
|
+
function useSnackbar(parameters = {}) {
|
|
21798
|
+
const {
|
|
21799
|
+
autoHideDuration = null,
|
|
21800
|
+
disableWindowBlurListener = false,
|
|
21801
|
+
onClose,
|
|
21802
|
+
open,
|
|
21803
|
+
resumeHideDuration
|
|
21804
|
+
} = parameters;
|
|
21805
|
+
const timerAutoHide = (0,_mui_utils_useTimeout__WEBPACK_IMPORTED_MODULE_2__["default"])();
|
|
21806
|
+
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
|
|
21807
|
+
if (!open) {
|
|
21808
|
+
return undefined;
|
|
21809
|
+
}
|
|
21810
|
+
|
|
21811
|
+
/**
|
|
21812
|
+
* @param {KeyboardEvent} nativeEvent
|
|
21813
|
+
*/
|
|
21814
|
+
function handleKeyDown(nativeEvent) {
|
|
21815
|
+
if (!nativeEvent.defaultPrevented) {
|
|
21816
|
+
if (nativeEvent.key === 'Escape') {
|
|
21817
|
+
// not calling `preventDefault` since we don't know if people may ignore this event e.g. a permanently open snackbar
|
|
21818
|
+
onClose?.(nativeEvent, 'escapeKeyDown');
|
|
21819
|
+
}
|
|
21820
|
+
}
|
|
21821
|
+
}
|
|
21822
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
21823
|
+
return () => {
|
|
21824
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
21825
|
+
};
|
|
21826
|
+
}, [open, onClose]);
|
|
21827
|
+
const handleClose = (0,_mui_utils_useEventCallback__WEBPACK_IMPORTED_MODULE_1__["default"])((event, reason) => {
|
|
21828
|
+
onClose?.(event, reason);
|
|
21829
|
+
});
|
|
21830
|
+
const setAutoHideTimer = (0,_mui_utils_useEventCallback__WEBPACK_IMPORTED_MODULE_1__["default"])(autoHideDurationParam => {
|
|
21831
|
+
if (!onClose || autoHideDurationParam == null) {
|
|
21832
|
+
return;
|
|
21833
|
+
}
|
|
21834
|
+
timerAutoHide.start(autoHideDurationParam, () => {
|
|
21835
|
+
handleClose(null, 'timeout');
|
|
21836
|
+
});
|
|
21837
|
+
});
|
|
21838
|
+
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
|
|
21839
|
+
if (open) {
|
|
21840
|
+
setAutoHideTimer(autoHideDuration);
|
|
21841
|
+
}
|
|
21842
|
+
return timerAutoHide.clear;
|
|
21843
|
+
}, [open, autoHideDuration, setAutoHideTimer, timerAutoHide]);
|
|
21844
|
+
const handleClickAway = event => {
|
|
21845
|
+
onClose?.(event, 'clickaway');
|
|
21846
|
+
};
|
|
21847
|
+
|
|
21848
|
+
// Pause the timer when the user is interacting with the Snackbar
|
|
21849
|
+
// or when the user hide the window.
|
|
21850
|
+
const handlePause = timerAutoHide.clear;
|
|
21851
|
+
|
|
21852
|
+
// Restart the timer when the user is no longer interacting with the Snackbar
|
|
21853
|
+
// or when the window is shown back.
|
|
21854
|
+
const handleResume = react__WEBPACK_IMPORTED_MODULE_0__.useCallback(() => {
|
|
21855
|
+
if (autoHideDuration != null) {
|
|
21856
|
+
setAutoHideTimer(resumeHideDuration != null ? resumeHideDuration : autoHideDuration * 0.5);
|
|
21857
|
+
}
|
|
21858
|
+
}, [autoHideDuration, resumeHideDuration, setAutoHideTimer]);
|
|
21859
|
+
const createHandleBlur = otherHandlers => event => {
|
|
21860
|
+
const onBlurCallback = otherHandlers.onBlur;
|
|
21861
|
+
onBlurCallback?.(event);
|
|
21862
|
+
handleResume();
|
|
21863
|
+
};
|
|
21864
|
+
const createHandleFocus = otherHandlers => event => {
|
|
21865
|
+
const onFocusCallback = otherHandlers.onFocus;
|
|
21866
|
+
onFocusCallback?.(event);
|
|
21867
|
+
handlePause();
|
|
21868
|
+
};
|
|
21869
|
+
const createMouseEnter = otherHandlers => event => {
|
|
21870
|
+
const onMouseEnterCallback = otherHandlers.onMouseEnter;
|
|
21871
|
+
onMouseEnterCallback?.(event);
|
|
21872
|
+
handlePause();
|
|
21873
|
+
};
|
|
21874
|
+
const createMouseLeave = otherHandlers => event => {
|
|
21875
|
+
const onMouseLeaveCallback = otherHandlers.onMouseLeave;
|
|
21876
|
+
onMouseLeaveCallback?.(event);
|
|
21877
|
+
handleResume();
|
|
21878
|
+
};
|
|
21879
|
+
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
|
|
21880
|
+
// TODO: window global should be refactored here
|
|
21881
|
+
if (!disableWindowBlurListener && open) {
|
|
21882
|
+
window.addEventListener('focus', handleResume);
|
|
21883
|
+
window.addEventListener('blur', handlePause);
|
|
21884
|
+
return () => {
|
|
21885
|
+
window.removeEventListener('focus', handleResume);
|
|
21886
|
+
window.removeEventListener('blur', handlePause);
|
|
21887
|
+
};
|
|
21888
|
+
}
|
|
21889
|
+
return undefined;
|
|
21890
|
+
}, [disableWindowBlurListener, open, handleResume, handlePause]);
|
|
21891
|
+
const getRootProps = (externalProps = {}) => {
|
|
21892
|
+
const externalEventHandlers = {
|
|
21893
|
+
...(0,_mui_utils_extractEventHandlers__WEBPACK_IMPORTED_MODULE_3__["default"])(parameters),
|
|
21894
|
+
...(0,_mui_utils_extractEventHandlers__WEBPACK_IMPORTED_MODULE_3__["default"])(externalProps)
|
|
21895
|
+
};
|
|
21896
|
+
return {
|
|
21897
|
+
// ClickAwayListener adds an `onClick` prop which results in the alert not being announced.
|
|
21898
|
+
// See https://github.com/mui/material-ui/issues/29080
|
|
21899
|
+
role: 'presentation',
|
|
21900
|
+
...externalProps,
|
|
21901
|
+
...externalEventHandlers,
|
|
21902
|
+
onBlur: createHandleBlur(externalEventHandlers),
|
|
21903
|
+
onFocus: createHandleFocus(externalEventHandlers),
|
|
21904
|
+
onMouseEnter: createMouseEnter(externalEventHandlers),
|
|
21905
|
+
onMouseLeave: createMouseLeave(externalEventHandlers)
|
|
21906
|
+
};
|
|
21907
|
+
};
|
|
21908
|
+
return {
|
|
21909
|
+
getRootProps,
|
|
21910
|
+
onClickAway: handleClickAway
|
|
21911
|
+
};
|
|
21912
|
+
}
|
|
21913
|
+
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (useSnackbar);
|
|
21914
|
+
|
|
21915
|
+
/***/ }),
|
|
21916
|
+
|
|
21917
|
+
/***/ "./node_modules/@mui/material/esm/SnackbarContent/SnackbarContent.js":
|
|
21918
|
+
/*!***************************************************************************!*\
|
|
21919
|
+
!*** ./node_modules/@mui/material/esm/SnackbarContent/SnackbarContent.js ***!
|
|
21920
|
+
\***************************************************************************/
|
|
21921
|
+
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
21922
|
+
|
|
21923
|
+
"use strict";
|
|
21924
|
+
__webpack_require__.r(__webpack_exports__);
|
|
21925
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
21926
|
+
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
|
|
21927
|
+
/* harmony export */ });
|
|
21928
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "./node_modules/react/index.js");
|
|
21929
|
+
/* harmony import */ var prop_types__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! prop-types */ "./node_modules/prop-types/index.js");
|
|
21930
|
+
/* harmony import */ var clsx__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! clsx */ "./node_modules/clsx/dist/clsx.mjs");
|
|
21931
|
+
/* harmony import */ var _mui_utils_composeClasses__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @mui/utils/composeClasses */ "./node_modules/@mui/utils/esm/composeClasses/composeClasses.js");
|
|
21932
|
+
/* harmony import */ var _mui_system_colorManipulator__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @mui/system/colorManipulator */ "./node_modules/@mui/system/esm/colorManipulator/colorManipulator.js");
|
|
21933
|
+
/* harmony import */ var _zero_styled_index_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../zero-styled/index.js */ "./node_modules/@mui/material/esm/styles/styled.js");
|
|
21934
|
+
/* harmony import */ var _utils_memoTheme_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../utils/memoTheme.js */ "./node_modules/@mui/material/esm/utils/memoTheme.js");
|
|
21935
|
+
/* harmony import */ var _DefaultPropsProvider_index_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../DefaultPropsProvider/index.js */ "./node_modules/@mui/material/esm/DefaultPropsProvider/DefaultPropsProvider.js");
|
|
21936
|
+
/* harmony import */ var _Paper_index_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../Paper/index.js */ "./node_modules/@mui/material/esm/Paper/Paper.js");
|
|
21937
|
+
/* harmony import */ var _snackbarContentClasses_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./snackbarContentClasses.js */ "./node_modules/@mui/material/esm/SnackbarContent/snackbarContentClasses.js");
|
|
21938
|
+
/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! react/jsx-runtime */ "./node_modules/react/jsx-runtime.js");
|
|
21939
|
+
'use client';
|
|
21940
|
+
|
|
21941
|
+
|
|
21942
|
+
|
|
21943
|
+
|
|
21944
|
+
|
|
21945
|
+
|
|
21946
|
+
|
|
21947
|
+
|
|
21948
|
+
|
|
21949
|
+
|
|
21950
|
+
|
|
21951
|
+
|
|
21952
|
+
const useUtilityClasses = ownerState => {
|
|
21953
|
+
const {
|
|
21954
|
+
classes
|
|
21955
|
+
} = ownerState;
|
|
21956
|
+
const slots = {
|
|
21957
|
+
root: ['root'],
|
|
21958
|
+
action: ['action'],
|
|
21959
|
+
message: ['message']
|
|
21960
|
+
};
|
|
21961
|
+
return (0,_mui_utils_composeClasses__WEBPACK_IMPORTED_MODULE_3__["default"])(slots, _snackbarContentClasses_js__WEBPACK_IMPORTED_MODULE_9__.getSnackbarContentUtilityClass, classes);
|
|
21962
|
+
};
|
|
21963
|
+
const SnackbarContentRoot = (0,_zero_styled_index_js__WEBPACK_IMPORTED_MODULE_5__["default"])(_Paper_index_js__WEBPACK_IMPORTED_MODULE_8__["default"], {
|
|
21964
|
+
name: 'MuiSnackbarContent',
|
|
21965
|
+
slot: 'Root'
|
|
21966
|
+
})((0,_utils_memoTheme_js__WEBPACK_IMPORTED_MODULE_6__["default"])(({
|
|
21967
|
+
theme
|
|
21968
|
+
}) => {
|
|
21969
|
+
const emphasis = theme.palette.mode === 'light' ? 0.8 : 0.98;
|
|
21970
|
+
return {
|
|
21971
|
+
...theme.typography.body2,
|
|
21972
|
+
color: theme.vars ? theme.vars.palette.SnackbarContent.color : theme.palette.getContrastText((0,_mui_system_colorManipulator__WEBPACK_IMPORTED_MODULE_4__.emphasize)(theme.palette.background.default, emphasis)),
|
|
21973
|
+
backgroundColor: theme.vars ? theme.vars.palette.SnackbarContent.bg : (0,_mui_system_colorManipulator__WEBPACK_IMPORTED_MODULE_4__.emphasize)(theme.palette.background.default, emphasis),
|
|
21974
|
+
display: 'flex',
|
|
21975
|
+
alignItems: 'center',
|
|
21976
|
+
flexWrap: 'wrap',
|
|
21977
|
+
padding: '6px 16px',
|
|
21978
|
+
flexGrow: 1,
|
|
21979
|
+
[theme.breakpoints.up('sm')]: {
|
|
21980
|
+
flexGrow: 'initial',
|
|
21981
|
+
minWidth: 288
|
|
21982
|
+
}
|
|
21983
|
+
};
|
|
21984
|
+
}));
|
|
21985
|
+
const SnackbarContentMessage = (0,_zero_styled_index_js__WEBPACK_IMPORTED_MODULE_5__["default"])('div', {
|
|
21986
|
+
name: 'MuiSnackbarContent',
|
|
21987
|
+
slot: 'Message'
|
|
21988
|
+
})({
|
|
21989
|
+
padding: '8px 0'
|
|
21990
|
+
});
|
|
21991
|
+
const SnackbarContentAction = (0,_zero_styled_index_js__WEBPACK_IMPORTED_MODULE_5__["default"])('div', {
|
|
21992
|
+
name: 'MuiSnackbarContent',
|
|
21993
|
+
slot: 'Action'
|
|
21994
|
+
})({
|
|
21995
|
+
display: 'flex',
|
|
21996
|
+
alignItems: 'center',
|
|
21997
|
+
marginLeft: 'auto',
|
|
21998
|
+
paddingLeft: 16,
|
|
21999
|
+
marginRight: -8
|
|
22000
|
+
});
|
|
22001
|
+
const SnackbarContent = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.forwardRef(function SnackbarContent(inProps, ref) {
|
|
22002
|
+
const props = (0,_DefaultPropsProvider_index_js__WEBPACK_IMPORTED_MODULE_7__.useDefaultProps)({
|
|
22003
|
+
props: inProps,
|
|
22004
|
+
name: 'MuiSnackbarContent'
|
|
22005
|
+
});
|
|
22006
|
+
const {
|
|
22007
|
+
action,
|
|
22008
|
+
className,
|
|
22009
|
+
message,
|
|
22010
|
+
role = 'alert',
|
|
22011
|
+
...other
|
|
22012
|
+
} = props;
|
|
22013
|
+
const ownerState = props;
|
|
22014
|
+
const classes = useUtilityClasses(ownerState);
|
|
22015
|
+
return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_10__.jsxs)(SnackbarContentRoot, {
|
|
22016
|
+
role: role,
|
|
22017
|
+
elevation: 6,
|
|
22018
|
+
className: (0,clsx__WEBPACK_IMPORTED_MODULE_2__["default"])(classes.root, className),
|
|
22019
|
+
ownerState: ownerState,
|
|
22020
|
+
ref: ref,
|
|
22021
|
+
...other,
|
|
22022
|
+
children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_10__.jsx)(SnackbarContentMessage, {
|
|
22023
|
+
className: classes.message,
|
|
22024
|
+
ownerState: ownerState,
|
|
22025
|
+
children: message
|
|
22026
|
+
}), action ? /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_10__.jsx)(SnackbarContentAction, {
|
|
22027
|
+
className: classes.action,
|
|
22028
|
+
ownerState: ownerState,
|
|
22029
|
+
children: action
|
|
22030
|
+
}) : null]
|
|
22031
|
+
});
|
|
22032
|
+
});
|
|
22033
|
+
true ? SnackbarContent.propTypes /* remove-proptypes */ = {
|
|
22034
|
+
// ┌────────────────────────────── Warning ──────────────────────────────┐
|
|
22035
|
+
// │ These PropTypes are generated from the TypeScript type definitions. │
|
|
22036
|
+
// │ To update them, edit the d.ts file and run `pnpm proptypes`. │
|
|
22037
|
+
// └─────────────────────────────────────────────────────────────────────┘
|
|
22038
|
+
/**
|
|
22039
|
+
* The action to display. It renders after the message, at the end of the snackbar.
|
|
22040
|
+
*/
|
|
22041
|
+
action: prop_types__WEBPACK_IMPORTED_MODULE_1__.node,
|
|
22042
|
+
/**
|
|
22043
|
+
* Override or extend the styles applied to the component.
|
|
22044
|
+
*/
|
|
22045
|
+
classes: prop_types__WEBPACK_IMPORTED_MODULE_1__.object,
|
|
22046
|
+
/**
|
|
22047
|
+
* @ignore
|
|
22048
|
+
*/
|
|
22049
|
+
className: prop_types__WEBPACK_IMPORTED_MODULE_1__.string,
|
|
22050
|
+
/**
|
|
22051
|
+
* The message to display.
|
|
22052
|
+
*/
|
|
22053
|
+
message: prop_types__WEBPACK_IMPORTED_MODULE_1__.node,
|
|
22054
|
+
/**
|
|
22055
|
+
* The ARIA role attribute of the element.
|
|
22056
|
+
* @default 'alert'
|
|
22057
|
+
*/
|
|
22058
|
+
role: prop_types__WEBPACK_IMPORTED_MODULE_1__.string,
|
|
22059
|
+
/**
|
|
22060
|
+
* The system prop that allows defining system overrides as well as additional CSS styles.
|
|
22061
|
+
*/
|
|
22062
|
+
sx: prop_types__WEBPACK_IMPORTED_MODULE_1__.oneOfType([prop_types__WEBPACK_IMPORTED_MODULE_1__.arrayOf(prop_types__WEBPACK_IMPORTED_MODULE_1__.oneOfType([prop_types__WEBPACK_IMPORTED_MODULE_1__.func, prop_types__WEBPACK_IMPORTED_MODULE_1__.object, prop_types__WEBPACK_IMPORTED_MODULE_1__.bool])), prop_types__WEBPACK_IMPORTED_MODULE_1__.func, prop_types__WEBPACK_IMPORTED_MODULE_1__.object])
|
|
22063
|
+
} : 0;
|
|
22064
|
+
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SnackbarContent);
|
|
22065
|
+
|
|
22066
|
+
/***/ }),
|
|
22067
|
+
|
|
22068
|
+
/***/ "./node_modules/@mui/material/esm/SnackbarContent/snackbarContentClasses.js":
|
|
22069
|
+
/*!**********************************************************************************!*\
|
|
22070
|
+
!*** ./node_modules/@mui/material/esm/SnackbarContent/snackbarContentClasses.js ***!
|
|
22071
|
+
\**********************************************************************************/
|
|
22072
|
+
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
22073
|
+
|
|
22074
|
+
"use strict";
|
|
22075
|
+
__webpack_require__.r(__webpack_exports__);
|
|
22076
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
22077
|
+
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__),
|
|
22078
|
+
/* harmony export */ getSnackbarContentUtilityClass: () => (/* binding */ getSnackbarContentUtilityClass)
|
|
22079
|
+
/* harmony export */ });
|
|
22080
|
+
/* harmony import */ var _mui_utils_generateUtilityClasses__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @mui/utils/generateUtilityClasses */ "./node_modules/@mui/utils/esm/generateUtilityClasses/generateUtilityClasses.js");
|
|
22081
|
+
/* harmony import */ var _mui_utils_generateUtilityClass__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @mui/utils/generateUtilityClass */ "./node_modules/@mui/utils/esm/generateUtilityClass/generateUtilityClass.js");
|
|
22082
|
+
|
|
22083
|
+
|
|
22084
|
+
function getSnackbarContentUtilityClass(slot) {
|
|
22085
|
+
return (0,_mui_utils_generateUtilityClass__WEBPACK_IMPORTED_MODULE_1__["default"])('MuiSnackbarContent', slot);
|
|
22086
|
+
}
|
|
22087
|
+
const snackbarContentClasses = (0,_mui_utils_generateUtilityClasses__WEBPACK_IMPORTED_MODULE_0__["default"])('MuiSnackbarContent', ['root', 'message', 'action']);
|
|
22088
|
+
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (snackbarContentClasses);
|
|
22089
|
+
|
|
22090
|
+
/***/ }),
|
|
22091
|
+
|
|
20816
22092
|
/***/ "./node_modules/@mui/material/esm/Stack/Stack.js":
|
|
20817
22093
|
/*!*******************************************************!*\
|
|
20818
22094
|
!*** ./node_modules/@mui/material/esm/Stack/Stack.js ***!
|
|
@@ -99612,38 +100888,41 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
99612
100888
|
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/CircularProgress/CircularProgress.js");
|
|
99613
100889
|
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/FormHelperText/FormHelperText.js");
|
|
99614
100890
|
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/Alert/Alert.js");
|
|
99615
|
-
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/
|
|
99616
|
-
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/
|
|
99617
|
-
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/
|
|
99618
|
-
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/
|
|
99619
|
-
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/
|
|
99620
|
-
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/
|
|
99621
|
-
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/
|
|
99622
|
-
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/
|
|
99623
|
-
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/
|
|
99624
|
-
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/
|
|
99625
|
-
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/
|
|
99626
|
-
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/styles/
|
|
99627
|
-
/* harmony import */ var
|
|
99628
|
-
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/
|
|
99629
|
-
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/
|
|
99630
|
-
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/
|
|
99631
|
-
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/
|
|
99632
|
-
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/
|
|
99633
|
-
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/
|
|
99634
|
-
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/
|
|
99635
|
-
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/
|
|
99636
|
-
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/
|
|
99637
|
-
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/
|
|
99638
|
-
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/
|
|
99639
|
-
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/
|
|
99640
|
-
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/
|
|
99641
|
-
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/
|
|
99642
|
-
/* harmony import */ var
|
|
99643
|
-
/* harmony import */ var
|
|
99644
|
-
/* harmony import */ var
|
|
99645
|
-
/* harmony import */ var
|
|
99646
|
-
/* harmony import */ var
|
|
100891
|
+
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/InputAdornment/InputAdornment.js");
|
|
100892
|
+
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/Tooltip/Tooltip.js");
|
|
100893
|
+
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/FormControl/FormControl.js");
|
|
100894
|
+
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/InputLabel/InputLabel.js");
|
|
100895
|
+
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/Select/Select.js");
|
|
100896
|
+
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/MenuItem/MenuItem.js");
|
|
100897
|
+
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/FormControlLabel/FormControlLabel.js");
|
|
100898
|
+
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/Checkbox/Checkbox.js");
|
|
100899
|
+
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/ToggleButtonGroup/ToggleButtonGroup.js");
|
|
100900
|
+
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/ToggleButton/ToggleButton.js");
|
|
100901
|
+
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/Paper/Paper.js");
|
|
100902
|
+
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/styles/createTheme.js");
|
|
100903
|
+
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/styles/ThemeProvider.js");
|
|
100904
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/AccountBalance.js");
|
|
100905
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/AttachMoney.js");
|
|
100906
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/AutoAwesome.js");
|
|
100907
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/Brightness4.js");
|
|
100908
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/Brightness7.js");
|
|
100909
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/CheckCircle.js");
|
|
100910
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/CloudDownload.js");
|
|
100911
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/ContentCopy.js");
|
|
100912
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/DeleteOutline.js");
|
|
100913
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/ExpandMore.js");
|
|
100914
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/InfoOutlined.js");
|
|
100915
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/Login.js");
|
|
100916
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/Logout.js");
|
|
100917
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/NoteAdd.js");
|
|
100918
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/Replay.js");
|
|
100919
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/Settings.js");
|
|
100920
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/Visibility.js");
|
|
100921
|
+
/* harmony import */ var _PromptManagerDialog__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(/*! ./PromptManagerDialog */ "./src/PromptManagerDialog.tsx");
|
|
100922
|
+
/* harmony import */ var _promptOverrides__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(/*! ./promptOverrides */ "./src/promptOverrides.ts");
|
|
100923
|
+
/* harmony import */ var xlsx__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(/*! xlsx */ "./node_modules/xlsx/xlsx.mjs");
|
|
100924
|
+
/* harmony import */ var jszip__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(/*! jszip */ "./node_modules/jszip/dist/jszip.min.js");
|
|
100925
|
+
/* harmony import */ var jszip__WEBPACK_IMPORTED_MODULE_54___default = /*#__PURE__*/__webpack_require__.n(jszip__WEBPACK_IMPORTED_MODULE_54__);
|
|
99647
100926
|
|
|
99648
100927
|
|
|
99649
100928
|
|
|
@@ -99704,6 +100983,183 @@ const INSTRUCTION_ROW = [
|
|
|
99704
100983
|
"# Обязательно | The URL for the main image of your item. Images must be in a supported format (JPG/GIF/PNG) and at least 500 x 500 pixels.",
|
|
99705
100984
|
"# Обязательно | Фирменное название товара. Не более 100 символов."
|
|
99706
100985
|
];
|
|
100986
|
+
/** Хвост ссылки для каталога: sub/utm и макросы Meta (не URL-encode — подстановка на стороне FB). */
|
|
100987
|
+
const CATALOG_LINK_TRACKING_SUFFIX = 'sub1={{ad.id}}&sub2={{adset.id}}&sub3={{campaign.id}}&sub4={{ad.name}}&sub5={{adset.name}}&sub6={{campaign.name}}&sub7={{placement}}&sub8={{site_source_name}}&utm_source=facebook&utm_medium=paid';
|
|
100988
|
+
/** Добавляет к URL лендинга creative_id и трекинговые параметры для строки каталога. */
|
|
100989
|
+
function appendCreativeIdToCatalogLink(baseUrl, creativeId) {
|
|
100990
|
+
const u = baseUrl.trim();
|
|
100991
|
+
if (!u)
|
|
100992
|
+
return u;
|
|
100993
|
+
const sep = u.includes('?') ? '&' : '?';
|
|
100994
|
+
return `${u}${sep}creative_id=${encodeURIComponent(creativeId)}&${CATALOG_LINK_TRACKING_SUFFIX}`;
|
|
100995
|
+
}
|
|
100996
|
+
/** Текст ответа из OpenRouter/OpenAI chat completion (string или массив частей). */
|
|
100997
|
+
function extractChatCompletionText(choice) {
|
|
100998
|
+
const msg = choice?.message;
|
|
100999
|
+
if (!msg)
|
|
101000
|
+
return '';
|
|
101001
|
+
const c = msg.content;
|
|
101002
|
+
if (typeof c === 'string')
|
|
101003
|
+
return c;
|
|
101004
|
+
if (Array.isArray(c)) {
|
|
101005
|
+
return c
|
|
101006
|
+
.map((part) => (typeof part === 'string' ? part : part?.text ?? part?.content ?? ''))
|
|
101007
|
+
.filter(Boolean)
|
|
101008
|
+
.join('');
|
|
101009
|
+
}
|
|
101010
|
+
if (c != null && typeof c === 'object' && typeof c.text === 'string') {
|
|
101011
|
+
return c.text;
|
|
101012
|
+
}
|
|
101013
|
+
return '';
|
|
101014
|
+
}
|
|
101015
|
+
function stripMarkdownJsonFence(raw) {
|
|
101016
|
+
let s = raw.trim();
|
|
101017
|
+
if (!s.startsWith('```'))
|
|
101018
|
+
return s;
|
|
101019
|
+
s = s.replace(/^```(?:json)?\s*/i, '');
|
|
101020
|
+
const end = s.lastIndexOf('```');
|
|
101021
|
+
if (end >= 0)
|
|
101022
|
+
s = s.slice(0, end).trim();
|
|
101023
|
+
return s;
|
|
101024
|
+
}
|
|
101025
|
+
/** Парсит JSON-массив переводов из ответа модели (с ```json или мусором вокруг). */
|
|
101026
|
+
function parsePairTranslationsJson(raw) {
|
|
101027
|
+
const cleaned = stripMarkdownJsonFence(raw);
|
|
101028
|
+
try {
|
|
101029
|
+
const parsed = JSON.parse(cleaned);
|
|
101030
|
+
if (Array.isArray(parsed))
|
|
101031
|
+
return parsed;
|
|
101032
|
+
}
|
|
101033
|
+
catch {
|
|
101034
|
+
/* далее — вырезка по скобкам */
|
|
101035
|
+
}
|
|
101036
|
+
const jsonMatch = cleaned.match(/\[[\s\S]*\]/);
|
|
101037
|
+
if (!jsonMatch)
|
|
101038
|
+
return null;
|
|
101039
|
+
try {
|
|
101040
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
101041
|
+
return Array.isArray(parsed) ? parsed : null;
|
|
101042
|
+
}
|
|
101043
|
+
catch {
|
|
101044
|
+
return null;
|
|
101045
|
+
}
|
|
101046
|
+
}
|
|
101047
|
+
/** Убирает повторяющиеся префиксы «ОШИБКА:» и лишние пробелы в строке из ответа валидатора. */
|
|
101048
|
+
function normalizeValidationErrorText(s) {
|
|
101049
|
+
let t = s.trim().replace(/\s+/g, ' ');
|
|
101050
|
+
while (/^ОШИБКА[:\s]+/i.test(t)) {
|
|
101051
|
+
t = t.replace(/^ОШИБКА[:\s]+/i, '').trim();
|
|
101052
|
+
}
|
|
101053
|
+
return t;
|
|
101054
|
+
}
|
|
101055
|
+
/** Одна и та же формулировка из ответа модели не дублируется в UI и в промпте переделки. */
|
|
101056
|
+
function dedupeValidationErrors(errors) {
|
|
101057
|
+
const seen = new Set();
|
|
101058
|
+
const out = [];
|
|
101059
|
+
for (const raw of errors) {
|
|
101060
|
+
const n = normalizeValidationErrorText(raw);
|
|
101061
|
+
if (!n)
|
|
101062
|
+
continue;
|
|
101063
|
+
const key = n.toLowerCase();
|
|
101064
|
+
if (seen.has(key))
|
|
101065
|
+
continue;
|
|
101066
|
+
seen.add(key);
|
|
101067
|
+
out.push(n);
|
|
101068
|
+
}
|
|
101069
|
+
return out;
|
|
101070
|
+
}
|
|
101071
|
+
/** Строка «ОШИБКА: нет» при статусе пересборки — противоречие; не считать содержательной ошибкой. */
|
|
101072
|
+
function isValidationNegationLine(s) {
|
|
101073
|
+
const t = normalizeValidationErrorText(s).toLowerCase();
|
|
101074
|
+
if (!t)
|
|
101075
|
+
return true;
|
|
101076
|
+
if (t === 'нет')
|
|
101077
|
+
return true;
|
|
101078
|
+
if (t.includes('нет ошибок') || t.includes('ошибок нет'))
|
|
101079
|
+
return true;
|
|
101080
|
+
if (t === 'none' || /^no errors?\.?$/i.test(t))
|
|
101081
|
+
return true;
|
|
101082
|
+
return false;
|
|
101083
|
+
}
|
|
101084
|
+
/** Все подписанные строки ОШИБКА:/ERROR: (модель иногда пишет по-английски). */
|
|
101085
|
+
function extractLabeledValidationErrors(content) {
|
|
101086
|
+
const out = [];
|
|
101087
|
+
const patterns = [
|
|
101088
|
+
/(?:^|\n)\s*ОШИБКА\s*[:\s]\s*([^\n]+)/gi,
|
|
101089
|
+
/(?:^|\n)\s*ERROR\s*[:\s]\s*([^\n]+)/gi,
|
|
101090
|
+
];
|
|
101091
|
+
for (const re of patterns) {
|
|
101092
|
+
let m;
|
|
101093
|
+
const r = new RegExp(re.source, re.flags);
|
|
101094
|
+
while ((m = r.exec(content)) !== null) {
|
|
101095
|
+
const t = normalizeValidationErrorText(m[1]);
|
|
101096
|
+
if (t)
|
|
101097
|
+
out.push(t);
|
|
101098
|
+
}
|
|
101099
|
+
}
|
|
101100
|
+
return out;
|
|
101101
|
+
}
|
|
101102
|
+
/**
|
|
101103
|
+
* Если модель поставила НУЖНА ПЕРЕСБОРКА, но не оформила список как ОШИБКА: — забираем осмысленные строки
|
|
101104
|
+
* между статусом и блоком РЕКОМЕНДАЦИЯ (часто там остаётся описание причин).
|
|
101105
|
+
*/
|
|
101106
|
+
function extractFallbackValidationErrorsBetweenStatusAndRecommendations(content) {
|
|
101107
|
+
const statusNeed = /СТАТУС\s*:\s*НУЖНА\s+ПЕРЕСБОРКА/i;
|
|
101108
|
+
const idx = content.search(statusNeed);
|
|
101109
|
+
if (idx < 0)
|
|
101110
|
+
return [];
|
|
101111
|
+
const tail = content.slice(idx);
|
|
101112
|
+
const firstNl = tail.indexOf('\n');
|
|
101113
|
+
const blockStart = firstNl >= 0 ? idx + firstNl + 1 : content.length;
|
|
101114
|
+
const rest = content.slice(blockStart);
|
|
101115
|
+
const recIdx = rest.search(/\nРЕКОМЕНДАЦИЯ\s*:/i);
|
|
101116
|
+
const block = recIdx >= 0 ? rest.slice(0, recIdx) : rest.slice(0, 3500);
|
|
101117
|
+
const lines = block.split('\n').map(l => l.trim()).filter(l => {
|
|
101118
|
+
if (l.length < 12)
|
|
101119
|
+
return false;
|
|
101120
|
+
if (/^(затем|список|каждая)\s/i.test(l))
|
|
101121
|
+
return false;
|
|
101122
|
+
if (/^ОШИБКА\s*[:\s]*нет\s*\.?$/i.test(l))
|
|
101123
|
+
return false;
|
|
101124
|
+
if (/^РЕКОМЕНДАЦИЯ\s*:/i.test(l))
|
|
101125
|
+
return false;
|
|
101126
|
+
if (/^ШАГ\s+[\dP]/i.test(l))
|
|
101127
|
+
return false;
|
|
101128
|
+
if (/^(?:HOOK|HEADLINE|PRICE|DISCOUNT|CTA|OTHER_TEXT)\s*:/i.test(l))
|
|
101129
|
+
return false;
|
|
101130
|
+
if (/^СТАТУС\s*:/i.test(l))
|
|
101131
|
+
return false;
|
|
101132
|
+
return true;
|
|
101133
|
+
});
|
|
101134
|
+
return lines
|
|
101135
|
+
.map(l => normalizeValidationErrorText(l.replace(/^ОШИБКА\s*[:\s]+/i, '')))
|
|
101136
|
+
.filter(Boolean);
|
|
101137
|
+
}
|
|
101138
|
+
/** Короткий фрагмент блока ФИНАЛ для подсказки, если структура ответа нестандартная. */
|
|
101139
|
+
function extractValidationFinalSnippet(content, maxLen) {
|
|
101140
|
+
const fi = content.search(/\bФИНАЛ\s*:/i);
|
|
101141
|
+
if (fi < 0)
|
|
101142
|
+
return null;
|
|
101143
|
+
let sn = content.slice(fi, fi + maxLen).replace(/\s+/g, ' ').trim();
|
|
101144
|
+
if (sn.length < 50)
|
|
101145
|
+
return null;
|
|
101146
|
+
if (sn.length > maxLen)
|
|
101147
|
+
sn = `${sn.slice(0, maxLen - 1)}…`;
|
|
101148
|
+
return sn;
|
|
101149
|
+
}
|
|
101150
|
+
/**
|
|
101151
|
+
* Разбор строк «ЗАГОЛОВОК n:» / «ТЕКСТ n:» из ответа модели.
|
|
101152
|
+
* Иногда модель пишет ZAGОЛОВОК (латиница ZAG + кириллица ОЛОВОК) или ZAGOLOVOK — без этого парсер не видит заголовки.
|
|
101153
|
+
*/
|
|
101154
|
+
const PAIRS_TITLE_LINE_RE = /^[\s\uFEFF]*(?:\*{1,2})?\s*(?:ЗАГОЛОВОК|ZAG[ОOо][ЛLl][ОOо][ВBb][ОOо][КKk]|ZAGOLOVOK)\s+(\d+)\s*:\s*(.+)$/iu;
|
|
101155
|
+
const PAIRS_TEXT_LINE_RE = /^[\s\uFEFF]*(?:\*{1,2})?\s*(?:ТЕКСТ|TEKST)\s+(\d+)\s*:\s*(.*)$/iu;
|
|
101156
|
+
/** Число из поля цены для быстрого переключения валюты; если нет — 99 */
|
|
101157
|
+
function extractLeadingPriceNumber(value) {
|
|
101158
|
+
const m = value.trim().match(/(\d+(?:[.,]\d+)?)/);
|
|
101159
|
+
if (m)
|
|
101160
|
+
return m[1].replace(',', '.');
|
|
101161
|
+
return '99';
|
|
101162
|
+
}
|
|
99707
101163
|
function App() {
|
|
99708
101164
|
const [clientId, setClientId] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)('');
|
|
99709
101165
|
const [clientSecret, setClientSecret] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)('');
|
|
@@ -99946,9 +101402,11 @@ function App() {
|
|
|
99946
101402
|
const [uploadedLink, setUploadedLink] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)('');
|
|
99947
101403
|
const [testLoading, setTestLoading] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false);
|
|
99948
101404
|
const [linkCopied, setLinkCopied] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false);
|
|
101405
|
+
const [pairsJsonCopied, setPairsJsonCopied] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false);
|
|
99949
101406
|
const [openRouterKeyCopied, setOpenRouterKeyCopied] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false);
|
|
99950
101407
|
const [loadingContentFromDrive, setLoadingContentFromDrive] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false);
|
|
99951
101408
|
const [driveFilesFound, setDriveFilesFound] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)({ content: false });
|
|
101409
|
+
const syncDriveAfterPromptSaveRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(() => { });
|
|
99952
101410
|
// Theme state
|
|
99953
101411
|
const [darkMode, setDarkMode] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(() => {
|
|
99954
101412
|
const saved = localStorage.getItem('themeMode');
|
|
@@ -99995,7 +101453,7 @@ function App() {
|
|
|
99995
101453
|
}
|
|
99996
101454
|
};
|
|
99997
101455
|
// Create theme based on mode
|
|
99998
|
-
const theme = react__WEBPACK_IMPORTED_MODULE_0___default().useMemo(() => (0,
|
|
101456
|
+
const theme = react__WEBPACK_IMPORTED_MODULE_0___default().useMemo(() => (0,_mui_material__WEBPACK_IMPORTED_MODULE_32__["default"])({
|
|
99999
101457
|
palette: {
|
|
100000
101458
|
mode: darkMode ? 'dark' : 'light',
|
|
100001
101459
|
...(darkMode
|
|
@@ -100087,7 +101545,7 @@ function App() {
|
|
|
100087
101545
|
};
|
|
100088
101546
|
loadKey();
|
|
100089
101547
|
// Load prompt overrides from Electron config
|
|
100090
|
-
(0,
|
|
101548
|
+
(0,_promptOverrides__WEBPACK_IMPORTED_MODULE_52__.loadOverridesFromElectron)();
|
|
100091
101549
|
}, []);
|
|
100092
101550
|
// Save form fields to localStorage whenever they change
|
|
100093
101551
|
(0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
|
|
@@ -100143,6 +101601,8 @@ function App() {
|
|
|
100143
101601
|
setTitles('');
|
|
100144
101602
|
setTexts(['']);
|
|
100145
101603
|
setLink('');
|
|
101604
|
+
setUploadedLink('');
|
|
101605
|
+
setPairTranslations({});
|
|
100146
101606
|
return;
|
|
100147
101607
|
}
|
|
100148
101608
|
const folderId = extractFolderId(driveFolderUrl);
|
|
@@ -100157,6 +101617,8 @@ function App() {
|
|
|
100157
101617
|
setTitles('');
|
|
100158
101618
|
setTexts(['']);
|
|
100159
101619
|
setLink('');
|
|
101620
|
+
setUploadedLink('');
|
|
101621
|
+
setPairTranslations({});
|
|
100160
101622
|
return;
|
|
100161
101623
|
}
|
|
100162
101624
|
logToTerminal('log', '[Load] driveFolderUrl changed, clearing old data and loading from folderId:', folderId);
|
|
@@ -100167,6 +101629,8 @@ function App() {
|
|
|
100167
101629
|
setTitles('');
|
|
100168
101630
|
setTexts(['']);
|
|
100169
101631
|
setLink('');
|
|
101632
|
+
setUploadedLink('');
|
|
101633
|
+
setPairTranslations({});
|
|
100170
101634
|
setLoadingContentFromDrive(true);
|
|
100171
101635
|
setDriveFilesFound({ content: false });
|
|
100172
101636
|
// Load content from Google Drive
|
|
@@ -100437,11 +101901,11 @@ function App() {
|
|
|
100437
101901
|
const data = await response.json();
|
|
100438
101902
|
const hasProduct = data.files.some((f) => {
|
|
100439
101903
|
const name = f.name?.toLowerCase() || '';
|
|
100440
|
-
return name === 'product.png' || name === 'product.jpg';
|
|
101904
|
+
return name === 'product.png' || name === 'product.jpg' || name === 'product.webp';
|
|
100441
101905
|
});
|
|
100442
101906
|
const hasCreativeImages = data.files.some((f) => {
|
|
100443
101907
|
const name = f.name?.toLowerCase() || '';
|
|
100444
|
-
return name !== 'product.png' && name !== 'product.jpg';
|
|
101908
|
+
return name !== 'product.png' && name !== 'product.jpg' && name !== 'product.webp';
|
|
100445
101909
|
});
|
|
100446
101910
|
if (!cancelled) {
|
|
100447
101911
|
setFolderFilesInfo({ hasProduct, hasCreativeImages });
|
|
@@ -101416,7 +102880,7 @@ function App() {
|
|
|
101416
102880
|
for (let li = 0; li < lines.length; li++) {
|
|
101417
102881
|
// Trim for matching (handles leading spaces, tabs, zero-width chars from model)
|
|
101418
102882
|
const trimmed = lines[li].trim();
|
|
101419
|
-
const titleMatch = trimmed.match(
|
|
102883
|
+
const titleMatch = trimmed.match(PAIRS_TITLE_LINE_RE);
|
|
101420
102884
|
if (titleMatch) {
|
|
101421
102885
|
// flush pending text
|
|
101422
102886
|
if (currentTextNum > 0) {
|
|
@@ -101427,7 +102891,7 @@ function App() {
|
|
|
101427
102891
|
titleMap[parseInt(titleMatch[1])] = titleMatch[2].trim();
|
|
101428
102892
|
continue;
|
|
101429
102893
|
}
|
|
101430
|
-
const textMatch = trimmed.match(
|
|
102894
|
+
const textMatch = trimmed.match(PAIRS_TEXT_LINE_RE);
|
|
101431
102895
|
if (textMatch) {
|
|
101432
102896
|
// flush previous text if any
|
|
101433
102897
|
if (currentTextNum > 0) {
|
|
@@ -101495,27 +102959,73 @@ function App() {
|
|
|
101495
102959
|
},
|
|
101496
102960
|
body: JSON.stringify(requestBody)
|
|
101497
102961
|
});
|
|
101498
|
-
if (!response.ok)
|
|
102962
|
+
if (!response.ok) {
|
|
102963
|
+
logToTerminal('warn', '[Translate RU] HTTP', response.status, '— перевод пар пропущен');
|
|
101499
102964
|
return;
|
|
102965
|
+
}
|
|
101500
102966
|
const data = await response.json();
|
|
101501
|
-
const
|
|
101502
|
-
|
|
101503
|
-
|
|
102967
|
+
const choice = data.choices?.[0];
|
|
102968
|
+
let raw = extractChatCompletionText(choice) ||
|
|
102969
|
+
(typeof choice?.text === 'string' ? choice.text : '') ||
|
|
102970
|
+
'';
|
|
102971
|
+
if (!raw.trim()) {
|
|
102972
|
+
logToTerminal('warn', '[Translate RU] Пустой ответ модели (content), перевод не выполнен');
|
|
102973
|
+
return;
|
|
102974
|
+
}
|
|
102975
|
+
const parsed = parsePairTranslationsJson(raw);
|
|
102976
|
+
if (!parsed || parsed.length === 0) {
|
|
102977
|
+
logToTerminal('warn', '[Translate RU] Не удалось разобрать JSON-массив переводов, превью:', raw.substring(0, 280));
|
|
101504
102978
|
return;
|
|
101505
|
-
|
|
102979
|
+
}
|
|
101506
102980
|
const translations = {};
|
|
101507
102981
|
parsed.forEach((item, idx) => {
|
|
101508
102982
|
translations[idx] = { titleRu: item.titleRu || '', textRu: item.textRu || '' };
|
|
101509
102983
|
});
|
|
101510
102984
|
setPairTranslations(translations);
|
|
102985
|
+
logToTerminal('log', '[Translate RU] OK, пар переведено:', parsed.length);
|
|
101511
102986
|
}
|
|
101512
102987
|
catch {
|
|
101513
|
-
|
|
102988
|
+
logToTerminal('warn', '[Translate RU] Ошибка запроса или разбора — см. консоль / лог');
|
|
101514
102989
|
}
|
|
101515
102990
|
finally {
|
|
101516
102991
|
setTranslatingPairs(false);
|
|
101517
102992
|
}
|
|
101518
102993
|
};
|
|
102994
|
+
/** Удалить одну сгенерированную пару (заголовок + текст) и сдвинуть индексы. */
|
|
102995
|
+
const handleDeleteGeneratedPair = (pairIndex) => {
|
|
102996
|
+
if (!window.confirm(`Удалить пару ${pairIndex + 1}?`))
|
|
102997
|
+
return;
|
|
102998
|
+
setGeneratedTitlesData(prev => {
|
|
102999
|
+
const next = prev.filter((_, idx) => idx !== pairIndex).map((t, idx) => ({ ...t, index: idx + 1 }));
|
|
103000
|
+
setTitles(next.map(t => t.title).filter(Boolean).join('\n'));
|
|
103001
|
+
return next;
|
|
103002
|
+
});
|
|
103003
|
+
setGeneratedTextsData(prev => {
|
|
103004
|
+
const next = prev.filter((_, idx) => idx !== pairIndex).map((t, idx) => ({ ...t, index: idx + 1 }));
|
|
103005
|
+
setTexts(next.length ? next.map(t => t.text) : ['']);
|
|
103006
|
+
return next;
|
|
103007
|
+
});
|
|
103008
|
+
setLastUsedApproachIndices(prev => prev.filter((_, idx) => idx !== pairIndex));
|
|
103009
|
+
setPairTranslations(prev => {
|
|
103010
|
+
const next = {};
|
|
103011
|
+
Object.entries(prev).forEach(([k, v]) => {
|
|
103012
|
+
const n = Number(k);
|
|
103013
|
+
if (Number.isNaN(n))
|
|
103014
|
+
return;
|
|
103015
|
+
if (n < pairIndex)
|
|
103016
|
+
next[n] = v;
|
|
103017
|
+
else if (n > pairIndex)
|
|
103018
|
+
next[n - 1] = v;
|
|
103019
|
+
});
|
|
103020
|
+
return next;
|
|
103021
|
+
});
|
|
103022
|
+
};
|
|
103023
|
+
/** Удалить один сгенерированный креатив и перенумеровать слоты. */
|
|
103024
|
+
const handleDeleteGeneratedImage = (imageIndex) => {
|
|
103025
|
+
if (!window.confirm(`Удалить креатив ${imageIndex}?`))
|
|
103026
|
+
return;
|
|
103027
|
+
setGeneratedImagesData(prev => prev.filter(img => img.index !== imageIndex).map((img, idx) => ({ ...img, index: idx + 1 })));
|
|
103028
|
+
};
|
|
101519
103029
|
const handleGenerateContent = async () => {
|
|
101520
103030
|
if (!generateProduct.trim() || !generateGeo.trim()) {
|
|
101521
103031
|
alert('Please fill in Product and Geo fields');
|
|
@@ -101531,7 +103041,7 @@ function App() {
|
|
|
101531
103041
|
setTexts(['']);
|
|
101532
103042
|
setPairTranslations({});
|
|
101533
103043
|
// Read pairs count from settings (3–10, default 3)
|
|
101534
|
-
const pairsCountInit = (0,
|
|
103044
|
+
const pairsCountInit = (0,_promptOverrides__WEBPACK_IMPORTED_MODULE_52__.getPairsCount)();
|
|
101535
103045
|
// Initialize placeholders
|
|
101536
103046
|
const initialTitles = Array.from({ length: pairsCountInit }, (_, index) => ({
|
|
101537
103047
|
index: index + 1,
|
|
@@ -101560,7 +103070,7 @@ function App() {
|
|
|
101560
103070
|
}
|
|
101561
103071
|
// Generate all pairs (title + text) in a single request
|
|
101562
103072
|
addLog(formatLogMessage('log', '📋 Generating title+text pairs in a single request...'));
|
|
101563
|
-
const selectedIndices = (0,
|
|
103073
|
+
const selectedIndices = (0,_promptOverrides__WEBPACK_IMPORTED_MODULE_52__.getSelectedPairApproaches)();
|
|
101564
103074
|
setLastUsedApproachIndices(selectedIndices);
|
|
101565
103075
|
const pairsCount = selectedIndices.length;
|
|
101566
103076
|
addLog(formatLogMessage('log', `⚙️ Generating ${pairsCount} pairs (approaches: ${selectedIndices.join(', ')})`));
|
|
@@ -101997,7 +103507,21 @@ function App() {
|
|
|
101997
103507
|
};
|
|
101998
103508
|
const keywords = geoKeywords[geo.toUpperCase()] || ['продукт', 'проблема'];
|
|
101999
103509
|
logMsg('log', `🔑 Ключевые слова: ${keywords.join(', ')}`);
|
|
102000
|
-
const
|
|
103510
|
+
const { price: briefPrice, currency: briefCurrency, currencySymbol } = parsePriceAndCurrency(generatePriceWithCurrency);
|
|
103511
|
+
let priceBriefForValidation = '';
|
|
103512
|
+
if (briefPrice && briefCurrency) {
|
|
103513
|
+
const nv = parseFloat(String(briefPrice).replace(',', '.'));
|
|
103514
|
+
const oldNum = Number.isFinite(nv) && nv > 0 ? nv * 2 : NaN;
|
|
103515
|
+
const oldStr = Number.isFinite(oldNum)
|
|
103516
|
+
? (Number.isInteger(oldNum) ? String(oldNum) : (Math.round(oldNum * 100) / 100).toString().replace(/\.?0+$/, ''))
|
|
103517
|
+
: '';
|
|
103518
|
+
priceBriefForValidation = `Новая цена по брифу (после скидки -50%): ${briefPrice} ${briefCurrency}${currencySymbol ? `, символ валюты: ${currencySymbol}` : ''}. ${Number.isFinite(oldNum) ? `Ожидаемая старая цена до скидки: ${oldStr} ${briefCurrency} (2× новой).` : 'Старая цена на макете должна быть в 2 раза больше новой.'} Любые другие суммы — ошибка «не совпадает с брифом».`;
|
|
103519
|
+
logMsg('log', `💶 Эталон цен для валидации: новая ${briefPrice} ${briefCurrency}${oldStr ? `, старая ${oldStr}` : ''}`);
|
|
103520
|
+
}
|
|
103521
|
+
else {
|
|
103522
|
+
logMsg('log', '💶 Поле цены в приложении пустое — валидатор сверяет только визуал двух цен');
|
|
103523
|
+
}
|
|
103524
|
+
const validationPrompt = (0,_prompts__WEBPACK_IMPORTED_MODULE_1__.getValidationPrompt)(product, geo, keywords, approachName, undefined, priceBriefForValidation);
|
|
102001
103525
|
const requestBody = {
|
|
102002
103526
|
model: selectedValidationModel,
|
|
102003
103527
|
messages: [
|
|
@@ -102136,25 +103660,28 @@ function App() {
|
|
|
102136
103660
|
}
|
|
102137
103661
|
// Update balance after successful API call
|
|
102138
103662
|
fetchOpenRouterBalance();
|
|
102139
|
-
// Парсим результат
|
|
102140
|
-
const
|
|
102141
|
-
const
|
|
102142
|
-
|
|
102143
|
-
const
|
|
102144
|
-
|
|
102145
|
-
|
|
102146
|
-
|
|
102147
|
-
|
|
102148
|
-
|
|
102149
|
-
|
|
102150
|
-
|
|
102151
|
-
|
|
102152
|
-
|
|
102153
|
-
|
|
102154
|
-
|
|
102155
|
-
|
|
103663
|
+
// Парсим результат (английский STATUS — на случай ответа модели не по шаблону)
|
|
103664
|
+
const statusMatchRu = content.match(/СТАТУС\s*:\s*(OK|НУЖНА\s+ПЕРЕСБОРКА)/i);
|
|
103665
|
+
const statusMatchEn = content.match(/\bSTATUS\s*:\s*(OK|NEEDS?\s+REBUILD|FAIL|FAILED)\b/i);
|
|
103666
|
+
const statusToken = statusMatchRu?.[1] ?? statusMatchEn?.[1] ?? '';
|
|
103667
|
+
const status = (() => {
|
|
103668
|
+
if (!statusToken)
|
|
103669
|
+
return 'needs_rebuild';
|
|
103670
|
+
const u = statusToken.toUpperCase().replace(/\s+/g, ' ');
|
|
103671
|
+
if (u === 'OK')
|
|
103672
|
+
return 'ok';
|
|
103673
|
+
if (u.includes('NEED') || u === 'FAIL' || u === 'FAILED')
|
|
103674
|
+
return 'needs_rebuild';
|
|
103675
|
+
if (u.includes('НУЖНА') || u.includes('ПЕРЕСБОРКА'))
|
|
103676
|
+
return 'needs_rebuild';
|
|
103677
|
+
return 'needs_rebuild';
|
|
103678
|
+
})();
|
|
103679
|
+
let errors = extractLabeledValidationErrors(content).filter(e => !isValidationNegationLine(e));
|
|
103680
|
+
errors = dedupeValidationErrors(errors);
|
|
103681
|
+
// Противоречие: пересборка, а единственная строка была «ОШИБКА: нет» — тянем текст из хвоста ответа
|
|
103682
|
+
if (status === 'needs_rebuild' && errors.length === 0) {
|
|
103683
|
+
errors = dedupeValidationErrors(extractFallbackValidationErrorsBetweenStatusAndRecommendations(content));
|
|
102156
103684
|
}
|
|
102157
|
-
// Если статус "НУЖНА ПЕРЕСБОРКА", но ошибок нет в формате ОШИБКА, ищем в тексте
|
|
102158
103685
|
if (status === 'needs_rebuild' && errors.length === 0) {
|
|
102159
103686
|
const lines = content.split('\n').filter(line => line.includes('нарушено') ||
|
|
102160
103687
|
line.includes('проблема') ||
|
|
@@ -102162,10 +103689,20 @@ function App() {
|
|
|
102162
103689
|
line.includes('не хватает'));
|
|
102163
103690
|
if (lines.length > 0) {
|
|
102164
103691
|
errors.push(...lines.map(l => l.trim()).filter(l => l.length > 0));
|
|
103692
|
+
errors = dedupeValidationErrors(errors);
|
|
102165
103693
|
}
|
|
102166
103694
|
}
|
|
102167
103695
|
const totalElapsed = Date.now() - validationStartTime;
|
|
102168
|
-
const
|
|
103696
|
+
const snippet = status === 'needs_rebuild' && errors.length === 0
|
|
103697
|
+
? extractValidationFinalSnippet(content, 900)
|
|
103698
|
+
: null;
|
|
103699
|
+
const finalErrors = errors.length > 0
|
|
103700
|
+
? errors
|
|
103701
|
+
: status === 'needs_rebuild'
|
|
103702
|
+
? (snippet
|
|
103703
|
+
? [`Валидатор не выписал строки «ОШИБКА:». Фрагмент ответа: ${snippet}`]
|
|
103704
|
+
: ['Валидатор указал пересборку, но не перечислил причины (нет строк «ОШИБКА:»). Откройте полный текст ответа модели в логе или повторите проверку.'])
|
|
103705
|
+
: [];
|
|
102169
103706
|
logMsg('log', `✅ === Валидация завершена ===`);
|
|
102170
103707
|
logMsg('log', `⏱️ Общее время: ${Math.round(totalElapsed / 1000)}s`);
|
|
102171
103708
|
logMsg('log', `📊 Статус: ${status === 'ok' ? '✅ OK' : '❌ НУЖНА ПЕРЕСБОРКА'}`);
|
|
@@ -102194,8 +103731,8 @@ function App() {
|
|
|
102194
103731
|
return;
|
|
102195
103732
|
e.target.value = '';
|
|
102196
103733
|
const ext = file.name.toLowerCase().split('.').pop();
|
|
102197
|
-
if (ext !== 'png' && ext !== 'jpg' && ext !== 'jpeg') {
|
|
102198
|
-
alert('Выберите изображение PNG или
|
|
103734
|
+
if (ext !== 'png' && ext !== 'jpg' && ext !== 'jpeg' && ext !== 'webp') {
|
|
103735
|
+
alert('Выберите изображение PNG, JPG или WebP');
|
|
102199
103736
|
return;
|
|
102200
103737
|
}
|
|
102201
103738
|
setUploadingProduct(true);
|
|
@@ -102219,12 +103756,12 @@ function App() {
|
|
|
102219
103756
|
reader.onerror = reject;
|
|
102220
103757
|
reader.readAsDataURL(file);
|
|
102221
103758
|
});
|
|
102222
|
-
const filename = ext === 'png' ? 'product.png' : 'product.jpg';
|
|
102223
|
-
logToTerminal('log',
|
|
103759
|
+
const filename = ext === 'png' ? 'product.png' : ext === 'webp' ? 'product.webp' : 'product.jpg';
|
|
103760
|
+
logToTerminal('log', `📤 Загрузка ${filename}...`);
|
|
102224
103761
|
await uploadImageToDrive(dataUrl, filename, folderId, addLog);
|
|
102225
|
-
logToTerminal('log',
|
|
103762
|
+
logToTerminal('log', `✅ ${filename} загружен`);
|
|
102226
103763
|
setFolderFilesInfo(prev => prev ? { ...prev, hasProduct: true } : { hasProduct: true });
|
|
102227
|
-
alert(
|
|
103764
|
+
alert(`${filename} успешно загружен в папку!`);
|
|
102228
103765
|
}
|
|
102229
103766
|
catch (err) {
|
|
102230
103767
|
const errorMsg = 'Ошибка загрузки: ' + err.message;
|
|
@@ -102465,17 +104002,19 @@ function App() {
|
|
|
102465
104002
|
fetchOpenRouterBalance();
|
|
102466
104003
|
return html;
|
|
102467
104004
|
};
|
|
102468
|
-
const createZipArchive = async (htmlContent, productImageBlob, addLog) => {
|
|
104005
|
+
const createZipArchive = async (htmlContent, productImageBlob, productImageName, addLog) => {
|
|
102469
104006
|
const logMsg = (level, ...args) => {
|
|
102470
104007
|
logToTerminal(level, ...args);
|
|
102471
104008
|
if (addLog)
|
|
102472
104009
|
addLog(formatLogMessage(level, ...args));
|
|
102473
104010
|
};
|
|
102474
104011
|
logMsg('log', '📦 Creating ZIP archive with HTML and product image...');
|
|
102475
|
-
const zip = new (
|
|
102476
|
-
|
|
102477
|
-
|
|
102478
|
-
|
|
104012
|
+
const zip = new (jszip__WEBPACK_IMPORTED_MODULE_54___default())();
|
|
104013
|
+
// Replace product image path in HTML to match actual filename (png/jpg/webp)
|
|
104014
|
+
const htmlWithProductPath = htmlContent.replace(/src=["']product\.(png|jpe?g|webp)["']/gi, `src="${productImageName}"`);
|
|
104015
|
+
zip.file('index.html', htmlWithProductPath);
|
|
104016
|
+
zip.file(productImageName, productImageBlob);
|
|
104017
|
+
logMsg('log', `✅ Files added to archive: index.html, ${productImageName}`);
|
|
102479
104018
|
return await zip.generateAsync({ type: 'blob' });
|
|
102480
104019
|
};
|
|
102481
104020
|
const uploadZipToDrive = async (zipBlob, filename, folderId, addLog) => {
|
|
@@ -102612,7 +104151,7 @@ function App() {
|
|
|
102612
104151
|
};
|
|
102613
104152
|
const handleCreateLanding = async () => {
|
|
102614
104153
|
if (!folderFilesInfo?.hasProduct || !driveFolderUrl.trim()) {
|
|
102615
|
-
alert('product.png/jpg не найден в папке. Сначала сгенерируйте его с помощью кнопки "Generate Product from Banka"');
|
|
104154
|
+
alert('product.png/jpg/webp не найден в папке. Сначала сгенерируйте его с помощью кнопки "Generate Product from Banka"');
|
|
102616
104155
|
return;
|
|
102617
104156
|
}
|
|
102618
104157
|
if (!openaiApiKey) {
|
|
@@ -102642,11 +104181,11 @@ function App() {
|
|
|
102642
104181
|
logToTerminal('log', '🔍 Получение изображения продукта...');
|
|
102643
104182
|
const productImage = await fetchProductImage(folderId);
|
|
102644
104183
|
if (!productImage) {
|
|
102645
|
-
throw new Error('product.png/jpg not found in the folder');
|
|
104184
|
+
throw new Error('product.png/jpg/webp not found in the folder');
|
|
102646
104185
|
}
|
|
102647
104186
|
// Download product image as blob
|
|
102648
|
-
addLog(formatLogMessage('log', '📥 Скачивание
|
|
102649
|
-
logToTerminal('log', '📥 Скачивание
|
|
104187
|
+
addLog(formatLogMessage('log', '📥 Скачивание изображения продукта...'));
|
|
104188
|
+
logToTerminal('log', '📥 Скачивание изображения продукта...');
|
|
102650
104189
|
let token = await getValidAccessToken();
|
|
102651
104190
|
if (!token) {
|
|
102652
104191
|
throw new Error('Not logged in to Google Drive');
|
|
@@ -102702,7 +104241,7 @@ function App() {
|
|
|
102702
104241
|
reader.readAsDataURL(productImageBlob);
|
|
102703
104242
|
});
|
|
102704
104243
|
// Replace relative image path with base64 data URL in HTML
|
|
102705
|
-
const htmlWithImage = htmlContent.replace(/src=["']product\.(png|jpe?g)["']/gi, `src="${imageBase64}"`);
|
|
104244
|
+
const htmlWithImage = htmlContent.replace(/src=["']product\.(png|jpe?g|webp)["']/gi, `src="${imageBase64}"`);
|
|
102706
104245
|
// Create blob URL and open in new window
|
|
102707
104246
|
const blob = new Blob([htmlWithImage], { type: 'text/html' });
|
|
102708
104247
|
const url = URL.createObjectURL(blob);
|
|
@@ -102721,7 +104260,7 @@ function App() {
|
|
|
102721
104260
|
// Create ZIP archive with HTML and product image
|
|
102722
104261
|
addLog(formatLogMessage('log', '📦 Создание ZIP архива с HTML и изображением...'));
|
|
102723
104262
|
logToTerminal('log', '📦 Создание ZIP архива...');
|
|
102724
|
-
const zipBlob = await createZipArchive(htmlContent, productImageBlob, addLog);
|
|
104263
|
+
const zipBlob = await createZipArchive(htmlContent, productImageBlob, productImage.name, addLog);
|
|
102725
104264
|
addLog(formatLogMessage('log', '✅ ZIP архив создан'));
|
|
102726
104265
|
// Upload ZIP to Google Drive
|
|
102727
104266
|
const zipFilename = `landing_${Date.now()}.zip`;
|
|
@@ -102792,15 +104331,15 @@ function App() {
|
|
|
102792
104331
|
throw new Error(errorMsg);
|
|
102793
104332
|
}
|
|
102794
104333
|
addLog(formatLogMessage('log', '✅ Folder ID extracted:', folderId));
|
|
102795
|
-
// Check for product
|
|
102796
|
-
addLog(formatLogMessage('log', '🔍 Checking for product
|
|
104334
|
+
// Check for product image (png/jpg/webp)
|
|
104335
|
+
addLog(formatLogMessage('log', '🔍 Checking for product image...'));
|
|
102797
104336
|
const productImage = await fetchProductImage(folderId);
|
|
102798
104337
|
if (!productImage) {
|
|
102799
|
-
const errorMsg = 'product.png/jpg not found in the folder. Please generate it first using "Generate Product from Banka" button.';
|
|
104338
|
+
const errorMsg = 'product.png/jpg/webp not found in the folder. Please generate it first using "Generate Product from Banka" button.';
|
|
102800
104339
|
addLog(formatLogMessage('error', errorMsg));
|
|
102801
104340
|
throw new Error(errorMsg);
|
|
102802
104341
|
}
|
|
102803
|
-
addLog(formatLogMessage('log', '✅
|
|
104342
|
+
addLog(formatLogMessage('log', '✅ Product image found'));
|
|
102804
104343
|
// Generate images with different approaches (количество по каждому подходу)
|
|
102805
104344
|
const approaches = (0,_prompts__WEBPACK_IMPORTED_MODULE_1__.getCreoApproaches)();
|
|
102806
104345
|
if (approaches.length === 0) {
|
|
@@ -102828,7 +104367,7 @@ function App() {
|
|
|
102828
104367
|
const [b1, b2, b3] = (0,_prompts__WEBPACK_IMPORTED_MODULE_1__.pickRandomBullets)(t.approach.name);
|
|
102829
104368
|
return `ОБЯЗАТЕЛЬНЫЕ БУЛЛЕТЫ (используй именно эти 3, в указанном порядке; переведи на язык ${generateGeo}): 1) ${b1} 2) ${b2} 3) ${b3}`;
|
|
102830
104369
|
})();
|
|
102831
|
-
return `🏷️ ПРОДУКТ: ${generateProduct}${additionalInfoLine}\n\n${basePromptStructure}🏷️ ПРОДУКТ (повторение для ясности): ${generateProduct}${additionalInfoLine}\n🎯 ПОДХОД: ${t.approach.name}\n\n${t.approach.prompt}\n\n${t.approach.headlineAngle}\n\n${bulletsLine}\n\nТекст — строго следуй правилам этого подхода (
|
|
104370
|
+
return `🏷️ ПРОДУКТ: ${generateProduct}${additionalInfoLine}\n\n${basePromptStructure}🏷️ ПРОДУКТ (повторение для ясности): ${generateProduct}${additionalInfoLine}\n🎯 ПОДХОД: ${t.approach.name}\n\n${t.approach.prompt}\n\n${t.approach.headlineAngle}\n\n${bulletsLine}\n\nТекст — строго следуй правилам этого подхода (верхний заголовок обязателен; на макете не пиши слова HOOK/CTA/CAPS; буллиты добавляй только если они разрешены для подхода).`;
|
|
102832
104371
|
});
|
|
102833
104372
|
// Initialize placeholders for all images
|
|
102834
104373
|
const initialPlaceholders = tasks.map((t, index) => ({
|
|
@@ -103112,8 +104651,7 @@ function App() {
|
|
|
103112
104651
|
...img,
|
|
103113
104652
|
regenerating: true,
|
|
103114
104653
|
regenerateStartTime: Date.now(),
|
|
103115
|
-
checkStatus: 'pending'
|
|
103116
|
-
imageUrl: undefined // Clear old image URL to force re-render with new one
|
|
104654
|
+
checkStatus: 'pending'
|
|
103117
104655
|
}
|
|
103118
104656
|
: img));
|
|
103119
104657
|
addLog(formatLogMessage('log', `🔄 Переделка изображения ${imageData.index} (${imageData.approach})...`));
|
|
@@ -103339,8 +104877,7 @@ ${imageData.originalPrompt}
|
|
|
103339
104877
|
checkResult: undefined,
|
|
103340
104878
|
checkErrors: undefined,
|
|
103341
104879
|
// Explicitly ignore any previous comments
|
|
103342
|
-
customRegeneratePrompt: ''
|
|
103343
|
-
imageUrl: undefined // Clear old image URL to force re-render with new one
|
|
104880
|
+
customRegeneratePrompt: ''
|
|
103344
104881
|
}
|
|
103345
104882
|
: img));
|
|
103346
104883
|
addLog(formatLogMessage('log', `🔁 Переделка заново (с нуля) изображения ${imageData.index} (${imageData.approach})...`));
|
|
@@ -103606,8 +105143,12 @@ ${imageData.originalPrompt}
|
|
|
103606
105143
|
try {
|
|
103607
105144
|
const parsed = new URL(toParse);
|
|
103608
105145
|
let path = parsed.pathname || '/';
|
|
103609
|
-
|
|
103610
|
-
|
|
105146
|
+
// Корень сайта — оставляем как `/`. Если есть «тело» пути (не один домен), завершающий `/` убираем, не добавляем.
|
|
105147
|
+
if (path !== '/' && path.length > 1) {
|
|
105148
|
+
while (path.length > 1 && path.endsWith('/')) {
|
|
105149
|
+
path = path.slice(0, -1);
|
|
105150
|
+
}
|
|
105151
|
+
}
|
|
103611
105152
|
const result = `https://${parsed.host}${path}${parsed.search}${parsed.hash}`;
|
|
103612
105153
|
setLink(result);
|
|
103613
105154
|
setLinkError('');
|
|
@@ -103657,10 +105198,10 @@ ${imageData.originalPrompt}
|
|
|
103657
105198
|
throw new Error(err.error?.message || 'Failed to fetch Drive files');
|
|
103658
105199
|
}
|
|
103659
105200
|
const data = await response.json();
|
|
103660
|
-
// Filter out product.png/jpg (used for product reference, not creative images)
|
|
105201
|
+
// Filter out product.png/jpg/webp (used for product reference, not creative images)
|
|
103661
105202
|
const filteredFiles = data.files.filter((f) => {
|
|
103662
105203
|
const name = f.name?.toLowerCase() || '';
|
|
103663
|
-
return name !== 'product.png' && name !== 'product.jpg';
|
|
105204
|
+
return name !== 'product.png' && name !== 'product.jpg' && name !== 'product.webp';
|
|
103664
105205
|
});
|
|
103665
105206
|
return filteredFiles.map((f) => f.id ? `https://drive.google.com/file/d/${f.id}/view?usp=sharing` : '');
|
|
103666
105207
|
};
|
|
@@ -103668,7 +105209,7 @@ ${imageData.originalPrompt}
|
|
|
103668
105209
|
const validToken = await getValidAccessToken();
|
|
103669
105210
|
if (!validToken)
|
|
103670
105211
|
throw new Error('Not logged in');
|
|
103671
|
-
const q = `'${folderId}' in parents and trashed = false and (name = 'product.png' or name = 'product.jpg')`;
|
|
105212
|
+
const q = `'${folderId}' in parents and trashed = false and (name = 'product.png' or name = 'product.jpg' or name = 'product.webp')`;
|
|
103672
105213
|
const fields = 'files(id, name)';
|
|
103673
105214
|
const url = `https://www.googleapis.com/drive/v3/files?q=${encodeURIComponent(q)}&fields=${encodeURIComponent(fields)}`;
|
|
103674
105215
|
const response = await fetch(url, {
|
|
@@ -103682,9 +105223,10 @@ ${imageData.originalPrompt}
|
|
|
103682
105223
|
}
|
|
103683
105224
|
const data = await response.json();
|
|
103684
105225
|
if (data.files && data.files.length > 0) {
|
|
103685
|
-
// Prefer product.png
|
|
105226
|
+
// Prefer product.png > product.webp > product.jpg if multiple exist
|
|
103686
105227
|
const pngFile = data.files.find((f) => f.name?.toLowerCase() === 'product.png');
|
|
103687
|
-
const
|
|
105228
|
+
const webpFile = data.files.find((f) => f.name?.toLowerCase() === 'product.webp');
|
|
105229
|
+
const file = pngFile || webpFile || data.files[0];
|
|
103688
105230
|
return {
|
|
103689
105231
|
id: file.id,
|
|
103690
105232
|
name: file.name,
|
|
@@ -103693,104 +105235,61 @@ ${imageData.originalPrompt}
|
|
|
103693
105235
|
}
|
|
103694
105236
|
return null;
|
|
103695
105237
|
};
|
|
103696
|
-
|
|
103697
|
-
|
|
103698
|
-
|
|
103699
|
-
|
|
103700
|
-
|
|
103701
|
-
const existingPromise = envFolderCreationPromises.get(parentFolderId);
|
|
103702
|
-
if (existingPromise) {
|
|
103703
|
-
logToTerminal('log', '[Env Folder] Waiting for ongoing creation for parent folder:', parentFolderId);
|
|
103704
|
-
return existingPromise;
|
|
103705
|
-
}
|
|
103706
|
-
// Create a new promise for this folder creation
|
|
103707
|
-
const creationPromise = (async () => {
|
|
103708
|
-
try {
|
|
103709
|
-
return await getOrCreateEnvFolderImpl(parentFolderId);
|
|
103710
|
-
}
|
|
103711
|
-
finally {
|
|
103712
|
-
// Remove from map when done (success or failure)
|
|
103713
|
-
envFolderCreationPromises.delete(parentFolderId);
|
|
103714
|
-
}
|
|
103715
|
-
})();
|
|
103716
|
-
envFolderCreationPromises.set(parentFolderId, creationPromise);
|
|
103717
|
-
return creationPromise;
|
|
103718
|
-
};
|
|
103719
|
-
// Implementation of getOrCreateEnvFolder
|
|
103720
|
-
const getOrCreateEnvFolderImpl = async (parentFolderId) => {
|
|
105238
|
+
const PROJECT_SETTINGS_FILENAME = 'project-settings.json';
|
|
105239
|
+
/** Старое имя файла — всё ещё ищем при загрузке; при сохранении переименуем в project-settings.json. */
|
|
105240
|
+
const LEGACY_PROJECT_SETTINGS_FILENAME = 'temp-generated-content.json';
|
|
105241
|
+
/** Папки `env` внутри проекта (только поиск, без создания) — для обратной совместимости и удаления после миграции. */
|
|
105242
|
+
const findEnvFolderIds = async (parentFolderId) => {
|
|
103721
105243
|
const validToken = await getValidAccessToken();
|
|
103722
|
-
if (!validToken)
|
|
103723
|
-
|
|
103724
|
-
}
|
|
103725
|
-
// Check if 'env' folder exists
|
|
105244
|
+
if (!validToken)
|
|
105245
|
+
return [];
|
|
103726
105246
|
const q = `'${parentFolderId}' in parents and trashed = false and name = 'env' and mimeType = 'application/vnd.google-apps.folder'`;
|
|
103727
105247
|
const fields = 'files(id, name)';
|
|
103728
105248
|
const searchUrl = `https://www.googleapis.com/drive/v3/files?q=${encodeURIComponent(q)}&fields=${encodeURIComponent(fields)}`;
|
|
103729
105249
|
const searchResponse = await fetch(searchUrl, {
|
|
103730
|
-
headers: {
|
|
103731
|
-
'Authorization': `Bearer ${validToken}`
|
|
103732
|
-
}
|
|
105250
|
+
headers: { 'Authorization': `Bearer ${validToken}` }
|
|
103733
105251
|
});
|
|
103734
|
-
if (searchResponse.ok)
|
|
105252
|
+
if (!searchResponse.ok)
|
|
105253
|
+
return [];
|
|
105254
|
+
const searchData = await searchResponse.json();
|
|
105255
|
+
return (searchData.files || []).map((f) => f.id).filter(Boolean);
|
|
105256
|
+
};
|
|
105257
|
+
/** Ищет JSON настроек в папке: сначала project-settings.json, иначе legacy temp-generated-content.json. */
|
|
105258
|
+
const findSettingsFileInFolder = async (parentFolderId) => {
|
|
105259
|
+
const validToken = await getValidAccessToken();
|
|
105260
|
+
if (!validToken)
|
|
105261
|
+
return null;
|
|
105262
|
+
const fields = 'files(id, name)';
|
|
105263
|
+
for (const fileName of [PROJECT_SETTINGS_FILENAME, LEGACY_PROJECT_SETTINGS_FILENAME]) {
|
|
105264
|
+
const q = `'${parentFolderId}' in parents and trashed = false and name = '${fileName}' and mimeType != 'application/vnd.google-apps.folder'`;
|
|
105265
|
+
const searchUrl = `https://www.googleapis.com/drive/v3/files?q=${encodeURIComponent(q)}&fields=${encodeURIComponent(fields)}`;
|
|
105266
|
+
const searchResponse = await fetch(searchUrl, {
|
|
105267
|
+
headers: { 'Authorization': `Bearer ${validToken}` }
|
|
105268
|
+
});
|
|
105269
|
+
if (!searchResponse.ok)
|
|
105270
|
+
continue;
|
|
103735
105271
|
const searchData = await searchResponse.json();
|
|
103736
105272
|
if (searchData.files && searchData.files.length > 0) {
|
|
103737
|
-
// If multiple folders found, use the first one (shouldn't happen, but handle it)
|
|
103738
|
-
const envFolderId = searchData.files[0].id;
|
|
103739
|
-
logToTerminal('log', '[Env Folder] Found existing env folder, id:', envFolderId);
|
|
103740
105273
|
if (searchData.files.length > 1) {
|
|
103741
|
-
logToTerminal('warn', '[
|
|
105274
|
+
logToTerminal('warn', '[Drive Settings] Multiple JSON with same name, using first:', fileName);
|
|
103742
105275
|
}
|
|
103743
|
-
return
|
|
105276
|
+
return searchData.files[0].id;
|
|
103744
105277
|
}
|
|
103745
105278
|
}
|
|
103746
|
-
|
|
103747
|
-
|
|
103748
|
-
|
|
103749
|
-
|
|
103750
|
-
|
|
103751
|
-
|
|
103752
|
-
|
|
103753
|
-
|
|
103754
|
-
|
|
103755
|
-
mimeType: 'application/vnd.google-apps.folder',
|
|
103756
|
-
parents: [parentFolderId]
|
|
103757
|
-
};
|
|
103758
|
-
const createResponse = await fetch('https://www.googleapis.com/drive/v3/files', {
|
|
103759
|
-
method: 'POST',
|
|
103760
|
-
headers: {
|
|
103761
|
-
'Authorization': `Bearer ${validToken}`,
|
|
103762
|
-
'Content-Type': 'application/json'
|
|
103763
|
-
},
|
|
103764
|
-
body: JSON.stringify(createMetadata)
|
|
105279
|
+
return null;
|
|
105280
|
+
};
|
|
105281
|
+
const trashDriveFile = async (fileId) => {
|
|
105282
|
+
const validToken = await getValidAccessToken();
|
|
105283
|
+
if (!validToken)
|
|
105284
|
+
return;
|
|
105285
|
+
const res = await fetch(`https://www.googleapis.com/drive/v3/files/${fileId}`, {
|
|
105286
|
+
method: 'DELETE',
|
|
105287
|
+
headers: { 'Authorization': `Bearer ${validToken}` }
|
|
103765
105288
|
});
|
|
103766
|
-
if (!
|
|
103767
|
-
const
|
|
103768
|
-
|
|
103769
|
-
// If folder already exists (race condition), try to find it again
|
|
103770
|
-
if (errorMessage.includes('already exists') || errorMessage.includes('duplicate') || createResponse.status === 409) {
|
|
103771
|
-
logToTerminal('log', '[Env Folder] Folder creation failed (likely already exists), searching again...');
|
|
103772
|
-
// Retry search after a short delay to allow for eventual consistency
|
|
103773
|
-
await new Promise(resolve => setTimeout(resolve, 500));
|
|
103774
|
-
const retrySearchResponse = await fetch(searchUrl, {
|
|
103775
|
-
headers: {
|
|
103776
|
-
'Authorization': `Bearer ${validToken}`
|
|
103777
|
-
}
|
|
103778
|
-
});
|
|
103779
|
-
if (retrySearchResponse.ok) {
|
|
103780
|
-
const retrySearchData = await retrySearchResponse.json();
|
|
103781
|
-
if (retrySearchData.files && retrySearchData.files.length > 0) {
|
|
103782
|
-
const envFolderId = retrySearchData.files[0].id;
|
|
103783
|
-
logToTerminal('log', '[Env Folder] Found existing env folder after retry, id:', envFolderId);
|
|
103784
|
-
return envFolderId;
|
|
103785
|
-
}
|
|
103786
|
-
}
|
|
103787
|
-
}
|
|
103788
|
-
logToTerminal('error', '[Env Folder] Failed to create env folder:', JSON.stringify(err));
|
|
103789
|
-
throw new Error(errorMessage || 'Failed to create env folder in Google Drive');
|
|
105289
|
+
if (!res.ok) {
|
|
105290
|
+
const t = await res.text();
|
|
105291
|
+
logToTerminal('warn', '[Drive Settings] Failed to trash/delete file:', fileId, res.status, t);
|
|
103790
105292
|
}
|
|
103791
|
-
const result = await createResponse.json();
|
|
103792
|
-
logToTerminal('log', '[Env Folder] Successfully created env folder, id:', result.id);
|
|
103793
|
-
return result.id;
|
|
103794
105293
|
};
|
|
103795
105294
|
const sanitizeGeneratedTitlesData = (titlesData) => {
|
|
103796
105295
|
if (!Array.isArray(titlesData))
|
|
@@ -103828,8 +105327,6 @@ ${imageData.originalPrompt}
|
|
|
103828
105327
|
logToTerminal('error', '[Save Content] No valid token');
|
|
103829
105328
|
throw new Error('Not logged in to Google Drive');
|
|
103830
105329
|
}
|
|
103831
|
-
// Get or create 'env' folder
|
|
103832
|
-
const envFolderId = await getOrCreateEnvFolder(folderId);
|
|
103833
105330
|
const dataToSave = {
|
|
103834
105331
|
aiGenerationSettings: aiSettings || {
|
|
103835
105332
|
generateProduct: generateProduct || '',
|
|
@@ -103839,35 +105336,20 @@ ${imageData.originalPrompt}
|
|
|
103839
105336
|
},
|
|
103840
105337
|
brand: brandValue !== undefined ? brandValue : brand || '',
|
|
103841
105338
|
link: linkValue !== undefined ? linkValue : link || '',
|
|
105339
|
+
selectedPairApproaches: (0,_promptOverrides__WEBPACK_IMPORTED_MODULE_52__.getSelectedPairApproaches)(),
|
|
105340
|
+
imageApproachCounts: (0,_promptOverrides__WEBPACK_IMPORTED_MODULE_52__.getImageApproachCounts)(),
|
|
103842
105341
|
savedAt: new Date().toISOString()
|
|
103843
105342
|
};
|
|
103844
105343
|
const jsonContent = JSON.stringify(dataToSave, null, 2);
|
|
103845
|
-
const filename =
|
|
103846
|
-
logToTerminal('log', '[Save Content] Filename:', filename, 'content length:', jsonContent.length);
|
|
103847
|
-
//
|
|
103848
|
-
|
|
103849
|
-
|
|
103850
|
-
|
|
103851
|
-
const searchResponse = await fetch(searchUrl, {
|
|
103852
|
-
headers: {
|
|
103853
|
-
'Authorization': `Bearer ${validToken}`
|
|
103854
|
-
}
|
|
103855
|
-
});
|
|
103856
|
-
let fileId = null;
|
|
103857
|
-
if (searchResponse.ok) {
|
|
103858
|
-
const searchData = await searchResponse.json();
|
|
103859
|
-
logToTerminal('log', '[Save Content] Search response, files found:', searchData.files?.length || 0);
|
|
103860
|
-
if (searchData.files && searchData.files.length > 0) {
|
|
103861
|
-
fileId = searchData.files[0].id;
|
|
103862
|
-
logToTerminal('log', '[Save Content] File exists, will update, fileId:', fileId);
|
|
103863
|
-
}
|
|
103864
|
-
else {
|
|
103865
|
-
logToTerminal('log', '[Save Content] File does not exist, will create new');
|
|
103866
|
-
}
|
|
105344
|
+
const filename = PROJECT_SETTINGS_FILENAME;
|
|
105345
|
+
logToTerminal('log', '[Save Content] Filename (project root):', filename, 'content length:', jsonContent.length);
|
|
105346
|
+
// Файл в корне папки проекта (не в env)
|
|
105347
|
+
let fileId = await findSettingsFileInFolder(folderId);
|
|
105348
|
+
if (fileId) {
|
|
105349
|
+
logToTerminal('log', '[Save Content] File exists in folder root, will update, fileId:', fileId);
|
|
103867
105350
|
}
|
|
103868
105351
|
else {
|
|
103869
|
-
|
|
103870
|
-
logToTerminal('warn', '[Save Content] Search failed, status:', searchResponse.status);
|
|
105352
|
+
logToTerminal('log', '[Save Content] No file in root yet, will create new at project root');
|
|
103871
105353
|
}
|
|
103872
105354
|
if (fileId) {
|
|
103873
105355
|
// Update existing file - don't include parents in metadata for updates
|
|
@@ -103895,12 +105377,11 @@ ${imageData.originalPrompt}
|
|
|
103895
105377
|
logToTerminal('log', '[Save Content] Successfully updated file');
|
|
103896
105378
|
}
|
|
103897
105379
|
else {
|
|
103898
|
-
|
|
103899
|
-
logToTerminal('log', '[Save Content] Creating new file in env folder');
|
|
105380
|
+
logToTerminal('log', '[Save Content] Creating new file in project folder root');
|
|
103900
105381
|
const createMetadata = {
|
|
103901
105382
|
name: filename,
|
|
103902
105383
|
mimeType: 'application/json',
|
|
103903
|
-
parents: [
|
|
105384
|
+
parents: [folderId]
|
|
103904
105385
|
};
|
|
103905
105386
|
const createForm = new FormData();
|
|
103906
105387
|
createForm.append('metadata', new Blob([JSON.stringify(createMetadata)], { type: 'application/json' }));
|
|
@@ -103921,6 +105402,12 @@ ${imageData.originalPrompt}
|
|
|
103921
105402
|
const result = await createResponse.json();
|
|
103922
105403
|
logToTerminal('log', '[Save Content] Successfully created file, id:', result.id);
|
|
103923
105404
|
}
|
|
105405
|
+
// После успешного сохранения в корень — убираем устаревшую папку env (и дубликаты, если были)
|
|
105406
|
+
const envIds = await findEnvFolderIds(folderId);
|
|
105407
|
+
for (const envId of envIds) {
|
|
105408
|
+
logToTerminal('log', '[Save Content] Removing legacy env folder:', envId);
|
|
105409
|
+
await trashDriveFile(envId);
|
|
105410
|
+
}
|
|
103924
105411
|
};
|
|
103925
105412
|
// Load generated content from Google Drive
|
|
103926
105413
|
const loadGeneratedContentFromDrive = async (folderId) => {
|
|
@@ -103931,40 +105418,28 @@ ${imageData.originalPrompt}
|
|
|
103931
105418
|
setDriveFilesFound(prev => ({ ...prev, content: false }));
|
|
103932
105419
|
return { found: false };
|
|
103933
105420
|
}
|
|
103934
|
-
//
|
|
103935
|
-
let
|
|
103936
|
-
|
|
103937
|
-
|
|
103938
|
-
}
|
|
103939
|
-
catch (err) {
|
|
103940
|
-
logToTerminal('warn', '[Load Content] Failed to get env folder:', err.message || 'Unknown error');
|
|
103941
|
-
return { found: false };
|
|
105421
|
+
// 1) Корень папки проекта; 2) иначе legacy: папка env (без создания env)
|
|
105422
|
+
let fileId = await findSettingsFileInFolder(folderId);
|
|
105423
|
+
if (fileId) {
|
|
105424
|
+
logToTerminal('log', '[Load Content] Found settings in project root');
|
|
103942
105425
|
}
|
|
103943
|
-
|
|
103944
|
-
|
|
103945
|
-
|
|
103946
|
-
|
|
103947
|
-
|
|
103948
|
-
|
|
103949
|
-
|
|
103950
|
-
|
|
105426
|
+
else {
|
|
105427
|
+
const envIds = await findEnvFolderIds(folderId);
|
|
105428
|
+
for (const envFolderId of envIds) {
|
|
105429
|
+
const id = await findSettingsFileInFolder(envFolderId);
|
|
105430
|
+
if (id) {
|
|
105431
|
+
fileId = id;
|
|
105432
|
+
logToTerminal('log', '[Load Content] Found settings in legacy env folder:', envFolderId);
|
|
105433
|
+
break;
|
|
105434
|
+
}
|
|
103951
105435
|
}
|
|
103952
|
-
});
|
|
103953
|
-
if (!response.ok) {
|
|
103954
|
-
const errorText = await response.text();
|
|
103955
|
-
logToTerminal('warn', '[Load Content] Search failed, status:', response.status, 'error:', errorText);
|
|
103956
|
-
setDriveFilesFound(prev => ({ ...prev, content: false }));
|
|
103957
|
-
return { found: false };
|
|
103958
105436
|
}
|
|
103959
|
-
|
|
103960
|
-
|
|
103961
|
-
if (!data.files || data.files.length === 0) {
|
|
103962
|
-
logToTerminal('log', '[Load Content] File not found - no temp-generated-content.json in folder');
|
|
105437
|
+
if (!fileId) {
|
|
105438
|
+
logToTerminal('log', `[Load Content] No settings file (${PROJECT_SETTINGS_FILENAME} or ${LEGACY_PROJECT_SETTINGS_FILENAME}) in root or env`);
|
|
103963
105439
|
setDriveFilesFound(prev => ({ ...prev, content: false }));
|
|
103964
105440
|
return { found: false };
|
|
103965
105441
|
}
|
|
103966
105442
|
setDriveFilesFound(prev => ({ ...prev, content: true }));
|
|
103967
|
-
const fileId = data.files[0].id;
|
|
103968
105443
|
logToTerminal('log', '[Load Content] File found, id:', fileId);
|
|
103969
105444
|
// Download file content
|
|
103970
105445
|
const downloadUrl = `https://www.googleapis.com/drive/v3/files/${fileId}?alt=media`;
|
|
@@ -104011,6 +105486,10 @@ ${imageData.originalPrompt}
|
|
|
104011
105486
|
setLink(loadedData.link || '');
|
|
104012
105487
|
logToTerminal('log', '[Load Content] Loaded link:', loadedData.link || '(empty)');
|
|
104013
105488
|
}
|
|
105489
|
+
const mergedApproaches = (0,_promptOverrides__WEBPACK_IMPORTED_MODULE_52__.mergePromptApproachesFromDriveFile)(loadedData);
|
|
105490
|
+
if (mergedApproaches) {
|
|
105491
|
+
logToTerminal('log', '[Load Content] Applied text + image approach settings from Drive JSON');
|
|
105492
|
+
}
|
|
104014
105493
|
logToTerminal('log', '[Load Content] Successfully loaded content');
|
|
104015
105494
|
setDriveFilesFound(prev => ({ ...prev, content: false }));
|
|
104016
105495
|
return { found: true };
|
|
@@ -104021,6 +105500,27 @@ ${imageData.originalPrompt}
|
|
|
104021
105500
|
return { found: false };
|
|
104022
105501
|
}
|
|
104023
105502
|
};
|
|
105503
|
+
syncDriveAfterPromptSaveRef.current = () => {
|
|
105504
|
+
if (!driveFolderUrl || loadingContentFromDrive)
|
|
105505
|
+
return;
|
|
105506
|
+
const folderId = extractFolderId(driveFolderUrl);
|
|
105507
|
+
if (!folderId)
|
|
105508
|
+
return;
|
|
105509
|
+
logToTerminal('log', '[Drive Sync] Prompt overrides saved locally — updating JSON on Drive');
|
|
105510
|
+
void saveGeneratedContentToDrive(folderId, {
|
|
105511
|
+
generateProduct,
|
|
105512
|
+
generateGeo,
|
|
105513
|
+
generateAdditionalInfo,
|
|
105514
|
+
generatePriceWithCurrency
|
|
105515
|
+
}, brand, link).catch((err) => {
|
|
105516
|
+
logToTerminal('warn', '[Drive Sync] Failed to update Drive after prompt save:', err?.message || err);
|
|
105517
|
+
});
|
|
105518
|
+
};
|
|
105519
|
+
(0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
|
|
105520
|
+
const listener = () => syncDriveAfterPromptSaveRef.current();
|
|
105521
|
+
window.addEventListener(_promptOverrides__WEBPACK_IMPORTED_MODULE_52__.PROMPT_OVERRIDES_SAVED_EVENT, listener);
|
|
105522
|
+
return () => window.removeEventListener(_promptOverrides__WEBPACK_IMPORTED_MODULE_52__.PROMPT_OVERRIDES_SAVED_EVENT, listener);
|
|
105523
|
+
}, []);
|
|
104024
105524
|
const handleGenerate = async () => {
|
|
104025
105525
|
if (!driveFolderUrl || !brand || !link) {
|
|
104026
105526
|
alert('Please fill all required fields');
|
|
@@ -104076,6 +105576,7 @@ ${imageData.originalPrompt}
|
|
|
104076
105576
|
const text = textList[i];
|
|
104077
105577
|
for (const image of images) {
|
|
104078
105578
|
const id = `${brand}${idCounter++}`;
|
|
105579
|
+
const rowLink = appendCreativeIdToCatalogLink(link, id);
|
|
104079
105580
|
rows.push([
|
|
104080
105581
|
id,
|
|
104081
105582
|
title,
|
|
@@ -104083,7 +105584,7 @@ ${imageData.originalPrompt}
|
|
|
104083
105584
|
'in stock',
|
|
104084
105585
|
'new',
|
|
104085
105586
|
'10,00 USD',
|
|
104086
|
-
|
|
105587
|
+
rowLink,
|
|
104087
105588
|
image,
|
|
104088
105589
|
brand
|
|
104089
105590
|
]);
|
|
@@ -104091,8 +105592,8 @@ ${imageData.originalPrompt}
|
|
|
104091
105592
|
}
|
|
104092
105593
|
setGeneratedData(rows);
|
|
104093
105594
|
// Create workbook
|
|
104094
|
-
const wb =
|
|
104095
|
-
const ws =
|
|
105595
|
+
const wb = xlsx__WEBPACK_IMPORTED_MODULE_53__.utils.book_new();
|
|
105596
|
+
const ws = xlsx__WEBPACK_IMPORTED_MODULE_53__.utils.aoa_to_sheet(rows);
|
|
104096
105597
|
// Set column widths (approximate pixel width / 7)
|
|
104097
105598
|
ws['!cols'] = [
|
|
104098
105599
|
{ wch: 20 }, // id
|
|
@@ -104105,9 +105606,9 @@ ${imageData.originalPrompt}
|
|
|
104105
105606
|
{ wch: 40 }, // image_link
|
|
104106
105607
|
{ wch: 20 } // brand
|
|
104107
105608
|
];
|
|
104108
|
-
|
|
105609
|
+
xlsx__WEBPACK_IMPORTED_MODULE_53__.utils.book_append_sheet(wb, ws, "Products");
|
|
104109
105610
|
// Generate buffer
|
|
104110
|
-
const wbout =
|
|
105611
|
+
const wbout = xlsx__WEBPACK_IMPORTED_MODULE_53__.write(wb, { bookType: 'xlsx', type: 'array' });
|
|
104111
105612
|
// Upload to Drive (имя файла по бренду)
|
|
104112
105613
|
const dateStr = new Date().toISOString().split('T')[0];
|
|
104113
105614
|
const fileName = `${brand}-${dateStr}.xlsx`;
|
|
@@ -104229,13 +105730,13 @@ ${imageData.originalPrompt}
|
|
|
104229
105730
|
setTestLoading(true);
|
|
104230
105731
|
try {
|
|
104231
105732
|
// Create simple test workbook with structure
|
|
104232
|
-
const wb =
|
|
105733
|
+
const wb = xlsx__WEBPACK_IMPORTED_MODULE_53__.utils.book_new();
|
|
104233
105734
|
const rows = [
|
|
104234
105735
|
INSTRUCTION_ROW,
|
|
104235
105736
|
['id', 'title', 'description', 'availability', 'condition', 'price', 'link', 'image_link', 'brand'],
|
|
104236
105737
|
['test1', 'Test Title', 'Test Description', 'in stock', 'new', '10.00 USD', 'http://test.com', 'http://test.com/img.jpg', 'TestBrand']
|
|
104237
105738
|
];
|
|
104238
|
-
const ws =
|
|
105739
|
+
const ws = xlsx__WEBPACK_IMPORTED_MODULE_53__.utils.aoa_to_sheet(rows);
|
|
104239
105740
|
// Set column widths
|
|
104240
105741
|
ws['!cols'] = [
|
|
104241
105742
|
{ wch: 20 }, // id
|
|
@@ -104248,8 +105749,8 @@ ${imageData.originalPrompt}
|
|
|
104248
105749
|
{ wch: 40 }, // image_link
|
|
104249
105750
|
{ wch: 20 } // brand
|
|
104250
105751
|
];
|
|
104251
|
-
|
|
104252
|
-
const wbout =
|
|
105752
|
+
xlsx__WEBPACK_IMPORTED_MODULE_53__.utils.book_append_sheet(wb, ws, "Test");
|
|
105753
|
+
const wbout = xlsx__WEBPACK_IMPORTED_MODULE_53__.write(wb, { bookType: 'xlsx', type: 'array' });
|
|
104253
105754
|
// Try to extract folder ID if available, otherwise upload to root
|
|
104254
105755
|
const folderId = driveFolderUrl ? extractFolderId(driveFolderUrl) : undefined;
|
|
104255
105756
|
const result = await uploadFileToDrive(wbout, 'test_table.xlsx', folderId || undefined);
|
|
@@ -104281,9 +105782,27 @@ ${imageData.originalPrompt}
|
|
|
104281
105782
|
alert('Failed to copy link');
|
|
104282
105783
|
}
|
|
104283
105784
|
};
|
|
105785
|
+
const copyGeneratedPairsAsJson = async () => {
|
|
105786
|
+
const n = Math.max(generatedTitlesData.length, generatedTextsData.length);
|
|
105787
|
+
if (n === 0)
|
|
105788
|
+
return;
|
|
105789
|
+
const pairs = Array.from({ length: n }, (_, i) => ({
|
|
105790
|
+
title: generatedTitlesData[i]?.title ?? '',
|
|
105791
|
+
text: generatedTextsData[i]?.text ?? '',
|
|
105792
|
+
}));
|
|
105793
|
+
const json = JSON.stringify(pairs, null, 2);
|
|
105794
|
+
try {
|
|
105795
|
+
await navigator.clipboard.writeText(json);
|
|
105796
|
+
setPairsJsonCopied(true);
|
|
105797
|
+
setTimeout(() => setPairsJsonCopied(false), 2000);
|
|
105798
|
+
}
|
|
105799
|
+
catch {
|
|
105800
|
+
alert('Не удалось скопировать в буфер обмена');
|
|
105801
|
+
}
|
|
105802
|
+
};
|
|
104284
105803
|
// Show lock screen if not unlocked
|
|
104285
105804
|
if (!unlocked) {
|
|
104286
|
-
return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
105805
|
+
return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_33__["default"], { theme: theme },
|
|
104287
105806
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_4__["default"], null),
|
|
104288
105807
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { onClick: handleSecretClick, sx: {
|
|
104289
105808
|
width: '100vw',
|
|
@@ -104323,24 +105842,24 @@ ${imageData.originalPrompt}
|
|
|
104323
105842
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("br", null),
|
|
104324
105843
|
"Please contact system administrator"))));
|
|
104325
105844
|
}
|
|
104326
|
-
return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
105845
|
+
return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_33__["default"], { theme: theme },
|
|
104327
105846
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_4__["default"], null),
|
|
104328
105847
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_7__["default"], { maxWidth: "lg", sx: { py: 4 } },
|
|
104329
105848
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { sx: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 } },
|
|
104330
105849
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "h4", component: "h1", sx: { fontWeight: 'bold', color: 'primary.main' } }, "Docs Combiner"),
|
|
104331
105850
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], null,
|
|
104332
105851
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_8__["default"], { onClick: () => setPromptManagerOpen(true), color: "inherit", "aria-label": "manage prompts", sx: { mr: 1 } },
|
|
104333
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
104334
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_8__["default"], { onClick: toggleTheme, color: "inherit", "aria-label": "toggle theme" }, darkMode ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
105852
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_49__["default"], null)),
|
|
105853
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_8__["default"], { onClick: toggleTheme, color: "inherit", "aria-label": "toggle theme" }, darkMode ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_38__["default"], null) : react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_37__["default"], null)))),
|
|
104335
105854
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_9__["default"], { variant: "outlined", sx: { mb: 4 } },
|
|
104336
105855
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_10__["default"], null,
|
|
104337
105856
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_11__["default"], { spacing: 3 },
|
|
104338
105857
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], null,
|
|
104339
105858
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "h6", gutterBottom: true }, "Google Drive Authentication"),
|
|
104340
105859
|
accessToken ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_12__["default"], null,
|
|
104341
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_13__["default"], { expandIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
105860
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_13__["default"], { expandIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_43__["default"], null) },
|
|
104342
105861
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { sx: { display: 'flex', alignItems: 'center', color: 'success.main' } },
|
|
104343
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
105862
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_39__["default"], { sx: { mr: 1 } }),
|
|
104344
105863
|
" Logged In (Credentials Hidden)")),
|
|
104345
105864
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_14__["default"], null,
|
|
104346
105865
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_11__["default"], { spacing: 2 },
|
|
@@ -104351,7 +105870,7 @@ ${imageData.originalPrompt}
|
|
|
104351
105870
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_15__["default"], { label: "Client ID", variant: "outlined", fullWidth: true, value: clientId, onChange: (e) => handleClientIdChange(e.target.value), helperText: "From Google Cloud Console (OAuth 2.0 Client ID)" }),
|
|
104352
105871
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_15__["default"], { label: "Client Secret", variant: "outlined", fullWidth: true, value: clientSecret, onChange: (e) => handleClientSecretChange(e.target.value) }))),
|
|
104353
105872
|
openaiApiKey && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { sx: { display: 'flex', alignItems: 'center', gap: 2, mt: 2 } },
|
|
104354
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
105873
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_34__["default"], { color: openRouterAccountBalance !== null ? 'primary' : 'disabled' }),
|
|
104355
105874
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "body2", color: openRouterAccountBalance !== null ? 'text.primary' : 'text.secondary' },
|
|
104356
105875
|
"\u0411\u0430\u043B\u0430\u043D\u0441: ",
|
|
104357
105876
|
openRouterBalanceLoading ? 'Loading...' : (openRouterAccountBalance !== null ? `$${openRouterAccountBalance.toFixed(2)}` : 'N/A')),
|
|
@@ -104360,8 +105879,8 @@ ${imageData.originalPrompt}
|
|
|
104360
105879
|
"\u041B\u0438\u043C\u0438\u0442 \u043A\u043B\u044E\u0447\u0430: ",
|
|
104361
105880
|
openRouterBalanceLoading ? 'Loading...' : (openRouterBalance === -1 ? 'Без лимита' : (openRouterBalance !== null ? `${openRouterBalance.toFixed(4)}` : 'N/A'))))),
|
|
104362
105881
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_11__["default"], { direction: "row", spacing: 2, alignItems: "center", sx: { mt: 2 } },
|
|
104363
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { variant: "contained", color: accessToken ? "success" : "primary", onClick: handleLogin, disabled: authLoading || !clientId || !clientSecret, startIcon: authLoading ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_18__["default"], { size: 20, color: "inherit" }) : (accessToken ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
104364
|
-
accessToken && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { variant: "outlined", color: "error", onClick: handleLogout, startIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
105882
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { variant: "contained", color: accessToken ? "success" : "primary", onClick: handleLogin, disabled: authLoading || !clientId || !clientSecret, startIcon: authLoading ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_18__["default"], { size: 20, color: "inherit" }) : (accessToken ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_39__["default"], null) : react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_45__["default"], null)), sx: { flexGrow: 1 } }, authLoading ? 'Logging in...' : (accessToken ? 'Logged In' : 'Login with Google')),
|
|
105883
|
+
accessToken && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { variant: "outlined", color: "error", onClick: handleLogout, startIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_46__["default"], null) }, "Logout")))),
|
|
104365
105884
|
!accessToken && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null,
|
|
104366
105885
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_16__["default"], null),
|
|
104367
105886
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], null,
|
|
@@ -104377,7 +105896,7 @@ ${imageData.originalPrompt}
|
|
|
104377
105896
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_18__["default"], { size: 14 }),
|
|
104378
105897
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", null, "\u041F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u0444\u0430\u0439\u043B\u043E\u0432...")))),
|
|
104379
105898
|
!checkingFolderFiles && folderFilesInfo && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_19__["default"], null,
|
|
104380
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { component: "span", sx: { display: 'block' } }, folderFilesInfo.hasProduct ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { component: "span", sx: { color: 'success.main' } }, "\u2713 product.png/jpg \u043D\u0430\u0439\u0434\u0435\u043D")) : (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { component: "span", sx: { color: 'info.main' } }, "\u2139 product.png/jpg \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D \u2014 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u0435 \u0447\u0435\u0440\u0435\u0437 \u043A\u043D\u043E\u043F\u043A\u0443 \u043D\u0438\u0436\u0435"))))),
|
|
105899
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { component: "span", sx: { display: 'block' } }, folderFilesInfo.hasProduct ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { component: "span", sx: { color: 'success.main' } }, "\u2713 product.png/jpg/webp \u043D\u0430\u0439\u0434\u0435\u043D")) : (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { component: "span", sx: { color: 'info.main' } }, "\u2139 product.png/jpg/webp \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D \u2014 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u0435 \u0447\u0435\u0440\u0435\u0437 \u043A\u043D\u043E\u043F\u043A\u0443 \u043D\u0438\u0436\u0435"))))),
|
|
104381
105900
|
!checkingFolderFiles && !folderFilesInfo && driveFolderUrl.trim() && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_19__["default"], null, "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043A\u043E\u0440\u0440\u0435\u043A\u0442\u043D\u0443\u044E \u0441\u0441\u044B\u043B\u043A\u0443 \u043D\u0430 \u043F\u0430\u043F\u043A\u0443 Google Drive"))))),
|
|
104382
105901
|
!driveFolderUrl.trim() ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_20__["default"], { severity: "info", sx: { mt: 2 } },
|
|
104383
105902
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "body1", sx: { fontWeight: 'bold', mb: 1 } }, "\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u043F\u0430\u043F\u043A\u0443 Google Drive \u0434\u043B\u044F \u043F\u0440\u043E\u0434\u043E\u043B\u0436\u0435\u043D\u0438\u044F"),
|
|
@@ -104409,39 +105928,58 @@ ${imageData.originalPrompt}
|
|
|
104409
105928
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_15__["default"], { label: "\u0422\u043E\u0432\u0430\u0440", variant: "outlined", fullWidth: true, value: generateProduct, onChange: (e) => setGenerateProduct(e.target.value), placeholder: "\u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440: \u043A\u0430\u043F\u043B\u0438 \u043E\u0442 \u043F\u0430\u0440\u0430\u0437\u0438\u0442\u043E\u0432 Detoxil Water", sx: { mb: 2 } })),
|
|
104410
105929
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_11__["default"], { direction: "row", spacing: 2, sx: { mb: 2 } },
|
|
104411
105930
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_15__["default"], { label: "\u0413\u0435\u043E", variant: "outlined", fullWidth: true, value: generateGeo, onChange: (e) => setGenerateGeo(e.target.value), placeholder: "\u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440: \u0420\u0443\u043C\u044B\u043D\u0438\u044F" }),
|
|
104412
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_15__["default"], { label: "\u0426\u0435\u043D\u0430 \u0438 \u0432\u0430\u043B\u044E\u0442\u0430", variant: "outlined", fullWidth: true, value: generatePriceWithCurrency, onChange: (e) => setGeneratePriceWithCurrency(e.target.value), placeholder: "\u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440: 29 euro, 11400 HUF, 149 RON \u0438\u043B\u0438 \u043B\u044E\u0431\u043E\u0439 \u0434\u0440\u0443\u0433\u043E\u0439 \u0444\u043E\u0440\u043C\u0430\u0442", helperText: "\u041B\u044E\u0431\u043E\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0434\u043B\u044F \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u044F \u0432 \u043F\u0440\u043E\u043C\u043F\u0442\u0435 \u0433\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u0438 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0439
|
|
105931
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_15__["default"], { label: "\u0426\u0435\u043D\u0430 \u0438 \u0432\u0430\u043B\u044E\u0442\u0430", variant: "outlined", fullWidth: true, value: generatePriceWithCurrency, onChange: (e) => setGeneratePriceWithCurrency(e.target.value), placeholder: "\u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440: 29 euro, 11400 HUF, 149 RON \u0438\u043B\u0438 \u043B\u044E\u0431\u043E\u0439 \u0434\u0440\u0443\u0433\u043E\u0439 \u0444\u043E\u0440\u043C\u0430\u0442", helperText: "\u041B\u044E\u0431\u043E\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0434\u043B\u044F \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u044F \u0432 \u043F\u0440\u043E\u043C\u043F\u0442\u0435 \u0433\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u0438 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0439. \u041A\u043D\u043E\u043F\u043A\u0438 \u0441\u043F\u0440\u0430\u0432\u0430 \u043F\u043E\u0434\u0441\u0442\u0430\u0432\u043B\u044F\u044E\u0442 \u0441\u0438\u043C\u0432\u043E\u043B \u0432\u0430\u043B\u044E\u0442\u044B, \u0446\u0438\u0444\u0440\u0443 \u0431\u0435\u0440\u0443\u0442 \u0438\u0437 \u043F\u043E\u043B\u044F (\u0438\u043B\u0438 99).", InputProps: {
|
|
105932
|
+
endAdornment: (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_21__["default"], { position: "end" },
|
|
105933
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { sx: { display: 'flex', alignItems: 'center', gap: 0.25, mr: -0.5 } },
|
|
105934
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_22__["default"], { title: "\u041F\u043E\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044C $ (\u0446\u0438\u0444\u0440\u0430 \u0438\u0437 \u043F\u043E\u043B\u044F \u0438\u043B\u0438 99)" },
|
|
105935
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_8__["default"], { size: "small", "aria-label": "\u0411\u044B\u0441\u0442\u0440\u043E \u0434\u043E\u043B\u043B\u0430\u0440", onClick: () => {
|
|
105936
|
+
const n = extractLeadingPriceNumber(generatePriceWithCurrency);
|
|
105937
|
+
setGeneratePriceWithCurrency(`$${n}`);
|
|
105938
|
+
}, edge: "end" },
|
|
105939
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_35__["default"], { sx: { fontSize: 20 } }))),
|
|
105940
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_22__["default"], { title: "\u041F\u043E\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u20AC (\u0446\u0438\u0444\u0440\u0430 \u0438\u0437 \u043F\u043E\u043B\u044F \u0438\u043B\u0438 99)" },
|
|
105941
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_8__["default"], { size: "small", "aria-label": "\u0411\u044B\u0441\u0442\u0440\u043E \u0435\u0432\u0440\u043E", onClick: () => {
|
|
105942
|
+
const n = extractLeadingPriceNumber(generatePriceWithCurrency);
|
|
105943
|
+
setGeneratePriceWithCurrency(`€${n}`);
|
|
105944
|
+
}, edge: "end", sx: { minWidth: 34, fontSize: '1rem', fontWeight: 700 } }, "\u20AC")),
|
|
105945
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_22__["default"], { title: "\u041F\u043E\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044C z\u0142 (\u0446\u0438\u0444\u0440\u0430 \u0438\u0437 \u043F\u043E\u043B\u044F \u0438\u043B\u0438 99)" },
|
|
105946
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_8__["default"], { size: "small", "aria-label": "\u0411\u044B\u0441\u0442\u0440\u043E \u0437\u043B\u043E\u0442\u044B\u0435", onClick: () => {
|
|
105947
|
+
const n = extractLeadingPriceNumber(generatePriceWithCurrency);
|
|
105948
|
+
setGeneratePriceWithCurrency(`${n} zł`);
|
|
105949
|
+
}, edge: "end", sx: { minWidth: 36, fontSize: '0.8rem', fontWeight: 700, letterSpacing: -0.3 } }, "z\u0142"))))),
|
|
105950
|
+
} })),
|
|
104413
105951
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], null,
|
|
104414
105952
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_15__["default"], { label: "\u0414\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u0430\u044F \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044F (\u043D\u0435 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E)", variant: "outlined", fullWidth: true, multiline: true, minRows: 3, value: generateAdditionalInfo, onChange: (e) => setGenerateAdditionalInfo(e.target.value), placeholder: "\u0418\u043D\u0433\u0440\u0435\u0434\u0438\u0435\u043D\u0442\u044B, \u0443\u0442\u043E\u0447\u043D\u0435\u043D\u0438\u044F \u043A \u043F\u0440\u043E\u043C\u043F\u0442\u0443 \u0438 \u0442.\u0434.", sx: { mb: 2 } })),
|
|
104415
105953
|
openaiApiKey && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_11__["default"], { direction: "row", spacing: 2, sx: { mb: 2 } },
|
|
104416
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
104417
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
104418
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
105954
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_23__["default"], { fullWidth: true, variant: "outlined" },
|
|
105955
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_24__["default"], null, "\u041C\u043E\u0434\u0435\u043B\u044C \u0434\u043B\u044F \u0433\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u0438 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0439"),
|
|
105956
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_25__["default"], { value: selectedImageModel, onChange: (e) => handleImageModelChange(e.target.value), label: "\u041C\u043E\u0434\u0435\u043B\u044C \u0434\u043B\u044F \u0433\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u0438 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0439", disabled: loadingImageModels || imageModels.length === 0 }, loadingImageModels ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_26__["default"], { disabled: true },
|
|
104419
105957
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { sx: { display: 'flex', alignItems: 'center', gap: 1 } },
|
|
104420
105958
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_18__["default"], { size: 16 }),
|
|
104421
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", null, "\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430 \u043C\u043E\u0434\u0435\u043B\u0435\u0439...")))) : imageModels.length === 0 ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
105959
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", null, "\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430 \u043C\u043E\u0434\u0435\u043B\u0435\u0439...")))) : imageModels.length === 0 ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_26__["default"], { disabled: true }, "\u041D\u0435\u0442 \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u0445 \u043C\u043E\u0434\u0435\u043B\u0435\u0439")) : (imageModels.map((model) => (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_26__["default"], { key: model.id, value: model.id }, model.name))))),
|
|
104422
105960
|
!loadingImageModels && imageModels.length > 0 && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_19__["default"], null, selectedImageModel === _models__WEBPACK_IMPORTED_MODULE_2__.MODELS.imageGeneration
|
|
104423
105961
|
? 'Используется модель по умолчанию'
|
|
104424
105962
|
: 'Выбрана модель: ' + (imageModels.find(m => m.id === selectedImageModel)?.name || selectedImageModel)))),
|
|
104425
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
104426
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
104427
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
105963
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_23__["default"], { fullWidth: true, variant: "outlined" },
|
|
105964
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_24__["default"], null, "\u041C\u043E\u0434\u0435\u043B\u044C \u0434\u043B\u044F \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0438 \u043A\u0440\u0435\u0430\u0442\u0438\u0432\u043E\u0432"),
|
|
105965
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_25__["default"], { value: selectedValidationModel, onChange: (e) => handleValidationModelChange(e.target.value), label: "\u041C\u043E\u0434\u0435\u043B\u044C \u0434\u043B\u044F \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0438 \u043A\u0440\u0435\u0430\u0442\u0438\u0432\u043E\u0432", disabled: loadingValidationModels || validationModels.length === 0 }, loadingValidationModels ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_26__["default"], { disabled: true },
|
|
104428
105966
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { sx: { display: 'flex', alignItems: 'center', gap: 1 } },
|
|
104429
105967
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_18__["default"], { size: 16 }),
|
|
104430
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", null, "\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430 \u043C\u043E\u0434\u0435\u043B\u0435\u0439...")))) : validationModels.length === 0 ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
105968
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", null, "\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430 \u043C\u043E\u0434\u0435\u043B\u0435\u0439...")))) : validationModels.length === 0 ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_26__["default"], { disabled: true }, "\u041D\u0435\u0442 \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u0445 \u043C\u043E\u0434\u0435\u043B\u0435\u0439")) : (validationModels.map((model) => (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_26__["default"], { key: model.id, value: model.id }, model.name))))),
|
|
104431
105969
|
!loadingValidationModels && validationModels.length > 0 && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_19__["default"], null, selectedValidationModel === _models__WEBPACK_IMPORTED_MODULE_2__.MODELS.creativeValidation
|
|
104432
105970
|
? 'Используется модель по умолчанию'
|
|
104433
105971
|
: 'Выбрана модель: ' + (validationModels.find(m => m.id === selectedValidationModel)?.name || selectedValidationModel))),
|
|
104434
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
105972
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_27__["default"], { control: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_28__["default"], { checked: validationDisabled, onChange: (e) => handleValidationDisabledChange(e.target.checked), color: "primary" }), label: "\u041E\u0442\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0443", sx: { mt: 1 } })))),
|
|
104435
105973
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_11__["default"], { direction: "row", spacing: 2, sx: { mb: 2 } },
|
|
104436
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { variant: "contained", color: "primary", startIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
105974
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { variant: "contained", color: "primary", startIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_36__["default"], null), onClick: handleGenerateContent, disabled: generating || loadingContentFromDrive || !openaiApiKey || !generateProduct.trim() || !generateGeo.trim(), sx: { flexGrow: 1 }, size: "large" }, generating ? 'Generating...' : 'Generate Titles & Descriptions'),
|
|
104437
105975
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_11__["default"], { direction: "row", spacing: 1, alignItems: "center", sx: { flexGrow: 1 } },
|
|
104438
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
105976
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_22__["default"], { title: imageAspectRatio === '1:1'
|
|
104439
105977
|
? '1:1 — квадрат (1024×1024 px)'
|
|
104440
105978
|
: imageAspectRatio === '2:3'
|
|
104441
105979
|
? '2:3 — портрет (1024×1536 px)'
|
|
104442
105980
|
: 'Оба — квадрат и портрет на каждый подход', placement: "top" },
|
|
104443
105981
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", null,
|
|
104444
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
105982
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_29__["default"], { value: imageAspectRatio, exclusive: true, onChange: (_e, val) => {
|
|
104445
105983
|
if (val && val !== imageAspectRatio) {
|
|
104446
105984
|
if (generatedImagesData.length > 0) {
|
|
104447
105985
|
const label = val === 'both' ? 'оба (1:1 + 2:3)' : val;
|
|
@@ -104457,10 +105995,10 @@ ${imageData.originalPrompt}
|
|
|
104457
105995
|
}
|
|
104458
105996
|
}
|
|
104459
105997
|
}, size: "small", disabled: generatingImages, sx: { height: 42 } },
|
|
104460
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
104461
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
104462
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
104463
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { variant: "contained", color: "secondary", startIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
105998
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_30__["default"], { value: "1:1", sx: { px: 1.5, fontWeight: 600, fontSize: '0.8rem' } }, "1:1"),
|
|
105999
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_30__["default"], { value: "2:3", sx: { px: 1.5, fontWeight: 600, fontSize: '0.8rem' } }, "2:3"),
|
|
106000
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_30__["default"], { value: "both", sx: { px: 1.5, fontWeight: 600, fontSize: '0.8rem' } }, "\u041E\u0431\u0430")))),
|
|
106001
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { variant: "contained", color: "secondary", startIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_36__["default"], null), onClick: handleGenerateImages, disabled: generatingImages ||
|
|
104464
106002
|
!openaiApiKey ||
|
|
104465
106003
|
(!accessToken && !refreshToken) ||
|
|
104466
106004
|
!generateProduct.trim() ||
|
|
@@ -104478,9 +106016,9 @@ ${imageData.originalPrompt}
|
|
|
104478
106016
|
: !driveFolderUrl.trim()
|
|
104479
106017
|
? 'Заполните URL папки Google Drive'
|
|
104480
106018
|
: undefined }, generatingImages ? 'Generating Images...' : 'Generate Images')),
|
|
104481
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { variant: "contained", color: "success", size: "large", onClick: handleGenerate, disabled: loading, startIcon: loading ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_18__["default"], { size: 20, color: "inherit" }) : react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106019
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { variant: "contained", color: "success", size: "large", onClick: handleGenerate, disabled: loading, startIcon: loading ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_18__["default"], { size: 20, color: "inherit" }) : react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_40__["default"], null), sx: { py: 1.5, fontSize: '1.1rem', flexGrow: 1 } }, loading ? 'Generating...' : 'Generate Catalog'),
|
|
104482
106020
|
uploadedLink && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_20__["default"], { severity: "success", sx: { flexGrow: 1, minWidth: 0 }, action: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_8__["default"], { "aria-label": "copy link", color: "inherit", size: "small", onClick: handleCopyLink, sx: { ml: 1 } },
|
|
104483
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106021
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_41__["default"], { fontSize: "small" })) },
|
|
104484
106022
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { sx: { display: 'flex', alignItems: 'center', gap: 1, flexWrap: 'wrap' } },
|
|
104485
106023
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", null,
|
|
104486
106024
|
"\u041A\u0430\u0442\u0430\u043B\u043E\u0433 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D!",
|
|
@@ -104490,22 +106028,22 @@ ${imageData.originalPrompt}
|
|
|
104490
106028
|
getElectronAPI().openExternal(uploadedLink);
|
|
104491
106029
|
}, style: { cursor: 'pointer', textDecoration: 'underline', color: 'inherit' } }, "\u041E\u0442\u043A\u0440\u044B\u0442\u044C \u0432 Google Drive")),
|
|
104492
106030
|
linkCopied && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "caption", sx: { color: 'success.dark', fontWeight: 'bold' } }, "\u0421\u043A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u043D\u043E!"))))),
|
|
104493
|
-
folderFilesInfo !== null && !folderFilesInfo.hasProduct && driveFolderUrl.trim() && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_20__["default"], { severity: "warning", sx: { mt: 1 } }, "\u0414\u043B\u044F \u0433\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u0438 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0439 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F product.png/jpg. \u0421\u043D\u0430\u0447\u0430\u043B\u0430 \u0441\u0433\u0435\u043D\u0435\u0440\u0438\u0440\u0443\u0439\u0442\u0435 \u0435\u0433\u043E \u0441 \u043F\u043E\u043C\u043E\u0449\u044C\u044E \u043A\u043D\u043E\u043F\u043A\u0438 \"Generate Product from Banka\".")),
|
|
106031
|
+
folderFilesInfo !== null && !folderFilesInfo.hasProduct && driveFolderUrl.trim() && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_20__["default"], { severity: "warning", sx: { mt: 1 } }, "\u0414\u043B\u044F \u0433\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u0438 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0439 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F product.png/jpg/webp. \u0421\u043D\u0430\u0447\u0430\u043B\u0430 \u0441\u0433\u0435\u043D\u0435\u0440\u0438\u0440\u0443\u0439\u0442\u0435 \u0435\u0433\u043E \u0441 \u043F\u043E\u043C\u043E\u0449\u044C\u044E \u043A\u043D\u043E\u043F\u043A\u0438 \"Generate Product from Banka\".")),
|
|
104494
106032
|
!generatingImages && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null,
|
|
104495
106033
|
!openaiApiKey && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_20__["default"], { severity: "error", sx: { mt: 1 } }, "\u0417\u0430\u043F\u043E\u043B\u043D\u0438\u0442\u0435 OpenRouter API Key")),
|
|
104496
106034
|
openaiApiKey && (!accessToken && !refreshToken) && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_20__["default"], { severity: "error", sx: { mt: 1 } }, "\u0412\u043E\u0439\u0434\u0438\u0442\u0435 \u0432 Google Drive")),
|
|
104497
106035
|
openaiApiKey && (accessToken || refreshToken) && !generateProduct.trim() && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_20__["default"], { severity: "error", sx: { mt: 1 } }, "\u0417\u0430\u043F\u043E\u043B\u043D\u0438\u0442\u0435 \u043F\u043E\u043B\u0435 \u0422\u043E\u0432\u0430\u0440")),
|
|
104498
106036
|
openaiApiKey && (accessToken || refreshToken) && generateProduct.trim() && !generateGeo.trim() && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_20__["default"], { severity: "error", sx: { mt: 1 } }, "\u0417\u0430\u043F\u043E\u043B\u043D\u0438\u0442\u0435 \u043F\u043E\u043B\u0435 \u0413\u0435\u043E")),
|
|
104499
106037
|
openaiApiKey && (accessToken || refreshToken) && generateProduct.trim() && generateGeo.trim() && !driveFolderUrl.trim() && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_20__["default"], { severity: "error", sx: { mt: 1 } }, "\u0417\u0430\u043F\u043E\u043B\u043D\u0438\u0442\u0435 URL \u043F\u0430\u043F\u043A\u0438 Google Drive"))))),
|
|
104500
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("input", { type: "file", ref: productFileInputRef, accept: "image/png,image/jpeg,image/jpg", style: { display: 'none' }, onChange: handleProductFileSelected }),
|
|
106038
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("input", { type: "file", ref: productFileInputRef, accept: "image/png,image/jpeg,image/jpg,image/webp", style: { display: 'none' }, onChange: handleProductFileSelected }),
|
|
104501
106039
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_11__["default"], { direction: "row", spacing: 2, sx: { mb: 2 } },
|
|
104502
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { variant: "contained", color: "success", startIcon: uploadingProduct ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_18__["default"], { size: 20, color: "inherit" }) : react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
104503
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { variant: "contained", color: "info", startIcon: generatingLanding ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_18__["default"], { size: 20, color: "inherit" }) : react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106040
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { variant: "contained", color: "success", startIcon: uploadingProduct ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_18__["default"], { size: 20, color: "inherit" }) : react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_40__["default"], null), onClick: handleUploadProductFile, disabled: uploadingProduct || !accessToken || !driveFolderUrl.trim(), sx: { flexGrow: 1 }, size: "large" }, uploadingProduct ? 'Загрузка...' : 'Загрузить product.png/jpg/webp'),
|
|
106041
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { variant: "contained", color: "info", startIcon: generatingLanding ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_18__["default"], { size: 20, color: "inherit" }) : react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_47__["default"], null), onClick: handleCreateLanding, disabled: generatingLanding ||
|
|
104504
106042
|
!openaiApiKey ||
|
|
104505
106043
|
!accessToken ||
|
|
104506
106044
|
!driveFolderUrl.trim() ||
|
|
104507
106045
|
(folderFilesInfo !== null && !folderFilesInfo.hasProduct), sx: { flexGrow: 1 }, size: "large", title: folderFilesInfo !== null && !folderFilesInfo.hasProduct
|
|
104508
|
-
? 'product.png/jpg не найден в папке. Загрузите его с помощью кнопки «Загрузить product
|
|
106046
|
+
? 'product.png/jpg/webp не найден в папке. Загрузите его с помощью кнопки «Загрузить product»'
|
|
104509
106047
|
: undefined }, generatingLanding ? 'Creating Landing...' : 'Создать лендинг')),
|
|
104510
106048
|
generatedImagesData.length > 0 && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { sx: { mb: 2, mt: 3 } },
|
|
104511
106049
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "h6", gutterBottom: true, sx: { fontWeight: 'bold' } },
|
|
@@ -104517,6 +106055,8 @@ ${imageData.originalPrompt}
|
|
|
104517
106055
|
checkingImages && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { sx: { display: 'flex', alignItems: 'center', gap: 1, mb: 2 } },
|
|
104518
106056
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_18__["default"], { size: 16 }),
|
|
104519
106057
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "caption", sx: { color: 'text.secondary' } }, "\u041F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043A\u0430\u0447\u0435\u0441\u0442\u0432\u0430..."))),
|
|
106058
|
+
generatedImagesData.length > 0 && generatedImagesData.some(img => !img.uploaded && img.imageUrl) && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { sx: { mb: 2 } },
|
|
106059
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { variant: "contained", color: "primary", onClick: handleUploadAllImages, disabled: uploadingImages || generatingImages || !driveFolderUrl.trim(), startIcon: uploadingImages ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_18__["default"], { size: 20 }) : react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_40__["default"], null), fullWidth: true }, uploadingImages ? 'Загрузка...' : `Загрузить все (${generatedImagesData.filter(img => !img.uploaded && img.imageUrl).length})`))),
|
|
104520
106060
|
generatedImagesData.length > 0 && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { sx: {
|
|
104521
106061
|
display: 'grid',
|
|
104522
106062
|
gridTemplateColumns: { xs: '1fr', sm: 'repeat(2, 1fr)', md: 'repeat(3, 1fr)' },
|
|
@@ -104526,6 +106066,34 @@ ${imageData.originalPrompt}
|
|
|
104526
106066
|
const imgRatio = imageData.aspectRatio ?? (imageAspectRatio === 'both' ? '1:1' : imageAspectRatio);
|
|
104527
106067
|
const aspectRatioCss = imgRatio === '2:3' ? '2 / 3' : '1 / 1';
|
|
104528
106068
|
return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { key: imageData.index, sx: { position: 'relative' } },
|
|
106069
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_22__["default"], { title: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u043A\u0440\u0435\u0430\u0442\u0438\u0432" },
|
|
106070
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", null,
|
|
106071
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_8__["default"], { size: "small", "aria-label": "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u043A\u0440\u0435\u0430\u0442\u0438\u0432", sx: {
|
|
106072
|
+
position: 'absolute',
|
|
106073
|
+
top: 6,
|
|
106074
|
+
right: 6,
|
|
106075
|
+
zIndex: 3,
|
|
106076
|
+
bgcolor: 'rgba(32, 32, 32, 0.92)',
|
|
106077
|
+
color: '#fff',
|
|
106078
|
+
border: '2px solid rgba(255, 255, 255, 0.95)',
|
|
106079
|
+
boxShadow: '0 2px 12px rgba(0, 0, 0, 0.45)',
|
|
106080
|
+
width: 36,
|
|
106081
|
+
height: 36,
|
|
106082
|
+
'&:hover': {
|
|
106083
|
+
bgcolor: 'error.main',
|
|
106084
|
+
borderColor: 'rgba(255, 255, 255, 1)',
|
|
106085
|
+
color: '#fff',
|
|
106086
|
+
},
|
|
106087
|
+
'&.Mui-disabled': {
|
|
106088
|
+
bgcolor: 'rgba(32, 32, 32, 0.45)',
|
|
106089
|
+
borderColor: 'rgba(255, 255, 255, 0.4)',
|
|
106090
|
+
color: 'rgba(255, 255, 255, 0.5)',
|
|
106091
|
+
},
|
|
106092
|
+
}, onClick: () => handleDeleteGeneratedImage(imageData.index), disabled: generatingImages ||
|
|
106093
|
+
imageData.generating ||
|
|
106094
|
+
!!imageData.regenerating ||
|
|
106095
|
+
!!imageData.uploading },
|
|
106096
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_42__["default"], { fontSize: "small" })))),
|
|
104529
106097
|
imageData.generating ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { sx: {
|
|
104530
106098
|
width: '100%',
|
|
104531
106099
|
aspectRatio: aspectRatioCss,
|
|
@@ -104546,7 +106114,24 @@ ${imageData.originalPrompt}
|
|
|
104546
106114
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "caption", sx: { color: 'text.secondary', textAlign: 'center' } }, imageData.approach),
|
|
104547
106115
|
generatingImages && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "caption", sx: { color: 'text.secondary', textAlign: 'center' } },
|
|
104548
106116
|
"\u23F1\uFE0F \u041F\u0440\u043E\u0448\u043B\u043E: ",
|
|
104549
|
-
formatElapsedTime(elapsedTime.images))))) : imageData.imageUrl ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106117
|
+
formatElapsedTime(elapsedTime.images))))) : imageData.regenerating && !imageData.imageUrl ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { sx: {
|
|
106118
|
+
width: '100%',
|
|
106119
|
+
aspectRatio: aspectRatioCss,
|
|
106120
|
+
border: (theme) => `2px dashed ${theme.palette.primary.main}`,
|
|
106121
|
+
borderRadius: 1,
|
|
106122
|
+
backgroundColor: (theme) => theme.palette.mode === 'dark'
|
|
106123
|
+
? 'rgba(25, 118, 210, 0.1)'
|
|
106124
|
+
: 'rgba(25, 118, 210, 0.05)',
|
|
106125
|
+
display: 'flex',
|
|
106126
|
+
flexDirection: 'column',
|
|
106127
|
+
alignItems: 'center',
|
|
106128
|
+
justifyContent: 'center',
|
|
106129
|
+
gap: 2,
|
|
106130
|
+
p: 3
|
|
106131
|
+
} },
|
|
106132
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_18__["default"], { size: 40, sx: { color: 'primary.main' } }),
|
|
106133
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "body2", sx: { color: 'text.secondary', textAlign: 'center', fontWeight: 'bold' } }, "\u041F\u0435\u0440\u0435\u0434\u0435\u043B\u043A\u0430..."),
|
|
106134
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "caption", sx: { color: 'text.secondary', textAlign: 'center' } }, imageData.approach))) : imageData.imageUrl ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null,
|
|
104550
106135
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { component: "img", src: imageData.imageUrl, alt: `Generated Image ${imageData.index}`, sx: {
|
|
104551
106136
|
width: '100%',
|
|
104552
106137
|
height: 'auto',
|
|
@@ -104641,7 +106226,7 @@ ${imageData.originalPrompt}
|
|
|
104641
106226
|
"+",
|
|
104642
106227
|
imageData.checkErrors.length - 2,
|
|
104643
106228
|
" \u0435\u0449\u0451")))),
|
|
104644
|
-
imageData.checkFailed && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { size: "small", variant: "outlined", color: "warning", startIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106229
|
+
imageData.checkFailed && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { size: "small", variant: "outlined", color: "warning", startIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_48__["default"], null), onClick: () => handleRetryCheck(imageData), disabled: imageData.checking, sx: { mt: 0.5, fontSize: '0.7rem', py: 0.25, px: 1 } }, "\u041F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u044C \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0443")))),
|
|
104645
106230
|
imageData.checkStatus === 'checking' && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "caption", sx: { color: 'warning.main', display: 'block' } }, "\uD83D\uDD0D \u041F\u0440\u043E\u0432\u0435\u0440\u044F\u0435\u0442\u0441\u044F...")),
|
|
104646
106231
|
imageData.checkStatus === 'pending' && !imageData.failed && !imageData.generating && imageData.imageUrl && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "caption", sx: { color: 'text.secondary', display: 'block' } }, "\u23F3 \u041E\u0436\u0438\u0434\u0430\u0435\u0442 \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0438")),
|
|
104647
106232
|
imageData.failed && !imageData.generating && !imageData.imageUrl && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "caption", sx: { color: 'error.main', display: 'block', fontWeight: 'bold' } }, "\u274C \u0413\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u044F \u043D\u0435 \u0443\u0434\u0430\u043B\u0430\u0441\u044C")),
|
|
@@ -104664,7 +106249,7 @@ ${imageData.originalPrompt}
|
|
|
104664
106249
|
: 'transparent'
|
|
104665
106250
|
}
|
|
104666
106251
|
} }),
|
|
104667
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { size: "small", variant: "contained", color: imageData.failed ? 'error' : imageData.checkStatus === 'needs_rebuild' ? 'warning' : 'primary', startIcon: imageData.regenerating ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_18__["default"], { size: 16 }) : react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106252
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { size: "small", variant: "contained", color: imageData.failed ? 'error' : imageData.checkStatus === 'needs_rebuild' ? 'warning' : 'primary', startIcon: imageData.regenerating ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_18__["default"], { size: 16 }) : react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_36__["default"], null), onClick: () => handleRegenerateImage(imageData), disabled: imageData.regenerating ||
|
|
104668
106253
|
imageData.uploading ||
|
|
104669
106254
|
imageData.checkStatus === 'checking' ||
|
|
104670
106255
|
!imageData.originalPrompt ||
|
|
@@ -104674,12 +106259,12 @@ ${imageData.originalPrompt}
|
|
|
104674
106259
|
: ((generatingImages && !imageData.imageUrl && !imageData.failed && !imageData.generating)
|
|
104675
106260
|
? 'В очереди'
|
|
104676
106261
|
: (!imageData.imageUrl ? 'Сгенерировать' : 'Переделать'))),
|
|
104677
|
-
imageData.imageUrl && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { size: "small", variant: "outlined", color: "secondary", startIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106262
|
+
imageData.imageUrl && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { size: "small", variant: "outlined", color: "secondary", startIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_48__["default"], null), onClick: () => handleRegenerateImageFresh(imageData), disabled: imageData.regenerating ||
|
|
104678
106263
|
imageData.uploading ||
|
|
104679
106264
|
imageData.checkStatus === 'checking' ||
|
|
104680
106265
|
!imageData.originalPrompt ||
|
|
104681
106266
|
!imageData.productImageUrl, fullWidth: true }, "\u041F\u0435\u0440\u0435\u0434\u0435\u043B\u0430\u0442\u044C \u0437\u0430\u043D\u043E\u0432\u043E")),
|
|
104682
|
-
!imageData.uploaded && imageData.imageUrl && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { size: "small", variant: "outlined", startIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106267
|
+
!imageData.uploaded && imageData.imageUrl && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { size: "small", variant: "outlined", startIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_40__["default"], null), onClick: () => {
|
|
104683
106268
|
const folderId = extractFolderId(driveFolderUrl);
|
|
104684
106269
|
if (folderId) {
|
|
104685
106270
|
handleUploadImage(imageData, folderId);
|
|
@@ -104687,15 +106272,24 @@ ${imageData.originalPrompt}
|
|
|
104687
106272
|
}, disabled: imageData.uploading || imageData.regenerating || !driveFolderUrl.trim(), fullWidth: true }, imageData.uploading ? 'Загрузка...' : 'Загрузить'))))));
|
|
104688
106273
|
}))),
|
|
104689
106274
|
generatedImagesData.length > 0 && generatedImagesData.some(img => !img.uploaded && img.imageUrl) && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { sx: { mt: 2 } },
|
|
104690
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { variant: "contained", color: "primary", onClick: handleUploadAllImages, disabled: uploadingImages || generatingImages || !driveFolderUrl.trim(), startIcon: uploadingImages ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_18__["default"], { size: 20 }) : react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106275
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { variant: "contained", color: "primary", onClick: handleUploadAllImages, disabled: uploadingImages || generatingImages || !driveFolderUrl.trim(), startIcon: uploadingImages ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_18__["default"], { size: 20 }) : react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_40__["default"], null), fullWidth: true }, uploadingImages ? 'Загрузка...' : `Загрузить все (${generatedImagesData.filter(img => !img.uploaded && img.imageUrl).length})`))))),
|
|
104691
106276
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_16__["default"], { sx: { my: 2 } }),
|
|
104692
106277
|
(generatedTitlesData.length > 0 || generatedTextsData.length > 0 || loadingContentFromDrive) && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { sx: { mb: 2 } },
|
|
104693
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
104694
|
-
"
|
|
104695
|
-
|
|
104696
|
-
|
|
104697
|
-
|
|
104698
|
-
|
|
106278
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { sx: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 1, mb: 1 } },
|
|
106279
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "h6", sx: { fontWeight: 'bold' }, component: "div" },
|
|
106280
|
+
"\u0421\u0433\u0435\u043D\u0435\u0440\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0435 \u043F\u0430\u0440\u044B (",
|
|
106281
|
+
Math.min(generatedTitlesData.filter(t => t.title).length, generatedTextsData.filter(t => t.text).length),
|
|
106282
|
+
"/",
|
|
106283
|
+
Math.max(generatedTitlesData.length, generatedTextsData.length),
|
|
106284
|
+
")"),
|
|
106285
|
+
(generatedTitlesData.length > 0 || generatedTextsData.length > 0) && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_22__["default"], { title: pairsJsonCopied ? 'Скопировано' : 'Скопировать все пары как JSON-массив' },
|
|
106286
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_8__["default"], { size: "small", "aria-label": "\u0421\u043A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u043F\u0430\u0440\u044B \u043A\u0430\u043A JSON", onClick: () => void copyGeneratedPairsAsJson(), disabled: generating, sx: {
|
|
106287
|
+
opacity: 0.28,
|
|
106288
|
+
p: 0.35,
|
|
106289
|
+
color: 'text.secondary',
|
|
106290
|
+
'&:hover': { opacity: 0.75, color: 'text.primary' },
|
|
106291
|
+
} },
|
|
106292
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_41__["default"], { sx: { fontSize: 16 } }))))),
|
|
104699
106293
|
loadingContentFromDrive && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { sx: {
|
|
104700
106294
|
display: 'flex',
|
|
104701
106295
|
flexDirection: 'column',
|
|
@@ -104722,7 +106316,7 @@ ${imageData.originalPrompt}
|
|
|
104722
106316
|
const pairLabel = pairApproach ? pairApproach.name : `пара ${i + 1}`;
|
|
104723
106317
|
const pairGenerating = (titleData?.generating || textData?.generating);
|
|
104724
106318
|
const pairFailed = (!pairGenerating && titleData?.failed && textData?.failed);
|
|
104725
|
-
return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106319
|
+
return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_31__["default"], { key: i, variant: "outlined", sx: {
|
|
104726
106320
|
p: 2,
|
|
104727
106321
|
borderColor: pairFailed
|
|
104728
106322
|
? 'error.main'
|
|
@@ -104734,7 +106328,7 @@ ${imageData.originalPrompt}
|
|
|
104734
106328
|
? (theme.palette.mode === 'dark' ? 'rgba(25,118,210,0.05)' : 'rgba(25,118,210,0.02)')
|
|
104735
106329
|
: 'transparent',
|
|
104736
106330
|
} },
|
|
104737
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_11__["default"], { direction: "row", spacing: 1, alignItems: "center", sx: { mb: 1.5 } },
|
|
106331
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_11__["default"], { direction: "row", spacing: 1, alignItems: "center", sx: { mb: 1.5, flexWrap: 'wrap' } },
|
|
104738
106332
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "caption", sx: {
|
|
104739
106333
|
fontWeight: 700,
|
|
104740
106334
|
px: 1,
|
|
@@ -104750,7 +106344,12 @@ ${imageData.originalPrompt}
|
|
|
104750
106344
|
"\u041F\u0430\u0440\u0430 ",
|
|
104751
106345
|
i + 1),
|
|
104752
106346
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "caption", color: "text.secondary" }, pairLabel),
|
|
104753
|
-
|
|
106347
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { sx: { flexGrow: 1, minWidth: 8 } }),
|
|
106348
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_22__["default"], { title: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u043F\u0430\u0440\u0443" },
|
|
106349
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", null,
|
|
106350
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_8__["default"], { size: "small", color: "error", "aria-label": "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u043F\u0430\u0440\u0443", onClick: () => handleDeleteGeneratedPair(i), disabled: pairGenerating || generating },
|
|
106351
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_42__["default"], { fontSize: "small" })))),
|
|
106352
|
+
translatingPairs && !pairTranslations[i] ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_18__["default"], { size: 13, sx: { color: 'text.disabled', ml: 0.5 } })) : pairTranslations[i] ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_22__["default"], { title: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], null,
|
|
104754
106353
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "caption", sx: { fontWeight: 700, display: 'block', mb: 0.5 } }, "\u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A:"),
|
|
104755
106354
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "caption", sx: { display: 'block', mb: 1 } }, pairTranslations[i].titleRu),
|
|
104756
106355
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "caption", sx: { fontWeight: 700, display: 'block', mb: 0.5 } }, "\u0422\u0435\u043A\u0441\u0442:"),
|
|
@@ -104758,13 +106357,26 @@ ${imageData.originalPrompt}
|
|
|
104758
106357
|
tooltip: { sx: { maxWidth: 360, fontSize: 12, lineHeight: 1.6, p: '10px 14px' } },
|
|
104759
106358
|
} },
|
|
104760
106359
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_8__["default"], { size: "small", sx: { p: 0.25, color: 'text.disabled', '&:hover': { color: 'primary.main' } } },
|
|
104761
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106360
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_44__["default"], { sx: { fontSize: 14 } })))) : null),
|
|
104762
106361
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_11__["default"], { spacing: 1.5 },
|
|
104763
106362
|
titleData && (titleData.generating ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { sx: { display: 'flex', alignItems: 'center', gap: 1 } },
|
|
104764
106363
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_18__["default"], { size: 16, sx: { color: 'primary.main' } }),
|
|
104765
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "body2", color: "text.secondary" }, "\u0413\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u044F \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u0430\u2026"))) : titleData.failed ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
104766
|
-
|
|
104767
|
-
|
|
106364
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "body2", color: "text.secondary" }, "\u0413\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u044F \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u0430\u2026"))) : titleData.failed ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_15__["default"], { label: `Заголовок ${i + 1}`, variant: "outlined", fullWidth: true, size: "small", value: titleData.title, placeholder: "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \u0432\u0440\u0443\u0447\u043D\u0443\u044E", helperText: titleData.errorMessage ? `Не сгенерирован: ${titleData.errorMessage}` : 'Можно ввести или исправить заголовок вручную', error: !!titleData.errorMessage, onChange: (e) => {
|
|
106365
|
+
const newValue = e.target.value;
|
|
106366
|
+
setGeneratedTitlesData(prev => {
|
|
106367
|
+
const updated = prev.map(t => t.index === titleData.index
|
|
106368
|
+
? { ...t, title: newValue, failed: false, errorMessage: undefined }
|
|
106369
|
+
: t);
|
|
106370
|
+
setTitles(updated.map(t => t.title).filter(Boolean).join('\n'));
|
|
106371
|
+
return updated;
|
|
106372
|
+
});
|
|
106373
|
+
}, sx: {
|
|
106374
|
+
'& .MuiInputBase-root': {
|
|
106375
|
+
backgroundColor: (theme) => theme.palette.mode === 'dark'
|
|
106376
|
+
? 'rgba(244,67,54,0.08)'
|
|
106377
|
+
: 'rgba(244,67,54,0.04)'
|
|
106378
|
+
}
|
|
106379
|
+
} })) : (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_15__["default"], { label: `Заголовок ${i + 1}`, variant: "outlined", fullWidth: true, size: "small", value: titleData.title, onChange: (e) => {
|
|
104768
106380
|
const newValue = e.target.value;
|
|
104769
106381
|
setGeneratedTitlesData(prev => {
|
|
104770
106382
|
const updated = prev.map(t => t.index === titleData.index ? { ...t, title: newValue } : t);
|
|
@@ -104780,9 +106392,22 @@ ${imageData.originalPrompt}
|
|
|
104780
106392
|
} }))),
|
|
104781
106393
|
textData && (textData.generating ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { sx: { display: 'flex', alignItems: 'center', gap: 1 } },
|
|
104782
106394
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_18__["default"], { size: 16, sx: { color: 'primary.main' } }),
|
|
104783
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "body2", color: "text.secondary" }, "\u0413\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u044F \u0442\u0435\u043A\u0441\u0442\u0430\u2026"))) : textData.failed ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
104784
|
-
|
|
104785
|
-
|
|
106395
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "body2", color: "text.secondary" }, "\u0413\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u044F \u0442\u0435\u043A\u0441\u0442\u0430\u2026"))) : textData.failed ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_15__["default"], { label: `Текст ${i + 1}`, variant: "outlined", fullWidth: true, multiline: true, minRows: 3, value: textData.text, placeholder: "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043A\u0441\u0442 \u043E\u0431\u044A\u044F\u0432\u043B\u0435\u043D\u0438\u044F \u0432\u0440\u0443\u0447\u043D\u0443\u044E", helperText: textData.errorMessage ? `Не сгенерирован: ${textData.errorMessage}` : 'Можно ввести или исправить текст вручную', error: !!textData.errorMessage, onChange: (e) => {
|
|
106396
|
+
const newValue = e.target.value;
|
|
106397
|
+
setGeneratedTextsData(prev => {
|
|
106398
|
+
const updated = prev.map(t => t.index === textData.index
|
|
106399
|
+
? { ...t, text: newValue, failed: false, errorMessage: undefined }
|
|
106400
|
+
: t);
|
|
106401
|
+
setTexts(updated.map(t => t.text));
|
|
106402
|
+
return updated;
|
|
106403
|
+
});
|
|
106404
|
+
}, sx: {
|
|
106405
|
+
'& .MuiInputBase-root': {
|
|
106406
|
+
backgroundColor: (theme) => theme.palette.mode === 'dark'
|
|
106407
|
+
? 'rgba(244,67,54,0.08)'
|
|
106408
|
+
: 'rgba(244,67,54,0.04)'
|
|
106409
|
+
}
|
|
106410
|
+
} })) : (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_15__["default"], { label: `Текст ${i + 1}`, variant: "outlined", fullWidth: true, multiline: true, minRows: 3, value: textData.text, onChange: (e) => {
|
|
104786
106411
|
const newValue = e.target.value;
|
|
104787
106412
|
setGeneratedTextsData(prev => {
|
|
104788
106413
|
const updated = prev.map(t => t.index === textData.index ? { ...t, text: newValue } : t);
|
|
@@ -104799,7 +106424,7 @@ ${imageData.originalPrompt}
|
|
|
104799
106424
|
}))))),
|
|
104800
106425
|
(landingGenerationLogs.length > 0 || generatingLanding) && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { sx: { mb: 2 } },
|
|
104801
106426
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "h6", gutterBottom: true, sx: { fontWeight: 'bold' } }, "\u041F\u0440\u043E\u0446\u0435\u0441\u0441 \u0441\u043E\u0437\u0434\u0430\u043D\u0438\u044F \u043B\u0435\u043D\u0434\u0438\u043D\u0433\u0430"),
|
|
104802
|
-
landingGenerationLogs.length > 0 && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106427
|
+
landingGenerationLogs.length > 0 && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_31__["default"], { sx: {
|
|
104803
106428
|
p: 2,
|
|
104804
106429
|
backgroundColor: (theme) => theme.palette.mode === 'dark'
|
|
104805
106430
|
? 'rgba(25, 118, 210, 0.1)'
|
|
@@ -104825,8 +106450,8 @@ ${imageData.originalPrompt}
|
|
|
104825
106450
|
generatingLanding && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { sx: { display: 'flex', alignItems: 'center', gap: 1, mb: 2 } },
|
|
104826
106451
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_18__["default"], { size: 20 }),
|
|
104827
106452
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { variant: "body2", sx: { color: 'text.secondary' } }, formatElapsedTime(elapsedTime.landing)))),
|
|
104828
|
-
!generatingLanding && generatedLandingHTML && generatedLandingImageBlob && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { variant: "outlined", color: "primary", onClick: handlePreviewLanding, startIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
104829
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106453
|
+
!generatingLanding && generatedLandingHTML && generatedLandingImageBlob && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_17__["default"], { variant: "outlined", color: "primary", onClick: handlePreviewLanding, startIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_50__["default"], null), fullWidth: true }, "\u041F\u0440\u0435\u0434\u043F\u0440\u043E\u0441\u043C\u043E\u0442\u0440 \u043B\u0435\u043D\u0434\u0438\u043D\u0433\u0430"))))))))),
|
|
106454
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_PromptManagerDialog__WEBPACK_IMPORTED_MODULE_51__["default"], { open: promptManagerOpen, onClose: () => setPromptManagerOpen(false) }))));
|
|
104830
106455
|
}
|
|
104831
106456
|
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (App);
|
|
104832
106457
|
|
|
@@ -104847,8 +106472,8 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
104847
106472
|
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "./node_modules/react/index.js");
|
|
104848
106473
|
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
|
|
104849
106474
|
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/Box/Box.js");
|
|
104850
|
-
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/
|
|
104851
|
-
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/
|
|
106475
|
+
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/Typography/Typography.js");
|
|
106476
|
+
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/Paper/Paper.js");
|
|
104852
106477
|
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/IconButton/IconButton.js");
|
|
104853
106478
|
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/TextField/TextField.js");
|
|
104854
106479
|
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/Stack/Stack.js");
|
|
@@ -104863,25 +106488,27 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
104863
106488
|
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/DialogContent/DialogContent.js");
|
|
104864
106489
|
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/Tabs/Tabs.js");
|
|
104865
106490
|
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/Tab/Tab.js");
|
|
104866
|
-
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/
|
|
104867
|
-
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/
|
|
104868
|
-
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/
|
|
104869
|
-
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/
|
|
104870
|
-
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/
|
|
104871
|
-
/* harmony import */ var
|
|
104872
|
-
/* harmony import */ var
|
|
104873
|
-
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/
|
|
104874
|
-
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/
|
|
104875
|
-
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/
|
|
104876
|
-
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/
|
|
104877
|
-
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/
|
|
104878
|
-
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/
|
|
104879
|
-
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/
|
|
104880
|
-
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/
|
|
104881
|
-
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/
|
|
104882
|
-
/* harmony import */ var
|
|
104883
|
-
/* harmony import */ var
|
|
104884
|
-
/* harmony import */ var
|
|
106491
|
+
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/Tooltip/Tooltip.js");
|
|
106492
|
+
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/Checkbox/Checkbox.js");
|
|
106493
|
+
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/Accordion/Accordion.js");
|
|
106494
|
+
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/AccordionSummary/AccordionSummary.js");
|
|
106495
|
+
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/AccordionDetails/AccordionDetails.js");
|
|
106496
|
+
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/DialogActions/DialogActions.js");
|
|
106497
|
+
/* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/esm/Snackbar/Snackbar.js");
|
|
106498
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/Cancel.js");
|
|
106499
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/Close.js");
|
|
106500
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/CompareArrows.js");
|
|
106501
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/Edit.js");
|
|
106502
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/ExpandMore.js");
|
|
106503
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/KeyboardArrowDown.js");
|
|
106504
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/KeyboardArrowUp.js");
|
|
106505
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/RestartAlt.js");
|
|
106506
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/Save.js");
|
|
106507
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/Search.js");
|
|
106508
|
+
/* harmony import */ var _mui_icons_material__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! @mui/icons-material */ "./node_modules/@mui/icons-material/esm/Settings.js");
|
|
106509
|
+
/* harmony import */ var _prompts__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! ./prompts */ "./src/prompts.ts");
|
|
106510
|
+
/* harmony import */ var _landingPrompts__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! ./landingPrompts */ "./src/landingPrompts.ts");
|
|
106511
|
+
/* harmony import */ var _promptOverrides__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! ./promptOverrides */ "./src/promptOverrides.ts");
|
|
104885
106512
|
|
|
104886
106513
|
|
|
104887
106514
|
|
|
@@ -104892,6 +106519,36 @@ function TabPanel(props) {
|
|
|
104892
106519
|
const { children, value, index, ...other } = props;
|
|
104893
106520
|
return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { role: "tabpanel", hidden: value !== index, id: `prompt-tabpanel-${index}`, "aria-labelledby": `prompt-tab-${index}`, ...other }, value === index && react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_1__["default"], { sx: { p: 3 } }, children)));
|
|
104894
106521
|
}
|
|
106522
|
+
/** Подсказка для кнопки типа товара: списки подходов для текстов и картинок (номера как в таблицах). */
|
|
106523
|
+
function productTypePresetTooltip(label) {
|
|
106524
|
+
const textNums = _promptOverrides__WEBPACK_IMPORTED_MODULE_38__.PRODUCT_TYPE_TEXT_PAIR_PRESETS[label];
|
|
106525
|
+
if (!textNums)
|
|
106526
|
+
return label;
|
|
106527
|
+
const sortedText = [...textNums].sort((a, b) => a - b);
|
|
106528
|
+
const imgPreset = _promptOverrides__WEBPACK_IMPORTED_MODULE_38__.PRODUCT_TYPE_IMAGE_PRESETS[label];
|
|
106529
|
+
const sortedImg = imgPreset ? [...imgPreset].sort((a, b) => a - b) : null;
|
|
106530
|
+
return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_1__["default"], { sx: { py: 0.25, maxWidth: 380, color: 'common.white', fontSize: '0.75rem' } },
|
|
106531
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_2__["default"], { variant: "caption", component: "div", sx: { fontWeight: 700, mb: 0.75, display: 'block', color: 'inherit' } },
|
|
106532
|
+
"\u0422\u0435\u043A\u0441\u0442\u044B \u2014 ",
|
|
106533
|
+
sortedText.length,
|
|
106534
|
+
" \u043F\u0430\u0440:"),
|
|
106535
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_1__["default"], { component: "ul", sx: { m: 0, pl: 2.25, mb: 1.25, listStyleType: 'disc', color: 'inherit' } }, sortedText.map((n) => (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_2__["default"], { key: `t-${n}`, variant: "caption", component: "li", sx: { display: 'list-item', lineHeight: 1.5, mb: 0.25, color: 'inherit' } },
|
|
106536
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("strong", null,
|
|
106537
|
+
n,
|
|
106538
|
+
"."),
|
|
106539
|
+
" ",
|
|
106540
|
+
_prompts__WEBPACK_IMPORTED_MODULE_36__.PAIR_APPROACH_POOL[n - 1]?.name ?? '—')))),
|
|
106541
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_2__["default"], { variant: "caption", component: "div", sx: { fontWeight: 700, mb: 0.75, display: 'block', color: 'inherit' } },
|
|
106542
|
+
"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F",
|
|
106543
|
+
sortedImg ? ` — ${sortedImg.length} подходов` : '',
|
|
106544
|
+
":"),
|
|
106545
|
+
sortedImg ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_1__["default"], { component: "ul", sx: { m: 0, pl: 2.25, listStyleType: 'disc', color: 'inherit' } }, sortedImg.map((n) => (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_2__["default"], { key: `i-${n}`, variant: "caption", component: "li", sx: { display: 'list-item', lineHeight: 1.5, mb: 0.25, color: 'inherit' } },
|
|
106546
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("strong", null,
|
|
106547
|
+
n,
|
|
106548
|
+
"."),
|
|
106549
|
+
" ",
|
|
106550
|
+
_prompts__WEBPACK_IMPORTED_MODULE_36__.CREO_APPROACHES[n - 1]?.name ?? '—'))))) : (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_2__["default"], { variant: "caption", sx: { display: 'block', lineHeight: 1.5, opacity: 0.85, color: 'inherit' } }, "\u0412\u0441\u0435 10 \u043F\u043E\u0434\u0445\u043E\u0434\u043E\u0432 \u043F\u043E 1 \u043A\u0440\u0435\u043E (\u043D\u0435\u0442 \u043E\u0442\u0434\u0435\u043B\u044C\u043D\u043E\u0433\u043E \u043F\u0440\u0435\u0441\u0435\u0442\u0430)"))));
|
|
106551
|
+
}
|
|
104895
106552
|
function SearchableTextField({ value, onChange, disabled, rows = 15, placeholder, helperText, fullWidth = true, multiline = true }) {
|
|
104896
106553
|
const [searchOpen, setSearchOpen] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false);
|
|
104897
106554
|
const [searchQuery, setSearchQuery] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)('');
|
|
@@ -104961,7 +106618,7 @@ function SearchableTextField({ value, onChange, disabled, rows = 15, placeholder
|
|
|
104961
106618
|
}
|
|
104962
106619
|
};
|
|
104963
106620
|
return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_1__["default"], { sx: { position: 'relative' } },
|
|
104964
|
-
searchOpen && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106621
|
+
searchOpen && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_3__["default"], { elevation: 3, sx: {
|
|
104965
106622
|
position: 'absolute',
|
|
104966
106623
|
top: 4,
|
|
104967
106624
|
right: 4,
|
|
@@ -104975,7 +106632,7 @@ function SearchableTextField({ value, onChange, disabled, rows = 15, placeholder
|
|
|
104975
106632
|
border: '1px solid',
|
|
104976
106633
|
borderColor: 'divider',
|
|
104977
106634
|
} },
|
|
104978
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106635
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_34__["default"], { sx: { fontSize: 18, color: 'text.secondary' } }),
|
|
104979
106636
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("input", { ref: searchInputRef, value: searchQuery, onChange: (e) => { setSearchQuery(e.target.value); setCurrentMatch(0); }, onKeyDown: handleKeyDown, placeholder: "\u041F\u043E\u0438\u0441\u043A...", style: {
|
|
104980
106637
|
border: 'none',
|
|
104981
106638
|
outline: 'none',
|
|
@@ -104986,13 +106643,13 @@ function SearchableTextField({ value, onChange, disabled, rows = 15, placeholder
|
|
|
104986
106643
|
color: 'inherit',
|
|
104987
106644
|
fontFamily: 'inherit',
|
|
104988
106645
|
}, autoFocus: true }),
|
|
104989
|
-
searchQuery && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106646
|
+
searchQuery && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_2__["default"], { variant: "caption", sx: { color: 'text.secondary', whiteSpace: 'nowrap', minWidth: 50, textAlign: 'center' } }, matches.length > 0 ? `${currentMatch + 1} / ${matches.length}` : 'нет')),
|
|
104990
106647
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_4__["default"], { size: "small", onClick: () => navigateToMatch(currentMatch - 1), disabled: matches.length === 0, sx: { p: 0.3 } },
|
|
104991
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106648
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_31__["default"], { sx: { fontSize: 18 } })),
|
|
104992
106649
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_4__["default"], { size: "small", onClick: () => navigateToMatch(currentMatch + 1), disabled: matches.length === 0, sx: { p: 0.3 } },
|
|
104993
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106650
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_30__["default"], { sx: { fontSize: 18 } })),
|
|
104994
106651
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_4__["default"], { size: "small", onClick: () => { setSearchOpen(false); setSearchQuery(''); }, sx: { p: 0.3 } },
|
|
104995
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106652
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_26__["default"], { sx: { fontSize: 18 } })))),
|
|
104996
106653
|
!searchOpen && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_4__["default"], { size: "small", onClick: () => { setSearchOpen(true); setTimeout(() => searchInputRef.current?.focus(), 50); }, sx: {
|
|
104997
106654
|
position: 'absolute',
|
|
104998
106655
|
top: 8,
|
|
@@ -105003,7 +106660,7 @@ function SearchableTextField({ value, onChange, disabled, rows = 15, placeholder
|
|
|
105003
106660
|
bgcolor: 'background.paper',
|
|
105004
106661
|
boxShadow: 1,
|
|
105005
106662
|
} },
|
|
105006
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106663
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_34__["default"], { sx: { fontSize: 16 } }))),
|
|
105007
106664
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { inputRef: textareaRef, fullWidth: fullWidth, multiline: multiline, rows: rows, value: value, onChange: onChange, disabled: disabled, placeholder: placeholder, helperText: helperText, onKeyDown: handleTextareaKeyDown, sx: {
|
|
105008
106665
|
'& .MuiInputBase-input': {
|
|
105009
106666
|
fontFamily: '"SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace',
|
|
@@ -105151,7 +106808,7 @@ function DiffViewer({ oldText, newText }) {
|
|
|
105151
106808
|
}
|
|
105152
106809
|
};
|
|
105153
106810
|
return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_1__["default"], { sx: { position: 'relative' } },
|
|
105154
|
-
searchOpen && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106811
|
+
searchOpen && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_3__["default"], { elevation: 3, sx: {
|
|
105155
106812
|
position: 'absolute',
|
|
105156
106813
|
top: 4,
|
|
105157
106814
|
right: 4,
|
|
@@ -105165,7 +106822,7 @@ function DiffViewer({ oldText, newText }) {
|
|
|
105165
106822
|
border: '1px solid',
|
|
105166
106823
|
borderColor: 'divider',
|
|
105167
106824
|
} },
|
|
105168
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106825
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_34__["default"], { sx: { fontSize: 18, color: 'text.secondary' } }),
|
|
105169
106826
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("input", { ref: searchInputRef, value: searchQuery, onChange: (e) => { setSearchQuery(e.target.value); setCurrentMatch(0); }, onKeyDown: handleSearchKeyDown, placeholder: "\u041F\u043E\u0438\u0441\u043A...", style: {
|
|
105170
106827
|
border: 'none',
|
|
105171
106828
|
outline: 'none',
|
|
@@ -105176,13 +106833,13 @@ function DiffViewer({ oldText, newText }) {
|
|
|
105176
106833
|
color: 'inherit',
|
|
105177
106834
|
fontFamily: 'inherit',
|
|
105178
106835
|
}, autoFocus: true }),
|
|
105179
|
-
searchQuery && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106836
|
+
searchQuery && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_2__["default"], { variant: "caption", sx: { color: 'text.secondary', whiteSpace: 'nowrap', minWidth: 50, textAlign: 'center' } }, totalMatches > 0 ? `${currentMatch + 1} / ${totalMatches}` : 'нет')),
|
|
105180
106837
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_4__["default"], { size: "small", onClick: () => navigateMatch(-1), disabled: totalMatches === 0, sx: { p: 0.3 } },
|
|
105181
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106838
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_31__["default"], { sx: { fontSize: 18 } })),
|
|
105182
106839
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_4__["default"], { size: "small", onClick: () => navigateMatch(1), disabled: totalMatches === 0, sx: { p: 0.3 } },
|
|
105183
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106840
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_30__["default"], { sx: { fontSize: 18 } })),
|
|
105184
106841
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_4__["default"], { size: "small", onClick: () => { setSearchOpen(false); setSearchQuery(''); }, sx: { p: 0.3 } },
|
|
105185
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106842
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_26__["default"], { sx: { fontSize: 18 } })))),
|
|
105186
106843
|
!searchOpen && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_4__["default"], { size: "small", onClick: () => { setSearchOpen(true); setTimeout(() => searchInputRef.current?.focus(), 50); }, sx: {
|
|
105187
106844
|
position: 'absolute',
|
|
105188
106845
|
top: 28,
|
|
@@ -105193,11 +106850,11 @@ function DiffViewer({ oldText, newText }) {
|
|
|
105193
106850
|
bgcolor: 'background.paper',
|
|
105194
106851
|
boxShadow: 1,
|
|
105195
106852
|
} },
|
|
105196
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106853
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_34__["default"], { sx: { fontSize: 16 } }))),
|
|
105197
106854
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { direction: "row", spacing: 1, sx: { mb: 1 }, alignItems: "center" },
|
|
105198
106855
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_7__["default"], { label: `+${stats.added}`, size: "small", sx: { bgcolor: '#e6ffec', color: '#1a7f37', fontWeight: 'bold', fontFamily: 'monospace' } }),
|
|
105199
106856
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_7__["default"], { label: `−${stats.removed}`, size: "small", sx: { bgcolor: '#ffebe9', color: '#cf222e', fontWeight: 'bold', fontFamily: 'monospace' } })),
|
|
105200
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
106857
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_3__["default"], { ref: tableRef, variant: "outlined", sx: {
|
|
105201
106858
|
overflow: 'auto',
|
|
105202
106859
|
maxHeight: 500,
|
|
105203
106860
|
fontFamily: '"SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace',
|
|
@@ -105262,20 +106919,33 @@ function PromptManagerDialog({ open, onClose }) {
|
|
|
105262
106919
|
// selectedApproaches: array of indices from PAIR_APPROACH_POOL, ordered
|
|
105263
106920
|
const [selectedApproaches, setSelectedApproaches] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)([0, 1, 2]);
|
|
105264
106921
|
// imageApproachCounts: по одному на каждый подход (CREO_APPROACHES), каждый 0–4
|
|
105265
|
-
const [imageApproachCounts, setImageApproachCounts] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(() => Array(
|
|
106922
|
+
const [imageApproachCounts, setImageApproachCounts] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(() => Array(_prompts__WEBPACK_IMPORTED_MODULE_36__.CREO_APPROACHES.length).fill(1));
|
|
106923
|
+
const [creoToastOpen, setCreoToastOpen] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false);
|
|
106924
|
+
const [creoToastMessage, setCreoToastMessage] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)('');
|
|
106925
|
+
const creoToastDebounceRef = react__WEBPACK_IMPORTED_MODULE_0___default().useRef(null);
|
|
105266
106926
|
// Загрузить оверрайды при открытии
|
|
105267
106927
|
(0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
|
|
105268
106928
|
if (open) {
|
|
105269
|
-
const loaded = (0,
|
|
106929
|
+
const loaded = (0,_promptOverrides__WEBPACK_IMPORTED_MODULE_38__.loadPromptOverrides)();
|
|
105270
106930
|
setOverrides(loaded);
|
|
105271
|
-
setSelectedApproaches((0,
|
|
105272
|
-
setImageApproachCounts((0,
|
|
106931
|
+
setSelectedApproaches((0,_promptOverrides__WEBPACK_IMPORTED_MODULE_38__.getSelectedPairApproaches)());
|
|
106932
|
+
setImageApproachCounts((0,_promptOverrides__WEBPACK_IMPORTED_MODULE_38__.getImageApproachCounts)());
|
|
105273
106933
|
setHasChanges(false);
|
|
105274
106934
|
}
|
|
105275
106935
|
}, [open]);
|
|
105276
106936
|
const handleTabChange = (_event, newValue) => {
|
|
105277
106937
|
setTabValue(newValue);
|
|
105278
106938
|
};
|
|
106939
|
+
const showCreoTotalToast = (pairsCount, imageCount) => {
|
|
106940
|
+
const imageAspectRatio = localStorage.getItem('imageAspectRatio') || '1:1';
|
|
106941
|
+
const bothMultiplier = imageAspectRatio === 'both' ? 2 : 1;
|
|
106942
|
+
const total = pairsCount * imageCount * bothMultiplier;
|
|
106943
|
+
const formula = bothMultiplier === 2
|
|
106944
|
+
? `${pairsCount} × ${imageCount} × 2 = ${total}`
|
|
106945
|
+
: `${pairsCount} × ${imageCount} = ${total}`;
|
|
106946
|
+
setCreoToastMessage(`Всего креативов: ${formula}`);
|
|
106947
|
+
setCreoToastOpen(true);
|
|
106948
|
+
};
|
|
105279
106949
|
const handlePairApproachToggle = (idx) => {
|
|
105280
106950
|
setSelectedApproaches(prev => {
|
|
105281
106951
|
let next;
|
|
@@ -105286,11 +106956,13 @@ function PromptManagerDialog({ open, onClose }) {
|
|
|
105286
106956
|
next = prev.filter(i => i !== idx);
|
|
105287
106957
|
}
|
|
105288
106958
|
else {
|
|
105289
|
-
// Select —
|
|
106959
|
+
// Select — сортировка по индексу подхода (порядок пар задаёт промпт по номерам 1…N)
|
|
105290
106960
|
next = [...prev, idx].sort((a, b) => a - b);
|
|
105291
106961
|
}
|
|
105292
106962
|
setOverrides(o => ({ ...o, selectedPairApproaches: next }));
|
|
105293
106963
|
setHasChanges(true);
|
|
106964
|
+
const imageCount = imageApproachCounts.reduce((a, b) => a + b, 0);
|
|
106965
|
+
setTimeout(() => showCreoTotalToast(next.length, imageCount), 0);
|
|
105294
106966
|
return next;
|
|
105295
106967
|
});
|
|
105296
106968
|
};
|
|
@@ -105302,9 +106974,27 @@ function PromptManagerDialog({ open, onClose }) {
|
|
|
105302
106974
|
next[idx] = clamped;
|
|
105303
106975
|
setOverrides(o => ({ ...o, imageApproachCounts: next }));
|
|
105304
106976
|
setHasChanges(true);
|
|
106977
|
+
// Debounced toast — показываем через 500ms после последнего изменения (стрелки/ввод)
|
|
106978
|
+
if (creoToastDebounceRef.current)
|
|
106979
|
+
clearTimeout(creoToastDebounceRef.current);
|
|
106980
|
+
creoToastDebounceRef.current = setTimeout(() => {
|
|
106981
|
+
creoToastDebounceRef.current = null;
|
|
106982
|
+
const pairsCount = selectedApproaches.length;
|
|
106983
|
+
const imageCount = next.reduce((a, b) => a + b, 0);
|
|
106984
|
+
showCreoTotalToast(pairsCount, imageCount);
|
|
106985
|
+
}, 500);
|
|
105305
106986
|
return next;
|
|
105306
106987
|
});
|
|
105307
106988
|
};
|
|
106989
|
+
const handleImageCountBlur = () => {
|
|
106990
|
+
if (creoToastDebounceRef.current) {
|
|
106991
|
+
clearTimeout(creoToastDebounceRef.current);
|
|
106992
|
+
creoToastDebounceRef.current = null;
|
|
106993
|
+
}
|
|
106994
|
+
const pairsCount = selectedApproaches.length;
|
|
106995
|
+
const imageCount = imageApproachCounts.reduce((a, b) => a + b, 0);
|
|
106996
|
+
showCreoTotalToast(pairsCount, imageCount);
|
|
106997
|
+
};
|
|
105308
106998
|
const handleToggleOverride = (promptName, enabled) => {
|
|
105309
106999
|
setOverrides(prev => {
|
|
105310
107000
|
const prevOverride = prev[promptName];
|
|
@@ -105355,14 +107045,15 @@ function PromptManagerDialog({ open, onClose }) {
|
|
|
105355
107045
|
else {
|
|
105356
107046
|
console.log(debugMsg, overrides);
|
|
105357
107047
|
}
|
|
105358
|
-
(0,
|
|
107048
|
+
(0,_promptOverrides__WEBPACK_IMPORTED_MODULE_38__.savePromptOverrides)(overrides);
|
|
107049
|
+
window.dispatchEvent(new Event(_promptOverrides__WEBPACK_IMPORTED_MODULE_38__.PROMPT_OVERRIDES_SAVED_EVENT));
|
|
105359
107050
|
setHasChanges(false);
|
|
105360
107051
|
onClose();
|
|
105361
107052
|
};
|
|
105362
107053
|
const handleCancel = () => {
|
|
105363
107054
|
if (hasChanges) {
|
|
105364
107055
|
if (window.confirm('Есть несохраненные изменения. Закрыть без сохранения?')) {
|
|
105365
|
-
setOverrides((0,
|
|
107056
|
+
setOverrides((0,_promptOverrides__WEBPACK_IMPORTED_MODULE_38__.loadPromptOverrides)());
|
|
105366
107057
|
setHasChanges(false);
|
|
105367
107058
|
onClose();
|
|
105368
107059
|
}
|
|
@@ -105376,25 +107067,25 @@ function PromptManagerDialog({ open, onClose }) {
|
|
|
105376
107067
|
const getOriginalPrompt = (promptName) => {
|
|
105377
107068
|
switch (promptName) {
|
|
105378
107069
|
case 'getPairsSystemPrompt':
|
|
105379
|
-
return (0,
|
|
107070
|
+
return (0,_prompts__WEBPACK_IMPORTED_MODULE_36__.getPairsSystemPrompt)('${geo}', true, selectedApproaches.length, selectedApproaches);
|
|
105380
107071
|
case 'getPairsUserPrompt':
|
|
105381
|
-
return (0,
|
|
107072
|
+
return (0,_prompts__WEBPACK_IMPORTED_MODULE_36__.getPairsUserPrompt)('${product}', '${geo}', '${additionalInfo}', true, selectedApproaches.length, selectedApproaches);
|
|
105382
107073
|
case 'getTitlesSystemPrompt':
|
|
105383
|
-
return (0,
|
|
107074
|
+
return (0,_prompts__WEBPACK_IMPORTED_MODULE_36__.getTitlesSystemPrompt)('${geo}', true, selectedApproaches.length);
|
|
105384
107075
|
case 'getTextsSystemPrompt':
|
|
105385
|
-
return (0,
|
|
107076
|
+
return (0,_prompts__WEBPACK_IMPORTED_MODULE_36__.getTextsSystemPrompt)('${geo}', true, selectedApproaches.length);
|
|
105386
107077
|
case 'getUserPrompt':
|
|
105387
|
-
return (0,
|
|
107078
|
+
return (0,_prompts__WEBPACK_IMPORTED_MODULE_36__.getUserPrompt)('${product}', '${geo}', '${additionalInfo}', 'titles', true, selectedApproaches.length);
|
|
105388
107079
|
case 'getImageCheckPrompt':
|
|
105389
|
-
return (0,
|
|
107080
|
+
return (0,_prompts__WEBPACK_IMPORTED_MODULE_36__.getImageCheckPrompt)('${product}', '${geo}', true);
|
|
105390
107081
|
case 'getValidationPrompt':
|
|
105391
|
-
return (0,
|
|
107082
|
+
return (0,_prompts__WEBPACK_IMPORTED_MODULE_36__.getValidationPrompt)('${product}', '${geo}', ['keyword1', 'keyword2'], '${approachName}', true, 'Новая по брифу: 29 EUR; старая (2×): 58 EUR — в рантайме подставляется из поля цены; в кастомном промпте плейсхолдер ${priceBrief}');
|
|
105392
107083
|
case 'getImageGenerationBasePrompt':
|
|
105393
|
-
return (0,
|
|
107084
|
+
return (0,_prompts__WEBPACK_IMPORTED_MODULE_36__.getImageGenerationBasePrompt)('${generateGeo}', '${generatePrice}', '${generateCurrency}', true);
|
|
105394
107085
|
case 'getLandingPageSystemPrompt':
|
|
105395
|
-
return (0,
|
|
107086
|
+
return (0,_landingPrompts__WEBPACK_IMPORTED_MODULE_37__.getLandingPageSystemPrompt)(true);
|
|
105396
107087
|
case 'getLandingPageUserPrompt':
|
|
105397
|
-
return (0,
|
|
107088
|
+
return (0,_landingPrompts__WEBPACK_IMPORTED_MODULE_37__.getLandingPageUserPrompt)('${product}', '${geo}', true);
|
|
105398
107089
|
default:
|
|
105399
107090
|
return '';
|
|
105400
107091
|
}
|
|
@@ -105416,18 +107107,18 @@ function PromptManagerDialog({ open, onClose }) {
|
|
|
105416
107107
|
enabled && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null,
|
|
105417
107108
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_10__["default"], { size: "small", value: viewMode, exclusive: true, onChange: (_, val) => val && setViewModes(prev => ({ ...prev, [viewModeKey]: val })) },
|
|
105418
107109
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_11__["default"], { value: "edit" },
|
|
105419
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
107110
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_28__["default"], { sx: { fontSize: 16, mr: 0.5 } }),
|
|
105420
107111
|
" \u0420\u0435\u0434\u0430\u043A\u0442\u043E\u0440"),
|
|
105421
107112
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_11__["default"], { value: "diff" },
|
|
105422
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
107113
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_27__["default"], { sx: { fontSize: 16, mr: 0.5 } }),
|
|
105423
107114
|
" Diff")),
|
|
105424
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_12__["default"], { size: "small", startIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
105425
|
-
description && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
107115
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_12__["default"], { size: "small", startIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_32__["default"], null), onClick: () => handleResetPrompt(promptName) }, "\u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C")))),
|
|
107116
|
+
description && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_2__["default"], { variant: "body2", color: "text.secondary", sx: { mb: 1 } }, description)),
|
|
105426
107117
|
enabled && viewMode === 'diff' ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(DiffViewer, { oldText: originalPrompt, newText: customPrompt })) : (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(SearchableTextField, { rows: 15, value: displayPrompt, onChange: (e) => handlePromptChange(promptName, e.target.value), disabled: !enabled, placeholder: enabled ? 'Введите кастомный промпт' : 'Включите переключатель для редактирования', helperText: !enabled ? 'Это оригинальный промпт. Включите переключатель выше для редактирования.' : undefined }))));
|
|
105427
107118
|
};
|
|
105428
107119
|
// Управление подходами для изображений
|
|
105429
107120
|
const handleApproachToggle = (approachName, enabled) => {
|
|
105430
|
-
const originalApproach =
|
|
107121
|
+
const originalApproach = _prompts__WEBPACK_IMPORTED_MODULE_36__.CREO_APPROACHES.find(a => a.name === approachName);
|
|
105431
107122
|
if (!originalApproach)
|
|
105432
107123
|
return;
|
|
105433
107124
|
setOverrides(prev => {
|
|
@@ -105477,8 +107168,8 @@ function PromptManagerDialog({ open, onClose }) {
|
|
|
105477
107168
|
return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_13__["default"], { open: open, onClose: handleCancel, maxWidth: "lg", fullWidth: true },
|
|
105478
107169
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_14__["default"], null,
|
|
105479
107170
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { direction: "row", spacing: 2, alignItems: "center" },
|
|
105480
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
105481
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
107171
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_35__["default"], null),
|
|
107172
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_2__["default"], { variant: "h6" }, "\u0423\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u0435 \u043F\u0440\u043E\u043C\u043F\u0442\u0430\u043C\u0438"),
|
|
105482
107173
|
hasChanges && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_7__["default"], { label: "\u0415\u0441\u0442\u044C \u043D\u0435\u0441\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u043D\u044B\u0435 \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F", color: "warning", size: "small" })))),
|
|
105483
107174
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_15__["default"], null,
|
|
105484
107175
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_16__["default"], { value: tabValue, onChange: handleTabChange, sx: { borderBottom: 1, borderColor: 'divider' } },
|
|
@@ -105489,9 +107180,41 @@ function PromptManagerDialog({ open, onClose }) {
|
|
|
105489
107180
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(TabPanel, { value: tabValue, index: 0 },
|
|
105490
107181
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_1__["default"], { sx: { mb: 3, p: 2, border: '1px solid', borderColor: 'divider', borderRadius: 1 } },
|
|
105491
107182
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { direction: "row", spacing: 2, alignItems: "center", sx: { mb: 1.5 } },
|
|
105492
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
107183
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_2__["default"], { variant: "subtitle1", sx: { fontWeight: 600 } }, "\u041F\u043E\u0434\u0445\u043E\u0434\u044B \u0434\u043B\u044F \u0442\u0435\u043A\u0441\u0442\u043E\u0432 (\u043F\u0430\u0440\u044B \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A + \u0442\u0435\u043A\u0441\u0442)"),
|
|
105493
107184
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_7__["default"], { label: `Выбрано: ${selectedApproaches.length}`, color: "primary", size: "small" }),
|
|
105494
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
107185
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_2__["default"], { variant: "caption", color: "text.secondary" }, "(\u043C\u0438\u043D\u0438\u043C\u0443\u043C 2, \u043C\u0430\u043A\u0441\u0438\u043C\u0443\u043C 10)")),
|
|
107186
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_2__["default"], { variant: "caption", color: "text.secondary", sx: { display: 'block', mb: 0.75 } }, "\u0422\u0438\u043F \u0442\u043E\u0432\u0430\u0440\u0430 \u2014 \u0431\u044B\u0441\u0442\u0440\u044B\u0439 \u043D\u0430\u0431\u043E\u0440 \u043F\u0430\u0440 \u0442\u0435\u043A\u0441\u0442\u043E\u0432 \u0438 \u043F\u043E\u0434\u0445\u043E\u0434\u043E\u0432 \u043A \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F\u043C (1\u201310 = \u2116 \u0441\u0442\u0440\u043E\u043A\u0438 \u0432 \u043A\u0430\u0436\u0434\u043E\u0439 \u0442\u0430\u0431\u043B\u0438\u0446\u0435):"),
|
|
107187
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { direction: "row", flexWrap: "wrap", gap: 0.75, sx: { mb: 1.5 } }, Object.entries(_promptOverrides__WEBPACK_IMPORTED_MODULE_38__.PRODUCT_TYPE_TEXT_PAIR_PRESETS).map(([label, nums]) => (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_18__["default"], { key: label, title: productTypePresetTooltip(label), placement: "top", arrow: true, enterDelay: 200, componentsProps: {
|
|
107188
|
+
tooltip: {
|
|
107189
|
+
sx: {
|
|
107190
|
+
maxWidth: 420,
|
|
107191
|
+
bgcolor: 'grey.900',
|
|
107192
|
+
color: 'common.white',
|
|
107193
|
+
border: '1px solid',
|
|
107194
|
+
borderColor: 'grey.700',
|
|
107195
|
+
'& .MuiTooltip-arrow': { color: 'grey.900' },
|
|
107196
|
+
},
|
|
107197
|
+
},
|
|
107198
|
+
} },
|
|
107199
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_12__["default"], { size: "small", variant: "outlined", color: "inherit", sx: { textTransform: 'none', fontSize: '0.8rem' }, onClick: () => {
|
|
107200
|
+
const next = (0,_promptOverrides__WEBPACK_IMPORTED_MODULE_38__.productPresetNumbersToIndices)(nums);
|
|
107201
|
+
if (next.length < 2)
|
|
107202
|
+
return;
|
|
107203
|
+
const imgNums = _promptOverrides__WEBPACK_IMPORTED_MODULE_38__.PRODUCT_TYPE_IMAGE_PRESETS[label];
|
|
107204
|
+
const nextImageCounts = imgNums
|
|
107205
|
+
? (0,_promptOverrides__WEBPACK_IMPORTED_MODULE_38__.productPresetNumbersToImageCounts)(imgNums)
|
|
107206
|
+
: Array(_prompts__WEBPACK_IMPORTED_MODULE_36__.CREO_APPROACHES.length).fill(1);
|
|
107207
|
+
setSelectedApproaches(next);
|
|
107208
|
+
setImageApproachCounts(nextImageCounts);
|
|
107209
|
+
setOverrides(o => ({
|
|
107210
|
+
...o,
|
|
107211
|
+
selectedPairApproaches: next,
|
|
107212
|
+
imageApproachCounts: nextImageCounts,
|
|
107213
|
+
}));
|
|
107214
|
+
setHasChanges(true);
|
|
107215
|
+
const imageCount = nextImageCounts.reduce((a, b) => a + b, 0);
|
|
107216
|
+
setTimeout(() => showCreoTotalToast(next.length, imageCount), 0);
|
|
107217
|
+
} }, label))))),
|
|
105495
107218
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_1__["default"], { sx: { overflowX: 'auto' } },
|
|
105496
107219
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("table", { style: { width: '100%', borderCollapse: 'collapse', fontSize: 12 } },
|
|
105497
107220
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("thead", null,
|
|
@@ -105500,7 +107223,7 @@ function PromptManagerDialog({ open, onClose }) {
|
|
|
105500
107223
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("th", { style: { textAlign: 'left', padding: '4px 8px', borderBottom: '1px solid #ccc', whiteSpace: 'nowrap', width: 140 } }, "\u0423\u0433\u043E\u043B"),
|
|
105501
107224
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("th", { style: { textAlign: 'left', padding: '4px 8px', borderBottom: '1px solid #ccc' } }, "\u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A"),
|
|
105502
107225
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("th", { style: { textAlign: 'left', padding: '4px 8px', borderBottom: '1px solid #ccc' } }, "\u0422\u0435\u043A\u0441\u0442"))),
|
|
105503
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("tbody", null,
|
|
107226
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("tbody", null, _prompts__WEBPACK_IMPORTED_MODULE_36__.PAIR_APPROACH_POOL.map((p, i) => {
|
|
105504
107227
|
const checked = selectedApproaches.includes(i);
|
|
105505
107228
|
const isLast = checked && selectedApproaches.length <= 2;
|
|
105506
107229
|
return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("tr", { key: i, onClick: () => handlePairApproachToggle(i), style: {
|
|
@@ -105512,16 +107235,16 @@ function PromptManagerDialog({ open, onClose }) {
|
|
|
105512
107235
|
transition: 'opacity 0.15s, background-color 0.15s',
|
|
105513
107236
|
} },
|
|
105514
107237
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("td", { style: { textAlign: 'center', padding: '2px 8px' } },
|
|
105515
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
107238
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_19__["default"], { checked: checked, disabled: isLast, size: "small", onClick: e => e.stopPropagation(), onChange: () => handlePairApproachToggle(i), sx: { p: 0.5 } })),
|
|
105516
107239
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("td", { style: { padding: '4px 8px', fontWeight: 500, whiteSpace: 'nowrap' } }, p.name),
|
|
105517
107240
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("td", { style: { padding: '4px 8px', color: '#777' } }, p.titleApproach),
|
|
105518
107241
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("td", { style: { padding: '4px 8px', color: '#777' } }, p.textApproach.split('\n')[0])));
|
|
105519
107242
|
}))))),
|
|
105520
107243
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_1__["default"], { sx: { mb: 3, p: 2, border: '1px solid', borderColor: 'divider', borderRadius: 1 } },
|
|
105521
107244
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { direction: "row", spacing: 2, alignItems: "center", sx: { mb: 1.5 } },
|
|
105522
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
107245
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_2__["default"], { variant: "subtitle1", sx: { fontWeight: 600 } }, "\u041F\u043E\u0434\u0445\u043E\u0434\u044B \u0434\u043B\u044F \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0439"),
|
|
105523
107246
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_7__["default"], { label: `Всего: ${imageApproachCounts.reduce((a, b) => a + b, 0)}`, color: "primary", size: "small" }),
|
|
105524
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
107247
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_2__["default"], { variant: "caption", color: "text.secondary" }, "(0\u20134 \u043D\u0430 \u043A\u0430\u0436\u0434\u044B\u0439 \u043F\u043E\u0434\u0445\u043E\u0434)")),
|
|
105525
107248
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_1__["default"], { sx: { overflowX: 'auto' } },
|
|
105526
107249
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("table", { style: { width: '100%', borderCollapse: 'collapse', fontSize: 12 } },
|
|
105527
107250
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("thead", null,
|
|
@@ -105529,14 +107252,14 @@ function PromptManagerDialog({ open, onClose }) {
|
|
|
105529
107252
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("th", { style: { textAlign: 'center', padding: '4px 8px', borderBottom: '1px solid #ccc', width: 70 } }, "\u041A\u043E\u043B-\u0432\u043E"),
|
|
105530
107253
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("th", { style: { textAlign: 'left', padding: '4px 8px', borderBottom: '1px solid #ccc', whiteSpace: 'nowrap', width: 180 } }, "\u041F\u043E\u0434\u0445\u043E\u0434"),
|
|
105531
107254
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("th", { style: { textAlign: 'left', padding: '4px 8px', borderBottom: '1px solid #ccc' } }, "\u041E\u043F\u0438\u0441\u0430\u043D\u0438\u0435"))),
|
|
105532
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("tbody", null,
|
|
107255
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("tbody", null, _prompts__WEBPACK_IMPORTED_MODULE_36__.CREO_APPROACHES.map((approach, i) => {
|
|
105533
107256
|
const count = imageApproachCounts[i] ?? 0;
|
|
105534
107257
|
return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement("tr", { key: i, style: { opacity: count > 0 ? 1 : 0.6 } },
|
|
105535
107258
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("td", { style: { textAlign: 'center', padding: '2px 8px', verticalAlign: 'middle' } },
|
|
105536
107259
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { type: "number", size: "small", value: count, onChange: (e) => {
|
|
105537
107260
|
const v = parseInt(e.target.value, 10);
|
|
105538
107261
|
handleImageApproachCountChange(i, isNaN(v) ? 0 : v);
|
|
105539
|
-
}, inputProps: { min: 0, max: 4, step: 1 }, sx: { width: 56, '& .MuiInputBase-input': { textAlign: 'center', py: 0.5 } } })),
|
|
107262
|
+
}, onBlur: handleImageCountBlur, inputProps: { min: 0, max: 4, step: 1 }, sx: { width: 56, '& .MuiInputBase-input': { textAlign: 'center', py: 0.5 } } })),
|
|
105540
107263
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("td", { style: { padding: '4px 8px', fontWeight: 500, whiteSpace: 'nowrap' } }, approach.name),
|
|
105541
107264
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement("td", { style: { padding: '4px 8px', color: '#777' } }, approach.prompt.split('\n')[0])));
|
|
105542
107265
|
}))))),
|
|
@@ -105544,46 +107267,46 @@ function PromptManagerDialog({ open, onClose }) {
|
|
|
105544
107267
|
renderPromptEditor('getPairsUserPrompt', 'Пользовательский промпт (пары)', 'Пользовательский промпт для генерации пар. Переменные: ${product}, ${geo}, ${additionalInfo}, ${count}, ${n}')),
|
|
105545
107268
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(TabPanel, { value: tabValue, index: 1 },
|
|
105546
107269
|
renderPromptEditor('getImageGenerationBasePrompt', 'Базовый промпт для изображений', 'Базовый промпт, используемый для всех подходов'),
|
|
105547
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
105548
|
-
|
|
107270
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_2__["default"], { variant: "h6", sx: { mt: 3, mb: 2 } }, "\u0420\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u0435 \u043F\u043E\u0434\u0445\u043E\u0434\u043E\u0432 \u0434\u043B\u044F \u0433\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u0438 \u043A\u0440\u0435\u0430\u0442\u0438\u0432\u043E\u0432"),
|
|
107271
|
+
_prompts__WEBPACK_IMPORTED_MODULE_36__.CREO_APPROACHES.map((approach) => {
|
|
105549
107272
|
const override = overrides.creoApproaches?.[approach.name];
|
|
105550
107273
|
const enabled = override?.enabled || false;
|
|
105551
107274
|
const approachViewKey = `approach_${approach.name}`;
|
|
105552
107275
|
const approachViewMode = viewModes[approachViewKey] || 'edit';
|
|
105553
|
-
return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
105554
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
107276
|
+
return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_20__["default"], { key: approach.name, sx: { mb: 2 } },
|
|
107277
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_21__["default"], { expandIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_29__["default"], null) },
|
|
105555
107278
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { direction: "row", spacing: 2, alignItems: "center", sx: { width: '100%', mr: 2 } },
|
|
105556
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
107279
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_2__["default"], { variant: "subtitle1" }, approach.name),
|
|
105557
107280
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_7__["default"], { label: enabled ? 'Кастомный' : 'Оригинал', color: enabled ? 'primary' : 'default', size: "small" }),
|
|
105558
|
-
enabled && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_12__["default"], { size: "small", startIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
107281
|
+
enabled && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_12__["default"], { size: "small", startIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_32__["default"], null), onClick: (e) => {
|
|
105559
107282
|
e.stopPropagation();
|
|
105560
107283
|
handleResetApproach(approach.name);
|
|
105561
107284
|
} }, "\u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C")))),
|
|
105562
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
107285
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_22__["default"], null,
|
|
105563
107286
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], { direction: "row", spacing: 2, alignItems: "center", sx: { mb: 2 } },
|
|
105564
107287
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_8__["default"], { control: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_9__["default"], { checked: enabled, onChange: (e) => handleApproachToggle(approach.name, e.target.checked) }), label: "\u0418\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u044C \u043A\u0430\u0441\u0442\u043E\u043C\u043D\u044B\u0439 \u043F\u043E\u0434\u0445\u043E\u0434" }),
|
|
105565
107288
|
enabled && (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_10__["default"], { size: "small", value: approachViewMode, exclusive: true, onChange: (_, val) => val && setViewModes(prev => ({ ...prev, [approachViewKey]: val })) },
|
|
105566
107289
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_11__["default"], { value: "edit" },
|
|
105567
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
107290
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_28__["default"], { sx: { fontSize: 16, mr: 0.5 } }),
|
|
105568
107291
|
" \u0420\u0435\u0434\u0430\u043A\u0442\u043E\u0440"),
|
|
105569
107292
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_11__["default"], { value: "diff" },
|
|
105570
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
107293
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_27__["default"], { sx: { fontSize: 16, mr: 0.5 } }),
|
|
105571
107294
|
" Diff")))),
|
|
105572
107295
|
enabled && approachViewMode === 'diff' ? (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_1__["default"], null,
|
|
105573
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
107296
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_2__["default"], { variant: "subtitle2", sx: { mb: 1 } }, "\u041F\u0440\u043E\u043C\u043F\u0442 \u043F\u043E\u0434\u0445\u043E\u0434\u0430"),
|
|
105574
107297
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(DiffViewer, { oldText: approach.prompt, newText: override?.customPrompt || approach.prompt }),
|
|
105575
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
107298
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_2__["default"], { variant: "subtitle2", sx: { mt: 2, mb: 1 } }, "\u0423\u0433\u043E\u043B \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u0430"),
|
|
105576
107299
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(DiffViewer, { oldText: approach.headlineAngle, newText: override?.customHeadlineAngle || approach.headlineAngle }),
|
|
105577
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
107300
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_2__["default"], { variant: "subtitle2", sx: { mt: 2, mb: 1 } }, "\u0424\u043E\u043A\u0443\u0441 \u043D\u0430 \u0431\u0443\u043B\u043B\u0435\u0442\u0430\u0445"),
|
|
105578
107301
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(DiffViewer, { oldText: approach.bulletsFocus, newText: override?.customBulletsFocus || approach.bulletsFocus }))) : (react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null,
|
|
105579
107302
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_1__["default"], { sx: { mb: 2 } },
|
|
105580
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
107303
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_2__["default"], { variant: "subtitle2", gutterBottom: true }, "\u041F\u0440\u043E\u043C\u043F\u0442 \u043F\u043E\u0434\u0445\u043E\u0434\u0430"),
|
|
105581
107304
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(SearchableTextField, { rows: 4, value: override?.customPrompt || approach.prompt, onChange: (e) => handleApproachFieldChange(approach.name, 'customPrompt', e.target.value), disabled: !enabled })),
|
|
105582
107305
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_1__["default"], { sx: { mb: 2 } },
|
|
105583
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
107306
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_2__["default"], { variant: "subtitle2", gutterBottom: true }, "\u0423\u0433\u043E\u043B \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u0430"),
|
|
105584
107307
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(SearchableTextField, { rows: 2, value: override?.customHeadlineAngle || approach.headlineAngle, onChange: (e) => handleApproachFieldChange(approach.name, 'customHeadlineAngle', e.target.value), disabled: !enabled })),
|
|
105585
107308
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_1__["default"], null,
|
|
105586
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
107309
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_2__["default"], { variant: "subtitle2", gutterBottom: true }, "\u0424\u043E\u043A\u0443\u0441 \u043D\u0430 \u0431\u0443\u043B\u043B\u0435\u0442\u0430\u0445"),
|
|
105587
107310
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(SearchableTextField, { rows: 2, value: override?.customBulletsFocus || approach.bulletsFocus, onChange: (e) => handleApproachFieldChange(approach.name, 'customBulletsFocus', e.target.value), disabled: !enabled })))))));
|
|
105588
107311
|
})),
|
|
105589
107312
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(TabPanel, { value: tabValue, index: 2 },
|
|
@@ -105592,9 +107315,10 @@ function PromptManagerDialog({ open, onClose }) {
|
|
|
105592
107315
|
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(TabPanel, { value: tabValue, index: 3 },
|
|
105593
107316
|
renderPromptEditor('getLandingPageSystemPrompt', 'Промпт лендинга (System)', 'Системный промпт для генерации лендинг-страниц'),
|
|
105594
107317
|
renderPromptEditor('getLandingPageUserPrompt', 'Промпт лендинга (User)', 'Пользовательский промпт для генерации лендинг-страниц'))),
|
|
105595
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
105596
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_12__["default"], { onClick: handleCancel, startIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
105597
|
-
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_12__["default"], { onClick: handleSave, variant: "contained", startIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(
|
|
107318
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_23__["default"], null,
|
|
107319
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_12__["default"], { onClick: handleCancel, startIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_25__["default"], null) }, "\u041E\u0442\u043C\u0435\u043D\u0430"),
|
|
107320
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_12__["default"], { onClick: handleSave, variant: "contained", startIcon: react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_33__["default"], null), disabled: !hasChanges }, "\u0421\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C")),
|
|
107321
|
+
react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_mui_material__WEBPACK_IMPORTED_MODULE_24__["default"], { open: creoToastOpen, autoHideDuration: 3000, onClose: () => setCreoToastOpen(false), message: creoToastMessage, anchorOrigin: { vertical: 'bottom', horizontal: 'center' } })));
|
|
105598
107322
|
}
|
|
105599
107323
|
|
|
105600
107324
|
|
|
@@ -105813,6 +107537,9 @@ const MODELS = {
|
|
|
105813
107537
|
"use strict";
|
|
105814
107538
|
__webpack_require__.r(__webpack_exports__);
|
|
105815
107539
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
107540
|
+
/* harmony export */ PRODUCT_TYPE_IMAGE_PRESETS: () => (/* binding */ PRODUCT_TYPE_IMAGE_PRESETS),
|
|
107541
|
+
/* harmony export */ PRODUCT_TYPE_TEXT_PAIR_PRESETS: () => (/* binding */ PRODUCT_TYPE_TEXT_PAIR_PRESETS),
|
|
107542
|
+
/* harmony export */ PROMPT_OVERRIDES_SAVED_EVENT: () => (/* binding */ PROMPT_OVERRIDES_SAVED_EVENT),
|
|
105816
107543
|
/* harmony export */ getCreoApproachOverride: () => (/* binding */ getCreoApproachOverride),
|
|
105817
107544
|
/* harmony export */ getImageApproachCounts: () => (/* binding */ getImageApproachCounts),
|
|
105818
107545
|
/* harmony export */ getPairsCount: () => (/* binding */ getPairsCount),
|
|
@@ -105820,6 +107547,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
105820
107547
|
/* harmony export */ getSelectedPairApproaches: () => (/* binding */ getSelectedPairApproaches),
|
|
105821
107548
|
/* harmony export */ loadOverridesFromElectron: () => (/* binding */ loadOverridesFromElectron),
|
|
105822
107549
|
/* harmony export */ loadPromptOverrides: () => (/* binding */ loadPromptOverrides),
|
|
107550
|
+
/* harmony export */ mergePromptApproachesFromDriveFile: () => (/* binding */ mergePromptApproachesFromDriveFile),
|
|
107551
|
+
/* harmony export */ normalizeImageApproachCountsFromDrive: () => (/* binding */ normalizeImageApproachCountsFromDrive),
|
|
107552
|
+
/* harmony export */ normalizeSelectedPairApproachesFromDrive: () => (/* binding */ normalizeSelectedPairApproachesFromDrive),
|
|
107553
|
+
/* harmony export */ productPresetNumbersToImageCounts: () => (/* binding */ productPresetNumbersToImageCounts),
|
|
107554
|
+
/* harmony export */ productPresetNumbersToIndices: () => (/* binding */ productPresetNumbersToIndices),
|
|
105823
107555
|
/* harmony export */ resetAllOverrides: () => (/* binding */ resetAllOverrides),
|
|
105824
107556
|
/* harmony export */ resetCreoApproachOverride: () => (/* binding */ resetCreoApproachOverride),
|
|
105825
107557
|
/* harmony export */ resetPromptOverride: () => (/* binding */ resetPromptOverride),
|
|
@@ -105831,6 +107563,50 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
105831
107563
|
* Утилиты для работы с оверрайдами промптов
|
|
105832
107564
|
*/
|
|
105833
107565
|
const STORAGE_KEY = 'promptOverrides';
|
|
107566
|
+
/** Номера 1–10 = строка в таблице подходов (PAIR_APPROACH_POOL[i] → номер i + 1). Порядок в массиве не важен — при применении сортируется по номеру строки. */
|
|
107567
|
+
const PRODUCT_TYPE_TEXT_PAIR_PRESETS = {
|
|
107568
|
+
похудалки: [1, 2, 3, 6, 10],
|
|
107569
|
+
простатит: [1, 6, 8, 10, 7],
|
|
107570
|
+
потенция: [6, 10, 8, 7, 1],
|
|
107571
|
+
диабет: [8, 1, 7, 6, 10],
|
|
107572
|
+
паразиты: [6, 1, 8, 5, 7],
|
|
107573
|
+
суставы: [1, 3, 8, 2, 7],
|
|
107574
|
+
};
|
|
107575
|
+
/** Номера 1–10 = строка в таблице подходов к изображениям (CREO_APPROACHES[i] → номер i + 1). Порядок в массиве не важен. */
|
|
107576
|
+
const PRODUCT_TYPE_IMAGE_PRESETS = {
|
|
107577
|
+
похудалки: [2, 3, 6, 8, 10],
|
|
107578
|
+
простатит: [1, 4, 5, 6, 7, 8, 9],
|
|
107579
|
+
потенция: [1, 4, 5, 6, 7, 8, 9],
|
|
107580
|
+
диабет: [1, 4, 6, 9],
|
|
107581
|
+
паразиты: [4, 5, 7, 8],
|
|
107582
|
+
суставы: [3, 4, 5, 6, 9],
|
|
107583
|
+
};
|
|
107584
|
+
/** Индексы PAIR_APPROACH_POOL (0-based), по возрастанию. */
|
|
107585
|
+
function productPresetNumbersToIndices(oneBased) {
|
|
107586
|
+
const poolLen = 10;
|
|
107587
|
+
const seen = new Set();
|
|
107588
|
+
for (const n of oneBased) {
|
|
107589
|
+
const i = n - 1;
|
|
107590
|
+
if (i >= 0 && i < poolLen)
|
|
107591
|
+
seen.add(i);
|
|
107592
|
+
}
|
|
107593
|
+
return [...seen].sort((a, b) => a - b);
|
|
107594
|
+
}
|
|
107595
|
+
/**
|
|
107596
|
+
* Пресет типа товара → массив длиной IMAGE_APPROACH_COUNT: у выбранных подходов кол-во 1, у остальных 0.
|
|
107597
|
+
*/
|
|
107598
|
+
function productPresetNumbersToImageCounts(oneBased) {
|
|
107599
|
+
const counts = Array(IMAGE_APPROACH_COUNT).fill(0);
|
|
107600
|
+
const seen = new Set();
|
|
107601
|
+
for (const n of oneBased) {
|
|
107602
|
+
const i = n - 1;
|
|
107603
|
+
if (i >= 0 && i < IMAGE_APPROACH_COUNT && !seen.has(i)) {
|
|
107604
|
+
seen.add(i);
|
|
107605
|
+
counts[i] = 1;
|
|
107606
|
+
}
|
|
107607
|
+
}
|
|
107608
|
+
return counts;
|
|
107609
|
+
}
|
|
105834
107610
|
// Debug logging — пишет в терминал Electron (или в console как fallback)
|
|
105835
107611
|
function _debugLog(...args) {
|
|
105836
107612
|
const api = typeof window !== 'undefined' ? window.electronAPI : null;
|
|
@@ -105864,6 +107640,34 @@ function getPairsCount() {
|
|
|
105864
107640
|
}
|
|
105865
107641
|
/** Количество подходов для изображений. Должно совпадать с CREO_APPROACHES.length в prompts.ts */
|
|
105866
107642
|
const IMAGE_APPROACH_COUNT = 10;
|
|
107643
|
+
const PAIR_APPROACH_POOL_LEN = 10;
|
|
107644
|
+
/** Нормализация индексов пар из JSON с диска (0-based, уникальные, отсортированные, минимум 2). */
|
|
107645
|
+
function normalizeSelectedPairApproachesFromDrive(raw) {
|
|
107646
|
+
if (!Array.isArray(raw))
|
|
107647
|
+
return null;
|
|
107648
|
+
const seen = new Set();
|
|
107649
|
+
for (const x of raw) {
|
|
107650
|
+
const n = typeof x === 'number' && Number.isInteger(x) ? x : parseInt(String(x), 10);
|
|
107651
|
+
if (Number.isInteger(n) && n >= 0 && n < PAIR_APPROACH_POOL_LEN)
|
|
107652
|
+
seen.add(n);
|
|
107653
|
+
}
|
|
107654
|
+
const out = [...seen].sort((a, b) => a - b);
|
|
107655
|
+
return out.length >= 2 ? out : null;
|
|
107656
|
+
}
|
|
107657
|
+
/** Нормализация количеств крео из JSON с диска (длина 10, 0–4; хотя бы один подход > 0). */
|
|
107658
|
+
function normalizeImageApproachCountsFromDrive(raw) {
|
|
107659
|
+
if (!Array.isArray(raw))
|
|
107660
|
+
return null;
|
|
107661
|
+
const out = [];
|
|
107662
|
+
for (let i = 0; i < IMAGE_APPROACH_COUNT; i++) {
|
|
107663
|
+
const v = raw[i];
|
|
107664
|
+
const n = typeof v === 'number' && Number.isFinite(v) ? v : parseInt(String(v), 10);
|
|
107665
|
+
out.push(Number.isFinite(n) ? Math.max(0, Math.min(4, Math.round(n))) : 0);
|
|
107666
|
+
}
|
|
107667
|
+
if (out.every(c => c === 0))
|
|
107668
|
+
return null;
|
|
107669
|
+
return out;
|
|
107670
|
+
}
|
|
105867
107671
|
/**
|
|
105868
107672
|
* Получить количество изображений по каждому подходу (N элементов, 0–4).
|
|
105869
107673
|
* По умолчанию — по 1 на каждый подход.
|
|
@@ -105929,6 +107733,32 @@ function savePromptOverrides(overrides) {
|
|
|
105929
107733
|
console.error('Failed to save prompt overrides:', err);
|
|
105930
107734
|
}
|
|
105931
107735
|
}
|
|
107736
|
+
/** Имя события после сохранения подходов в менеджере промптов — чтобы синхронизировать JSON на Drive. */
|
|
107737
|
+
const PROMPT_OVERRIDES_SAVED_EVENT = 'docs-combiner-prompt-overrides-saved';
|
|
107738
|
+
/**
|
|
107739
|
+
* Подмешать в localStorage выбранные подходы из project-settings.json на Drive (если поля валидны).
|
|
107740
|
+
*/
|
|
107741
|
+
function mergePromptApproachesFromDriveFile(loadedData) {
|
|
107742
|
+
const pairs = normalizeSelectedPairApproachesFromDrive(loadedData.selectedPairApproaches);
|
|
107743
|
+
const counts = normalizeImageApproachCountsFromDrive(loadedData.imageApproachCounts);
|
|
107744
|
+
if (!pairs && !counts)
|
|
107745
|
+
return false;
|
|
107746
|
+
const overrides = loadPromptOverrides();
|
|
107747
|
+
let dirty = false;
|
|
107748
|
+
if (pairs) {
|
|
107749
|
+
overrides.selectedPairApproaches = pairs;
|
|
107750
|
+
dirty = true;
|
|
107751
|
+
}
|
|
107752
|
+
if (counts) {
|
|
107753
|
+
overrides.imageApproachCounts = counts;
|
|
107754
|
+
dirty = true;
|
|
107755
|
+
}
|
|
107756
|
+
if (dirty) {
|
|
107757
|
+
savePromptOverrides(overrides);
|
|
107758
|
+
return true;
|
|
107759
|
+
}
|
|
107760
|
+
return false;
|
|
107761
|
+
}
|
|
105932
107762
|
/**
|
|
105933
107763
|
* Получить оверрайд для простого промпта
|
|
105934
107764
|
*/
|
|
@@ -106123,58 +107953,57 @@ function _debugLog(...args) {
|
|
|
106123
107953
|
const PAIR_APPROACH_POOL = [
|
|
106124
107954
|
{
|
|
106125
107955
|
name: 'болевая точка',
|
|
106126
|
-
titleApproach: '
|
|
106127
|
-
textApproach: '
|
|
107956
|
+
titleApproach: 'одна ясная боль (не две проблемы в одном заголовке). Усиливай через несправедливость / ощущение «так несправедливо» (устал бороться, снова срыв, тело не слушается) — не только сухое перечисление симптомов. ЗАГОЛОВОК = КОНСТАТАЦИЯ, не вопрос: ЗАПРЕЩЕНО заканчивать на «почему?», «perché?», «why?» и подобное — боль называешь фактом, не спрашиваешь',
|
|
107957
|
+
textApproach: 'Одна центральная проблема за текст — не распыляйся на несколько болей. ЗАПРЕЩЕНО перечислять ингредиенты, состав, matcha/MCT/«формулу» — это территория «авторитет/экспертиза», не болевой точки. Опиши дискомфорт и как продукт снимает именно эту боль; без каталога компонентов.',
|
|
106128
107958
|
},
|
|
106129
107959
|
{
|
|
106130
107960
|
name: 'трансформация до/после',
|
|
106131
|
-
titleApproach: 'контраст
|
|
106132
|
-
textApproach: '
|
|
107961
|
+
titleApproach: 'контраст СОСТОЯНИЙ и ощущений до/после (вздутие/усталость → лёгкость, тяжесть → контроль, «не узнаю себя в зеркале» → спокойствие) с якорем во времени во фразе, но БЕЗ цифр на весах. ЗАПРЕЩЕНО в заголовке: −X kg, «persi N kg», весы, любой явный минус килограммов — это только у testimonial',
|
|
107962
|
+
textApproach: 'СТРОГО от первого лица («Я / Io / Yo…»). Это не отзыв с именем — это МОЙ контраст «как было плохо / как стало лучше» по телу и эмоциям. ЗАПРЕЩЕНО копировать формат отзыва: не начинай как реклама «я попробовала продукт и минус X кг» подряд; сначала ощущения и жизнь до/после, продукт — связка, а не пересказ цифр с весов (цифры веса допустимы в тексте лишь второстепенно, если уместно; акцент — на смене состояния). ЗАПРЕЩЕНО соцдоказательство («многие отмечают», «molte persone»).',
|
|
106133
107963
|
},
|
|
106134
107964
|
{
|
|
106135
107965
|
name: 'testimonial',
|
|
106136
107966
|
isTestimonial: true,
|
|
106137
|
-
titleApproach: '
|
|
106138
|
-
textApproach:
|
|
106139
|
-
*
|
|
106140
|
-
*
|
|
106141
|
-
*
|
|
106142
|
-
* Конкретный результат с таймингом (7–14 дней; примеры: «Po 7 dniach...», «Después de 2 semanas...»)
|
|
107967
|
+
titleApproach: 'короткая «живая» фраза с конкретикой результата на весах/сроке («−2,8 kg in 10 giorni… incredibile 😅») — здесь УМЕСТНЫ −кг и срок; это отличает testimonial от «трансформации». НЕ используй «Имя, возраст:» в заголовке — только в тексте',
|
|
107968
|
+
textApproach: `Это единственный подход-ОТЗЫВ: читатель должен поверить в реального человека.
|
|
107969
|
+
* Обязательно начало текста с «Имя, возраст:» («Giulia, 49 anni:», «Kasia, 41 lat:»)
|
|
107970
|
+
* История только от первого лица после имени
|
|
107971
|
+
* Конкретный результат с таймингом (7–14 дней), можно килограммы и детали быта
|
|
106143
107972
|
* Заканчивается приглашением попробовать + CTA`,
|
|
106144
107973
|
},
|
|
106145
107974
|
{
|
|
106146
107975
|
name: 'срочность/дефицит',
|
|
106147
|
-
titleApproach: '
|
|
107976
|
+
titleApproach: 'ТОЛЬКО дефицит оффера: время до конкретного дедлайна, остаток штук, «до полуночи», «осталось N упаковок» — ЗАПРЕЩЕНО в заголовке проблема, тело, продукт, «лишние кг», категория товара. Не баннер магазина — конкретная граница (день, час, число мест)',
|
|
106148
107977
|
textApproach: 'Начни с конкретного сигнала ограниченности — времени или количества («Tylko dziś», «Últimas unidades», «Осталось 12 упаковок», «Акция до конца дня»). Весь текст строится ИСКЛЮЧИТЕЛЬНО вокруг дефицита или дедлайна: осталось мало, время заканчивается, потом будет дороже или не будет вообще. ЗАПРЕЩЕНО упоминать состав, ингредиенты, свойства или пользу продукта — только ограниченность оффера. CTA максимально срочный.',
|
|
106149
107978
|
},
|
|
106150
107979
|
{
|
|
106151
107980
|
name: 'социальное доказательство',
|
|
106152
|
-
titleApproach: '
|
|
107981
|
+
titleApproach: 'одна ЧИТАЕМАЯ фраза с крупной цифрой (например «50.000 italiane hanno già scelto … 🔥») — грамматика и смысл на языке GEO должны сходиться; читатель понимает фразу с первого раза. ЗАПРЕЩЕНО несвязные склейки («9 su 10 scelgono controllo 🔥 fame») и обрывки, где цифра + существительные не составляют нормального высказывания',
|
|
106153
107982
|
textApproach: 'Начни с цифры или массового факта («Уже 50 000 клиентов», «9 din 10 femei observă diferența»). Акцент на том, что проблему уже решили тысячи — и ты тоже можешь.',
|
|
106154
107983
|
},
|
|
106155
107984
|
{
|
|
106156
107985
|
name: 'любопытство/интрига',
|
|
106157
|
-
titleApproach: '
|
|
107986
|
+
titleApproach: 'провокационный вопрос или утверждение, которое ломает сразу ДВА привычных решения (диета И спорт / dieta e palestra…), — но ОДНОЙ ЦЕЛЬНОЙ фразой: связный синтаксис, без рубки на обрывки через запятую и эмодзи посередине. Пример уровня: «Dieta e palestra ma la pancia resta? 🤔» — а не три оторванных куска',
|
|
106158
107987
|
textApproach: 'Начни с провокационного вопроса или неожиданного инсайта («Знаете, почему обычные средства не помогают?», «¿Sabías que…?»). Раскрой неочевидный факт о проблеме или механизме решения и выведи к продукту.',
|
|
106159
107988
|
},
|
|
106160
107989
|
{
|
|
106161
107990
|
name: 'авторитет/экспертиза',
|
|
106162
|
-
titleApproach: '
|
|
107991
|
+
titleApproach: 'information gap: в заголовке ЗАПРЕЩЕНО называть ингредиенты и раскрывать метод/механизм напрямую — никаких matcha, MCT, tè verde, «formula con…», «metodo naturale per…», «accelerare il metabolismo», «supporta il metabolismo» и т.п.; иначе ответ уже в заголовке и клик не нужен. Подай состав или подход как тайну / открытие / «что скрывают» / «почему это не то же самое, что обычные средства» — без конкретики, ответ только в основном тексте. ЗАПРЕЩЕНЫ эмодзи-подсказки по составу (например 🍵, если по смыслу выдаёт чай), если они заменяют то, что должен открыть текст. Не закрывай интригу формулировками уровня «Perché X e Y supportano…»',
|
|
106163
107992
|
textApproach: 'Начни с ФАКТА/утверждения об экспертизе («Włoska receptura», «Hecho en Italia», «3 składniki naturalne», «Разработано фармацевтами»). Акцент на составе, происхождении или механизме действия. Почему это работает — объясни просто и убедительно.',
|
|
106164
107993
|
},
|
|
106165
107994
|
{
|
|
106166
107995
|
name: 'страх бездействия',
|
|
106167
|
-
titleApproach: '
|
|
106168
|
-
textApproach: 'Начни с описания негативного сценария бездействия («С каждым днём становится хуже…», «Если не взять под контроль сейчас…»). Покажи, что проблема прогрессирует. CTA —
|
|
107996
|
+
titleApproach: 'узнаваемый паттерн промедления — ОДНА СВЯЗНАЯ фраза (допустимы многоточие, союз «но», тире), а не перечень обрывков через запятую. Пример уровня: «Rimandi a lunedì… ma la fame non aspetta 😣» — смысл течёт от начала к концу',
|
|
107997
|
+
textApproach: 'Начни с описания негативного сценария бездействия («С каждым днём становится хуже…», «Если не взять под контроль сейчас…»). Покажи, что проблема прогрессирует. Финальный CTA — ТОЛЬКО про заботу о себе / начать сейчас / не откладывать (на языке GEO). ЗАПРЕЩЕНЫ прямые призывы к заказу в финале: «ordina ora», «закажи», «купи сейчас», «clicca e acquista» — вместо них: взять под контроль, сделать первый шаг, начать сегодня и т.п.',
|
|
106169
107998
|
},
|
|
106170
107999
|
{
|
|
106171
108000
|
name: 'прямой оффер/выгода',
|
|
106172
|
-
titleApproach: 'конкретная числовая выгода в заголовке — сколько экономишь или что получаешь (например «-50%», «Вторая упаковка бесплатно», «Цена как раньше»). НЕ просто «скидка есть» — а ЧТО именно и
|
|
108001
|
+
titleApproach: 'конкретная числовая выгода в заголовке — сколько экономишь или что получаешь (например «-50%», «Вторая упаковка бесплатно», «Цена как раньше»). НЕ просто «скидка есть» — а ЧТО именно и сколько. ОБЯЗАТЕЛЬНО минимум один эмодзи в заголовке (💸 🔥 ✨ 🎁 ⏳ 📦 и т.п.) — как у остальных подходов в наборе, без эмодзи заголовок считается ошибкой',
|
|
106173
108002
|
textApproach: 'Аудитория уже думает о покупке — текст снимает последнее сомнение, а не убеждает в проблеме. Начни с оффера числом: скидка -50%, конкретная цена, что получаешь за эти деньги. Ответь на вопрос «почему взять сейчас, а не завтра» — цена вырастет, акция закончится, запас ограничен. ЗАПРЕЩЕНО объяснять пользу продукта или описывать проблему — читатель уже всё знает. Только сделка, только экономика, только CTA с акцентом на выгоде прямо сейчас.',
|
|
106174
108003
|
},
|
|
106175
108004
|
{
|
|
106176
108005
|
name: 'ситуационный/узнаваемый момент',
|
|
106177
|
-
titleApproach: '
|
|
108006
|
+
titleApproach: 'одна яркая узнаваемая сцена в 1–2 коротких связных сегментах (лучше одна картинка), без перечня симптомов через запятую. Пример уровня: «Dopo pranzo i pantaloni tirano 😩» — сразу видно момент и боль; ЗАПРЕЩЕНО нагромождать «после обеда 😩 джинсы, живот, тесно» отдельными ярлыками',
|
|
106178
108007
|
textApproach: 'Начни с конкретной жизненной сцены, где проблема ощущается («[ключевой симптом категории продукта]…», «Вечером перед сном не можешь уснуть из-за дискомфорта…» — адаптируй под категорию). Создай узнаваемую ситуацию — читатель должен сказать «это про меня» — и предложи решение.',
|
|
106179
108008
|
},
|
|
106180
108009
|
];
|
|
@@ -106379,6 +108208,12 @@ function getPairsSystemPrompt(geo, noOverride, count = 3, selectedIndices) {
|
|
|
106379
108208
|
const distributionLines = pairs
|
|
106380
108209
|
.map((p, i) => `Пара ${i + 1} → [${p.name}]:\n Заголовок: ${p.titleApproach}\n Текст: ${p.textApproach}`)
|
|
106381
108210
|
.join('\n');
|
|
108211
|
+
const hasUrgencyScarcity = pairs.some(p => p.name === 'срочность/дефицит');
|
|
108212
|
+
const hasFearInaction = pairs.some(p => p.name === 'страх бездействия');
|
|
108213
|
+
const hasSocialProof = pairs.some(p => p.name === 'социальное доказательство');
|
|
108214
|
+
const hasAuthorityExpertise = pairs.some(p => p.name === 'авторитет/экспертиза');
|
|
108215
|
+
const hasDirectOffer = pairs.some(p => p.name === 'прямой оффер/выгода');
|
|
108216
|
+
const hasTransformAndTestimonial = pairs.some(p => p.name === 'трансформация до/после') && pairs.some(p => p.isTestimonial);
|
|
106382
108217
|
const deadlineNote = n >= 2
|
|
106383
108218
|
? `- В Тексте 1 ИЛИ Тексте 2 ОБЯЗАТЕЛЬНО укажи ожидаемый срок результата 7–14 дней (на языке ${geo}).`
|
|
106384
108219
|
: `- В Тексте 1 ОБЯЗАТЕЛЬНО укажи ожидаемый срок результата 7–14 дней (на языке ${geo}).`;
|
|
@@ -106393,6 +108228,11 @@ function getPairsSystemPrompt(geo, noOverride, count = 3, selectedIndices) {
|
|
|
106393
108228
|
|
|
106394
108229
|
... и так для всех ${n} пар. Каждая пара отделена пустой строкой.
|
|
106395
108230
|
|
|
108231
|
+
КРИТИЧНО ДЛЯ РАЗБОРА:
|
|
108232
|
+
- Служебные метки в начале строки пиши РОВНО как в примере: слово «ЗАГОЛОВОК» целиком кириллицей (не ZAG, не смесь латиницы и кириллицы), слово «ТЕКСТ» целиком кириллицей.
|
|
108233
|
+
- Не вставляй строки «ЗАГОЛОВОК N:» внутрь текста объявления; каждый заголовок — отдельная строка перед своим «ТЕКСТ N:».
|
|
108234
|
+
- Контент объявления (заголовок и текст) — на языке ${geo}; только метки ЗАГОЛОВОК/ТЕКСТ остаются кириллицей как шаблон.
|
|
108235
|
+
|
|
106396
108236
|
РАСПРЕДЕЛЕНИЕ ПОДХОДОВ ПО ПАРАМ:
|
|
106397
108237
|
${distributionLines}
|
|
106398
108238
|
|
|
@@ -106400,20 +108240,24 @@ ${distributionLines}
|
|
|
106400
108240
|
- Заголовок — короткий крючок (боль или триггер)
|
|
106401
108241
|
- Текст — раскрывает тот же угол глубже, добавляет детали, заканчивается CTA
|
|
106402
108242
|
- Текст НЕ повторяет заголовок дословно, но развивает его смысл
|
|
108243
|
+
- Не подмешивай чужие углы: например в «трансформация до/после» не используй формулировки соцдоказательства («многие отмечают», «клиенты говорят»)
|
|
108244
|
+
${hasTransformAndTestimonial ? '\n- РАЗВЕДЕНИЕ «трансформация до/после» и «testimonial» в одном ответе: у трансформации заголовок = контраст ощущений/состояния (без −кг и без «минус X kg за N дней»); у testimonial заголовок может содержать −кг, весы, срок — как убедительный отзыв. Не делай два заголовка в одном формате «цифра + срок на весах».' : ''}
|
|
106403
108245
|
|
|
106404
108246
|
ТРЕБОВАНИЯ К ЗАГОЛОВКУ:
|
|
106405
108247
|
- До 55–60 символов, максимум 6–7 слов
|
|
108248
|
+
- Цельность: заголовок читается как одно высказывание (или один связный вопрос целиком). ЗАПРЕЩЕНО склеивать несвязные ярлыки запятыми ради ключевых слов; эмодзи не должно разрывать грамматику так, что фраза перестаёт быть человеческой
|
|
106406
108249
|
- ЗАПРЕЩЕНО двоеточие (:) — используй тире (—) или переформулируй
|
|
106407
|
-
- 1–2 эмодзи естественно
|
|
106408
|
-
- Хотя бы одно ключевое слово проблемы, релевантное
|
|
106409
|
-
- НЕ упоминай название продукта — заголовок = боль +
|
|
108250
|
+
- 1–2 эмодзи естественно (часто в конце фразы или после целого смыслового блока); избегай ⚠️ и 🚨${hasDirectOffer ? '\n- Для пары «прямой оффер/выгода» эмодзи в заголовке ОБЯЗАТЕЛЕН (минимум один) — визуально вровень с остальными парами набора' : ''}
|
|
108251
|
+
- Хотя бы одно ключевое слово проблемы, релевантное продукту${hasUrgencyScarcity ? '\n- ИСКЛЮЧЕНИЕ: для пары с подходом «срочность/дефицит» в заголовке ЗАПРЕЩЕНЫ симптомы, проблема, тело, продукт — только лимит оффера (время, количество, дедлайн)' : ''}${hasAuthorityExpertise ? '\n- Пара «авторитет/экспертиза»: заголовок держит information gap — без ингредиентов и без прямого названия механизма; состав и «как это работает» — только в тексте пары' : ''}
|
|
108252
|
+
- НЕ упоминай название продукта — заголовок = боль + триггер${hasUrgencyScarcity ? ' (кроме пары «срочность/дефицит»: там заголовок = только дефицит/дедлайн, без продукта и без боли)' : ''}${hasSocialProof ? '\n- Исключение: в паре «социальное доказательство» название продукта в заголовке допустимо, если оно входит в цельную фразу про массовый выбор (например «N persone hanno già scelto [продукт]»)' : ''}
|
|
106410
108253
|
- Звучит как живая рекламная фраза, а не строка ключевых слов
|
|
106411
108254
|
|
|
106412
108255
|
ТРЕБОВАНИЯ К ТЕКСТУ:
|
|
106413
108256
|
- 150–280 символов (testimonial — до 300)
|
|
106414
|
-
- Хотя бы одно ключевое слово проблемы
|
|
106415
|
-
- Сильный явный CTA в конце («кликни», «попробуй сейчас», «закажи», «не жди»)
|
|
108257
|
+
- Хотя бы одно ключевое слово проблемы (для «срочность/дефицит» в тексте допустимо слабее, если весь фокус — на лимите оффера)
|
|
108258
|
+
- Сильный явный CTA в конце («кликни», «попробуй сейчас», «закажи», «не жди»)${hasFearInaction ? '\n- ИСКЛЮЧЕНИЕ: для пары «страх бездействия» финальная фраза — не заказ, а забота о себе / начать сейчас; без «ordina ora», «закажи», «купи», «clicca e acquista» в конце' : ''}
|
|
106416
108259
|
- Короткие рубленые фразы, императивы, FOMO допустим${hasTestimonial ? '\n- Testimonial: строго от первого лица, начинается с «Имя, возраст:», конкретный результат с таймингом' : ''}
|
|
108260
|
+
- Ингредиенты и состав из доп. информации — только в углах «авторитет/экспертиза» (и сходных); в «болевой точке» и чисто эмоциональных углах состав не перечислять
|
|
106417
108261
|
${deadlineNote}
|
|
106418
108262
|
|
|
106419
108263
|
ОБЩИЕ ТРЕБОВАНИЯ:
|
|
@@ -106472,7 +108316,9 @@ function getImageCheckPrompt(product, geo, noOverride) {
|
|
|
106472
108316
|
/**
|
|
106473
108317
|
* Промпт для валидации рекламных креативов
|
|
106474
108318
|
*/
|
|
106475
|
-
function getValidationPrompt(product, geo, keywords, approachName, noOverride
|
|
108319
|
+
function getValidationPrompt(product, geo, keywords, approachName, noOverride,
|
|
108320
|
+
/** Краткий эталон цен из приложения (новая + ожидаемая старая при -50%); пусто — без сверки чисел */
|
|
108321
|
+
priceBrief) {
|
|
106476
108322
|
if (!noOverride) {
|
|
106477
108323
|
const override = (0,_promptOverrides__WEBPACK_IMPORTED_MODULE_0__.getPromptOverride)('getValidationPrompt');
|
|
106478
108324
|
if (override?.enabled && override.customPrompt) {
|
|
@@ -106481,63 +108327,49 @@ function getValidationPrompt(product, geo, keywords, approachName, noOverride) {
|
|
|
106481
108327
|
.replace(/\$\{product\}/g, product)
|
|
106482
108328
|
.replace(/\$\{geo\}/g, geo)
|
|
106483
108329
|
.replace(/\$\{keywords\}/g, keywords.join(', '))
|
|
106484
|
-
.replace(/\$\{approachLine\}/g, approachLine)
|
|
108330
|
+
.replace(/\$\{approachLine\}/g, approachLine)
|
|
108331
|
+
.replace(/\$\{priceBrief\}/g, priceBrief?.trim() || 'В приложении бриф цены не задан — сверяй только визуально две цены и -50%.');
|
|
106485
108332
|
}
|
|
106486
108333
|
}
|
|
106487
108334
|
const approachLine = approachName?.trim() ? `\nПОДХОД: ${approachName.trim()}\n` : '\n';
|
|
106488
|
-
// Resolve no-bullets conditions in code — don't leave "if approach = X" for the LLM
|
|
106489
|
-
const noBulletsApproachNames = CREO_APPROACHES.filter(a => a.noBullets).map(a => a.name);
|
|
106490
|
-
const isNoBullets = noBulletsApproachNames.includes(approachName?.trim() ?? '');
|
|
106491
108335
|
const isScreenshotReviews = (approachName?.trim() ?? '') === 'Скрин отзывов';
|
|
106492
|
-
//
|
|
106493
|
-
const step0BulletsHint =
|
|
106494
|
-
|
|
106495
|
-
|
|
106496
|
-
|
|
106497
|
-
const
|
|
106498
|
-
|
|
106499
|
-
|
|
106500
|
-
|
|
106501
|
-
|
|
106502
|
-
|
|
106503
|
-
|
|
106504
|
-
-
|
|
106505
|
-
-
|
|
106506
|
-
-
|
|
106507
|
-
|
|
106508
|
-
|
|
106509
|
-
-
|
|
106510
|
-
-
|
|
106511
|
-
|
|
106512
|
-
|
|
106513
|
-
|
|
106514
|
-
|
|
106515
|
-
-
|
|
106516
|
-
|
|
106517
|
-
|
|
106518
|
-
|
|
106519
|
-
|
|
106520
|
-
-
|
|
106521
|
-
-
|
|
106522
|
-
|
|
106523
|
-
- По умолчанию любой другой рекламный текст (бейджи/подписи/пояснения) запрещён.
|
|
106524
|
-
- НО допускаются (не обязательно) дополнительные бейджи ВНЕ упаковки — это НЕ ошибка, если ВСЕ элементы OTHER_TEXT подпадают под разрешённые типы:
|
|
106525
|
-
A) URGENCY (0–1 шт): бейдж срочности/дефицита — только ясные формулировки («только сегодня», «последние штуки», «акция до конца дня»). ЗАПРЕЩЕНО: «24h» и подобные — непонятно что означает.
|
|
106526
|
-
B) TRUST (0–3 шт, для «Минимализм / Clean Big Text» — макс 1): печати цветные, яркие, очень похожие на печать FDA. Подчёркивают: натуральность состава, премиальность, безопасность. Допустимо: качество, натуральные ингредиенты, экологичность, контроль качества. Печати — размер как минимум как у буллитов, крупные. Даже одна печать — крупная.
|
|
106527
|
-
Правила для каждого элемента OTHER_TEXT:
|
|
106528
|
-
* строго на языке ${geo} (без английских слов)
|
|
106529
|
-
* без цены/скидки/процентов (кроме обязательного поля DISCOUNT), без доменов/ссылок
|
|
106530
|
-
* TRUST‑печати — про натуральность/премиальность/безопасность (не про доставку/поддержку)
|
|
106531
|
-
Примеры стиля (адаптируй к языку GEO, не требуются):
|
|
106532
|
-
- URGENCY: «Ostatnie sztuki», «Tylko dziś», «Koniec dziś» (НЕ «24h» — непонятно)
|
|
106533
|
-
- TRUST: «Naturalna formuła», «Wysoka jakość» (для PL); «Ingrediente naturale», «Calitate» (для RO). ЗАПРЕЩЕНО: «NATURAL», «QUALITY», «100% NATURAL» — английские слова.
|
|
106534
|
-
- Если OTHER_TEXT содержит что-то вне этих типов, или URGENCY > 1, или TRUST > 3 (для Минимализма — TRUST > 1) — ОШИБКА.`;
|
|
108336
|
+
// Буллеты валидатором не проверяются (ни количество, ни наличие)
|
|
108337
|
+
const step0BulletsHint = 'BULLETS: кратко опиши, что видишь на макете (для справки). Количество и наличие буллетов НЕ валидируются.';
|
|
108338
|
+
const step2Bullets = `ШАГ 2 — БУЛЛЕТЫ:
|
|
108339
|
+
- Не проверяй и не оценивай количество, отсутствие или наличие буллетов. 0, 1, 2, 3 и больше — всё допустимо.
|
|
108340
|
+
- НЕ добавляй в финальный список ошибок ни одного пункта, связанного с буллетами (вертикальность, «ровно 3», иконки, читаемость буллетов и т.п.).`;
|
|
108341
|
+
const priceBriefTrim = priceBrief?.trim() || '';
|
|
108342
|
+
const stepPriceBrief = priceBriefTrim
|
|
108343
|
+
? `ШАГ P — ЦЕНЫ (сначала макет, потом бриф):
|
|
108344
|
+
Эталон из приложения:
|
|
108345
|
+
${priceBriefTrim}
|
|
108346
|
+
|
|
108347
|
+
1) ВНУТРЕННЯЯ ЛОГИКА НА МАКЕТЕ (главное):
|
|
108348
|
+
- Должны быть видны две суммы: новая (акционная) и старая (зачёркнутая). Старая ≈ 2× новой при скидке -50% (допуск до ~2% из‑за округления; «1 180» и «1180» — одно и то же).
|
|
108349
|
+
- Если отношение старая/новая ≈ 2 (в пределах допуска) — это уже доказательство корректной пары -50% на макете. В этом случае ЗАПРЕЩЕНО выводить ОШИБКУ формулировками вроде «выдуманные цены», «неверные суммы», «не соответствуют брифу» — даже если цифры в брифе другие или бриф кажется не тем.
|
|
108350
|
+
- Если пара математически согласована с -50% и процент «-50%» где‑либо читаем в зоне оффера (см. ШАГ 4) — не придумывай расхождение с брифом из‑за символа валюты (€ / EUR / MXN и т.д.) или пробелов.
|
|
108351
|
+
|
|
108352
|
+
2) СВЕРКА С БРИФОМ (только когда сопоставимо):
|
|
108353
|
+
- Сравнивай число НОВОЙ цены с брифом ТОЛЬКО если валюта на макете явно та же, что в брифе (EUR↔EUR, MXN↔MXN и т.д.; символ € и код EUR — одна валюта). Допускается разное оформление числа (пробелы тысяч, запятая/точка).
|
|
108354
|
+
- Если валюта на креативе другая, чем в брифе, или не уверен в коде валюты — не требуй совпадения цифр с брифом: достаточно пункта (1).
|
|
108355
|
+
- Ошибку по ценам ставь только если: (а) на макете нет двух цен / нет согласованности -50%, ИЛИ (б) валюта однозначно совпадает с брифом, а число новой цены явно другое (не в пределах округления).
|
|
108356
|
+
|
|
108357
|
+
3) Цена не должна быть оформлена как строка буллета с галочкой — отдельный блок.`
|
|
108358
|
+
: `ШАГ P — ЦЕНЫ (бриф числом не задан):
|
|
108359
|
+
- На макете должны быть ДВЕ цены, старая зачёркнута толсто, новая выразительна; пара должна визуально соответствовать -50% (старая ≈ 2× новой). Конкретные суммы с приложением не сверяй.`;
|
|
108360
|
+
const step3OtherText = isScreenshotReviews
|
|
108361
|
+
? `ШАГ 3 — Подход «Скрин отзывов»:
|
|
108362
|
+
- Блок отзывов (аватары, имена, звёзды, текст) — это нормальный контент креатива, не считай его лишним OTHER_TEXT.`
|
|
108363
|
+
: `ШАГ 3 — Доп. текст, бейджи, печати:
|
|
108364
|
+
- Не валидируй объём текста и не отклоняй креатив за «слишком много элементов», punch vs не punch, количество плашек или пустоту OTHER_TEXT.
|
|
108365
|
+
- Не требуй отсутствия trust/urgency/подписей — для любого подхода это не ошибка.
|
|
108366
|
+
- Язык рекламного текста (включая бейджи) — по-прежнему ШАГ 5. Неясные срочности вроде «24h» — по-прежнему ШАГ 6.`;
|
|
106535
108367
|
return `Ты — СТРОГИЙ валидатор рекламных креативов (1:1). Не улучшай и не предлагай идеи — только проверка и вердикт.
|
|
106536
108368
|
Продукт: ${product}. GEO/язык: ${geo}.${approachLine}
|
|
106537
108369
|
|
|
106538
108370
|
ВАЖНО:
|
|
106539
|
-
- Проверяй язык ТОЛЬКО для рекламного текста на макете (
|
|
106540
|
-
- Если сомневаешься,
|
|
108371
|
+
- Проверяй язык ТОЛЬКО для рекламного текста на макете (заголовок/CTA/цена/скидка/разрешённые бейджи из OTHER_TEXT; если есть буллеты — и их текст). Текст на самой упаковке/этикетке игнорируй (включая название/бренд вроде "${product}").
|
|
108372
|
+
- Если сомневаешься, мелкий текст на банке — этикетка или нет: для языка считай этикеткой и не валидируй. Исключение: **нижний оффер-блок** макета (две цены, зачёркивание, «-50%», кнопка CTA в одной полосе/ряду под картинкой продукта) — это всегда рекламный слой **вне упаковки**, даже рядом с фото банки; цены и скидку оттуда учитывай в PRICE/DISCOUNT и не считай «на упаковке».
|
|
106541
108373
|
- Если текст плохо читается/микрошрифт — это ошибка.
|
|
106542
108374
|
|
|
106543
108375
|
ШАГ 0 — Сначала выпиши распознанный текст (как ты его видишь на макете):
|
|
@@ -106547,9 +108379,7 @@ PRICE: "..." (если нет — "нет")
|
|
|
106547
108379
|
DISCOUNT: "..." (если нет — "нет")
|
|
106548
108380
|
CTA: "..." (если нет — "нет")
|
|
106549
108381
|
OTHER_TEXT: ["..."] (любой другой рекламный текст на макете ВНЕ упаковки и ВНЕ элементов выше; название/бренд на упаковке НЕ включай)
|
|
106550
|
-
(
|
|
106551
|
-
URGENCY_BADGE: "..." (бейдж срочности, если есть; «24h» — ОШИБКА, непонятно что означает)
|
|
106552
|
-
TRUST_BADGES: ["..."] (печати цветные, яркие, в стиле FDA; про натуральность/премиальность/безопасность; размер как у буллитов — крупные, если есть)
|
|
108382
|
+
(опционально, для ясности): URGENCY_BADGE, TRUST_BADGES — перечисли, если есть
|
|
106553
108383
|
|
|
106554
108384
|
ШАГ 1 — HOOK/HEADLINE (критично):
|
|
106555
108385
|
- Должен быть ВЫШЕ всех элементов и читабелен (хорошо читается на телефоне)
|
|
@@ -106562,35 +108392,38 @@ TRUST_BADGES: ["..."] (печати цветные, яркие, в стиле FD
|
|
|
106562
108392
|
|
|
106563
108393
|
${step2Bullets}
|
|
106564
108394
|
|
|
108395
|
+
${stepPriceBrief}
|
|
108396
|
+
|
|
106565
108397
|
ШАГ 2.5 — CLAIMS CHECK:
|
|
106566
108398
|
- Клеймы по результату (жёсткие/абсолютные или мягкие) — НЕ проверяются и НЕ запрещаются. Не блокируй за формулировки обещаний результата.
|
|
106567
108399
|
|
|
106568
|
-
${
|
|
108400
|
+
${step3OtherText}
|
|
106569
108401
|
|
|
106570
|
-
ШАГ 4 — CTA
|
|
108402
|
+
ШАГ 4 — CTA и визуал цены/скидки (критично):
|
|
106571
108403
|
- CTA: на языке ${geo}, хорошо заметная кнопка (позиция НЕ важна: можно вправо/влево/по центру). Главное — CTA читабельна и выглядит как кнопка.
|
|
106572
|
-
-
|
|
106573
|
-
- Скидка ОБЯЗАТЕЛЬНА: «-50%»
|
|
108404
|
+
- Блок цен: две суммы, старая зачёркнута ТОЛСТОЙ линией, новая выразительно (детали и сверка чисел с брифом — в ШАГ P). Если только одна цена — ОШИБКА.
|
|
108405
|
+
- Скидка ОБЯЗАТЕЛЬНА: читаемое «-50%». **Отдельный видимый бейдж** = любая заметная плашка/круг/прямоугольник с текстом «-50%» в **той же зоне оффера**, что и цены (сбоку от сумм, над/под ценовой строкой, между ценой и CTA) — это ОК, не требуй отдельного «далёкого» элемента. «НЕ на упаковке» означает только: не напечатано на этикетке/банке товара; плашка в нижней рекламной полосе макета **не** считается упаковкой.
|
|
108406
|
+
- Если в ШАГ 0 в DISCOUNT ты указал «-50%» (или эквивалент) — ЗАПРЕЩЕНО ставить ошибку «скидка не отображается» / «нет отдельного бейджа».
|
|
106574
108407
|
- Не считать ошибкой, если скидка/цена конкурируют с CTA по акценту — это допустимо, пока CTA остаётся хорошо заметной и читабельной.
|
|
106575
108408
|
- Если скидка указана и она не равна -50% — ошибка.
|
|
106576
108409
|
|
|
106577
108410
|
ШАГ 5 — ЯЗЫК (критично):
|
|
106578
|
-
- В рекламном тексте (HOOK/HEADLINE
|
|
108411
|
+
- В рекламном тексте (HOOK/HEADLINE, текст на буллетах если есть, CTA/PRICE/DISCOUNT/OTHER_TEXT) НЕТ английских слов. Если есть — ошибка.
|
|
108412
|
+
- ЗАПРЕЩЁННЫЕ служебные подписи на макете (частая ошибка модели): слова HOOK, CTA, CAPS, BULLET, HEADLINE, PRICE, DISCOUNT как видимый текст на плашках или кнопке — ОШИБКА (это метки из брифа, не для читателя).
|
|
106579
108413
|
- Все слова соответствуют GEO/языку ${geo}. Если смешение языков — ошибка.
|
|
106580
108414
|
|
|
106581
108415
|
ШАГ 6 — КОМПОЗИЦИЯ:
|
|
106582
108416
|
- Если креатив без человека (lifestyle/clean), проверь наличие контекста использования (кухня, стол, тумбочка, и т.д.). Продукт на полностью пустом/белом фоне без контекста — РЕКОМЕНДАЦИЯ к улучшению (не критичная ошибка, но слабый визуал)
|
|
106583
|
-
- КОНТРАСТ ПЛАШЕК: если
|
|
106584
|
-
-
|
|
106585
|
-
- TRUST‑печати: если печати мелкие или текст нечитабелен на телефоне — ОШИБКА (
|
|
106586
|
-
- СКИДКА «-50%»:
|
|
106587
|
-
- ЦЕНА: ОБЯЗАТЕЛЬНО ДВЕ — старая зачёркнута ТОЛСТОЙ линией (не тонкой!), новая выразительно. Одна цена или тонкое зачёркивание — ОШИБКА.
|
|
108417
|
+
- КОНТРАСТ ПЛАШЕК: если HOOK, CTA или блок цен визуально сливается с фоном и текст плохо читается — это ОШИБКА. (Контраст буллетов не проверяй.)
|
|
108418
|
+
- Две цены и зачёркивание старой — см. ШАГ 4 и ШАГ P. Цена не должна быть оформлена как элемент списка с галочкой в стиле бенефитов.
|
|
108419
|
+
- TRUST‑печати: если печати мелкие или текст нечитабелен на телефоне — ОШИБКА (должны быть крупными).
|
|
108420
|
+
- СКИДКА «-50%»: как в ШАГ 4 — плашка рядом с ценами в оффер-блоке засчитывается; если DISCOUNT в ШАГ 0 заполнен — не дублируй ошибку про бейдж.
|
|
106588
108421
|
- Бейджи срочности: «24h» и подобные неясные формулировки — ОШИБКА (непонятно что означает). Ясные («только сегодня», «последние штуки») — ок.
|
|
106589
108422
|
|
|
106590
108423
|
ФИНАЛ:
|
|
106591
108424
|
Выведи строго:
|
|
106592
108425
|
СТАТУС: OK / НУЖНА ПЕРЕСБОРКА
|
|
106593
|
-
Затем список ошибок, каждая строка начинается с "ОШИБКА:" (кратко, по делу). Если ошибок нет —
|
|
108426
|
+
Затем список ошибок, каждая строка начинается с "ОШИБКА:" (кратко, по делу). Одну и ту же проблему не повторяй — не больше одной строки на один тип нарушения. Если СТАТУС: НУЖНА ПЕРЕСБОРКА — ОБЯЗАТЕЛЬНО минимум одна конкретная строка "ОШИБКА: ..." (что именно не так); нельзя писать только "ОШИБКА: нет". Если ошибок нет — СТАТУС: OK и "ОШИБКА: нет".
|
|
106594
108427
|
Затем список рекомендаций (если есть), каждая строка начинается с "РЕКОМЕНДАЦИЯ:" (кратко, по делу). Если рекомендаций нет — напиши "РЕКОМЕНДАЦИЯ: нет".
|
|
106595
108428
|
Не блокируй за клеймы по результату или формулировки обещаний.`;
|
|
106596
108429
|
}
|
|
@@ -106626,6 +108459,9 @@ function getImageGenerationBasePrompt(generateGeo, generatePrice, generateCurren
|
|
|
106626
108459
|
ВАЖНО: изображение должно быть ${ratioShape} — строго соблюдай пропорции холста.
|
|
106627
108460
|
Язык текста: ${generateGeo}.
|
|
106628
108461
|
|
|
108462
|
+
🚫 СЛУЖЕБНЫЕ СЛОВА НЕ РИСОВАТЬ НА КАРТИНКЕ (КРИТИЧНО):
|
|
108463
|
+
Слова HOOK, CTA, CAPS, BULLET, HEADLINE, PRICE, DISCOUNT, BULLETS, LAYER и любые похожие английские метки из этой инструкции (в т.ч. thumb‑stop) — только для тебя; на макете их НЕТ ни на кнопке, ни на плашках, ни мелким текстом. Кнопка: только реальный призыв на языке ${generateGeo} (1–2 слова), без префикса «CTA». Заголовок: только живой текст оффера, без слова HOOK. Заголовок делай прописными буквами на языке ${generateGeo}, но не пиши на изображении слово CAPS и не подписывай блоки ярлыками.
|
|
108464
|
+
|
|
106629
108465
|
🚨 КРИТИЧНО — РЕЛЕВАНТНОСТЬ ПРОДУКТУ (читай ЭТО ПЕРВЫМ):
|
|
106630
108466
|
- Название продукта передано в начале промпта (строка «🏷️ ПРОДУКТ: ...»). Прочитай его ПРЯМО СЕЙЧАС и определи категорию.
|
|
106631
108467
|
- Категории и их проблемы: суставы/колени → боль в суставах, скованность, тугоподвижность; пищеварение → дискомфорт после еды, тяжесть; сон → бессонница, усталость; похудение → лишний вес; простата → частые позывы, дискомфорт.
|
|
@@ -106656,7 +108492,7 @@ HOOK / HEADLINE (строгое правило):
|
|
|
106656
108492
|
- 1–4 строки; до 12 слов. Без переноса внутри слова
|
|
106657
108493
|
- ОБЯЗАТЕЛЬНО содержит ключевое слово проблемы ЯВНО. Примеры по категориям: простата → простатит, простата; похудение → лишний вес, похудение; суставы → боль в суставах, колени, скованность; пищеварение → дискомфорт, вздутие, тяжесть; сон → бессонница, усталость. Без ключевого слова — ОШИБКА
|
|
106658
108494
|
- HOOK ВЫШЕ всех элементов (продукт, буллеты, CTA, цена). Самый крупный текстовый элемент на креативе
|
|
106659
|
-
- HOOK должен быть ВИЗУАЛЬНО “тяжёлым”: ОЧЕНЬ крупный, ТОЛСТЫЙ/жирный шрифт,
|
|
108495
|
+
- HOOK должен быть ВИЗУАЛЬНО “тяжёлым”: ОЧЕНЬ крупный, ТОЛСТЫЙ/жирный шрифт, весь текст заголовка ПРОПИСНЫМИ буквами на языке ${generateGeo}, на яркой контрастной плашке/подложке. Это верхний главный элемент, цепляющий внимание в ленте
|
|
106660
108496
|
- Можно (не обязательно) включить СРОК прямо в HOOK (например «7 dni», «14 dni») как триггер
|
|
106661
108497
|
- Заголовок должен быть РЕЗКИМ и призывным: короткие рубленые фразы, вопросы и предупреждения допустимы. Можно использовать обращение на «ты» (в языке GEO: «Masz…», «Twój…») и вопросительный знак
|
|
106662
108498
|
- заголовок НЕ должен быть абстрактным слоганом/лозунгом или метафорой без конкретной боли. Допускается «thumb‑stop» стиль (вызов/вопрос/предупреждение), если это конкретно и релевантно категории
|
|
@@ -106707,7 +108543,7 @@ CTA > PRICE:
|
|
|
106707
108543
|
❗ ИСКЛЮЧЕНИЕ: если 🎯 ПОДХОД = ${noBulletsCond} → цена и «-50%» могут быть более крупными и заметными, но CTA всё равно должен оставаться очень заметным и выглядеть как кнопка (не теряется на фоне)
|
|
106708
108544
|
|
|
106709
108545
|
ПОКАЗЫВАЙ ТОЛЬКО ЭТИ ТЕКСТОВЫЕ ЭЛЕМЕНТЫ:
|
|
106710
|
-
- HOOK (1–4 строки; выше всех элементов; самый крупный;
|
|
108546
|
+
- HOOK (1–4 строки; выше всех элементов; самый крупный; прописные буквы; жирный; на яркой контрастной подложке; ключевое слово проблемы явно)
|
|
106711
108547
|
- 3 буллета (крупные, с иконками/галочками ✓, на контрастных подложках, НЕ на банке/упаковке)
|
|
106712
108548
|
- Цена: ОБЯЗАТЕЛЬНО ДВЕ — старая (2×${generatePrice} ${generateCurrency}) зачёркнута ТОЛСТОЙ контрастной линией + новая ${generatePrice} ${generateCurrency} выразительно. Одна цена = ОШИБКА. Тонкая линия зачёркивания = ОШИБКА. Без слов. Не на упаковке.
|
|
106713
108549
|
- Скидка: «-50%» ОБЯЗАТЕЛЬНО отдельным видимым бейджем (не только в цене!). Процент скидки должен быть явно читаем. Ярко, заметно, строго НЕ на банке/упаковке, визуально слабее CTA
|
|
@@ -106743,11 +108579,11 @@ ANTI-TEMPLATE DIVERSITY (КРИТИЧНО):
|
|
|
106743
108579
|
* 🎯 ПОДХОД: Визуализация проблемы → Инфографика/схема: слева проблема (иконка/схема зоны тела, релевантной продукту), справа решение + продукт. HOOK сверху по центру, BULLETS справа или снизу (вертикально), CTA снизу справа, PRICE/DISCOUNT возле CTA. Trust‑печати (если есть) — компактно по низу, размер как минимум как у буллитов (крупные, читабельны на телефоне). Красный акцент только на проблеме.
|
|
106744
108580
|
* 🎯 ПОДХОД: Power / Сила решения → БЕЗ человека. ДИНАМИЧНЫЙ комикс‑кадр, диагональная композиция. Продукт как “герой” + power‑иконки (щит/молния/бёрст). HOOK сверху слева на яркой плашке, BULLETS слева ниже, CTA снизу справа, PRICE/DISCOUNT возле CTA. Trust‑печати (если есть) — компактно по низу, размер как минимум как у буллитов (крупные, читабельны на телефоне).
|
|
106745
108581
|
* 🎯 ПОДХОД: Минимализм / Clean Big Text → Белый/градиентный фон, минимум элементов. ОГРОМНЫЙ HOOK занимает верх/центр, продукт крупно (центр/право), CTA снизу по центру, PRICE/DISCOUNT рядом (слабее CTA). Trust‑печати (если есть) — размер как минимум как у буллитов, крупные и читабельные.
|
|
106746
|
-
* 🎯 ПОДХОД: Problem Visual Punch → БЕЗ человека. Яркий сплошной фон (красный/оранжевый) или агрессивный градиент. В центре КРУПНАЯ иконка/схема зоны тела, релевантной продукту (для суставов — колено; для пищеварения — желудок), с красным свечением. Продукт крупно рядом. HOOK 1–4 строки, до 12 слов, огромный
|
|
106747
|
-
* 🎯 ПОДХОД: Любительский Примитивизм → БЕЗ человека. Чёрный или кислотный сплошной фон. Продукт по центру или справа без декора. HOOK сверху — 1–4 строки, до 12 слов, крупный, грубый bold/рукописный,
|
|
108582
|
+
* 🎯 ПОДХОД: Problem Visual Punch → БЕЗ человека. Яркий сплошной фон (красный/оранжевый) или агрессивный градиент. В центре КРУПНАЯ иконка/схема зоны тела, релевантной продукту (для суставов — колено; для пищеварения — желудок), с красным свечением. Продукт крупно рядом. HOOK 1–4 строки, до 12 слов, огромный прописной текст, выше всех. БЕЗ буллитов. Две цены + «-50%» крупно и заметно. Кнопка призыва контрастная (только текст на языке ${generateGeo}, без слова CTA)
|
|
108583
|
+
* 🎯 ПОДХОД: Любительский Примитивизм → БЕЗ человека. Чёрный или кислотный сплошной фон. Продукт по центру или справа без декора. HOOK сверху — 1–4 строки, до 12 слов, крупный, грубый bold/рукописный, прописные буквы, выше всех. Крупные надписи цены/скидки вокруг продукта. Кнопка призыва — плоская, без градиентов (только короткая фраза на языке ${generateGeo}). БЕЗ буллитов, бейджей, теней, иконок.
|
|
106748
108584
|
|
|
106749
108585
|
AUTO-CHECK (перед финалом):
|
|
106750
|
-
- HOOK: 1–4 строки, до 12 слов,
|
|
108586
|
+
- HOOK: 1–4 строки, до 12 слов, прописные буквы, жирный на контрастной плашке, выше всех элементов, ключевое слово проблемы явно, язык ${generateGeo} без английских слов (включая метки HOOK/CTA/CAPS)
|
|
106751
108587
|
- Буллеты: по умолчанию ровно 3, каждый <= 4 слов, без запятых, не предложения. ИСКЛЮЧЕНИЕ: если 🎯 ПОДХОД = ${noBulletsCond} → буллетов 0 (запрещены)
|
|
106752
108588
|
- Нет лишнего текста кроме: HOOK, буллетов, цены, скидки, кнопки (+ опционально 1 бейдж срочности + опционально 1–3 trust‑печати)
|
|
106753
108589
|
- Есть скидка «-50%» (вне упаковки) и она слабее CTA
|
|
@@ -106791,37 +108627,37 @@ const CREO_APPROACHES = [
|
|
|
106791
108627
|
{
|
|
106792
108628
|
name: 'Эксперт / Авторитет',
|
|
106793
108629
|
prompt: `ЭКСПЕРТ / АВТОРИТЕТ (без человека): стиль “рекомендация эксперта”, но БЕЗ человека. Профессиональный контекст — аптечные полки на фоне / медицинский планшет / стетоскоп / рецептурный блокнот как реквизит рядом с продуктом. Продукт в центре как “рекомендованное решение”. Чистый профессиональный фон, высокий контраст. Trust‑печати (1–3 шт): цветные, яркие, очень похожие на печать FDA; подчёркивают натуральность состава, премиальность, безопасность. Размер как минимум как у буллитов — крупные, читабельны на телефоне. Даже одна печать — крупная.`,
|
|
106794
|
-
headlineAngle: `HOOK: угол «предупреждение / интрига / специалисты знают». Формат: вопрос‑предупреждение ИЛИ “специалисты знают/используют” (адаптируй под GEO). 1–4 строки, до 12 слов,
|
|
108630
|
+
headlineAngle: `HOOK: угол «предупреждение / интрига / специалисты знают». Формат: вопрос‑предупреждение ИЛИ “специалисты знают/используют” (адаптируй под GEO). 1–4 строки, до 12 слов, прописные буквы, ключевое слово проблемы явно.`,
|
|
106795
108631
|
bulletsFocus: `БУЛЛИТЫ: выбери 3 СЛУЧАЙНЫХ из пула (действие + срок + соц.доказательство/формула) в ПРОИЗВОЛЬНОМ порядке. Уникальный набор для этого подхода — не повторяй комбинации из других креативов.`
|
|
106796
108632
|
},
|
|
106797
108633
|
{
|
|
106798
108634
|
name: 'Lifestyle / Момент приёма',
|
|
106799
108635
|
prompt: `LIFESTYLE / МОМЕНТ ПРИЁМА: продукт в контексте использования (кухня/стол/спальня/тумбочка). Без человека, но с "историей" (стакан воды, чай, тарелка, будильник/часы/календарь). Срочность: реквизит (часы/таймер‑иконка) и/или опциональный urgency‑бейдж (1–3 слова) в углу кадра — только ясные формулировки («только сегодня», «последние штуки»), ЗАПРЕЩЕНО «24h». Высокий контраст, яркий акцент на продукте. Опционально: 1–3 trust‑печати по низу (цветные, яркие, очень похожие на печать FDA; натуральность/премиальность/безопасность). Размер как минимум как у буллитов — крупные, читабельны на телефоне. Даже одна печать — крупная. ВАЖНО: буллиты располагаются вертикально и всегда читабельны на экране телефона без зума — даже если уходят вбок, минимальный размер шрифта буллитов не уменьшается. Если буллиты не вмещаются сбоку с нужным шрифтом — переставь их вниз.`,
|
|
106800
|
-
headlineAngle: `HOOK: угол «цифры + срочность». Формат: число/процент + ограничение времени/“сейчас/сегодня” (адаптируй под GEO), 1–4 строки, до 12 слов,
|
|
108636
|
+
headlineAngle: `HOOK: угол «цифры + срочность». Формат: число/процент + ограничение времени/“сейчас/сегодня” (адаптируй под GEO), 1–4 строки, до 12 слов, прописные буквы, ключевое слово проблемы явно.`,
|
|
106801
108637
|
bulletsFocus: `БУЛЛИТЫ: выбери 3 СЛУЧАЙНЫХ из пула (срок + цифра + действие/формула) в ПРОИЗВОЛЬНОМ порядке. Уникальный набор — не повторяй комбинации из других креативов.`
|
|
106802
108638
|
},
|
|
106803
108639
|
{
|
|
106804
108640
|
name: 'Эмоция / Портрет',
|
|
106805
108641
|
prompt: `ЭМОЦИЯ / ПОРТРЕТ: один из двух подходов с человеком в серии. Используй максимально: ОЧЕНЬ крупный план лица (thumb‑stop), прямой взгляд в камеру, сильная эмоция облегчения/надежды (без широкой стоковой улыбки). Возраст человека подбери под категорию и ЦА продукта: по умолчанию 50–60, но для категорий с более молодой аудиторией (например похудение/фитнес) допускается 35–55. Продукт в руке на уровне лица или рядом, хорошо виден. Свет "тень → свет" на лице допустим. Минимум отвлекающих деталей, высокий контраст. Опционально: 1–3 trust‑печати по низу (цветные, яркие, очень похожие на печать FDA; натуральность/премиальность/безопасность). Размер как минимум как у буллитов — крупные, читабельны на телефоне. Даже одна печать — крупная. ИЕРАРХИЯ: лицо — главный и доминирующий визуальный элемент (верхние 2/3 кадра). Все текстовые блоки (HOOK исключение — сверху) уходят в нижнюю треть. Буллиты, цена, CTA НЕ перекрывают лицо и НЕ конкурируют с ним по визуальному весу — они заметно меньше и ниже.`,
|
|
106806
|
-
headlineAngle: `HOOK: угол «персонально на “ты” + результат/облегчение». 1–4 строки, до 12 слов,
|
|
108642
|
+
headlineAngle: `HOOK: угол «персонально на “ты” + результат/облегчение». 1–4 строки, до 12 слов, прописные буквы, ключевое слово проблемы явно. Тон максимально личный и прямой.`,
|
|
106807
108643
|
bulletsFocus: `БУЛЛИТЫ: выбери 3 СЛУЧАЙНЫХ из пула (качество жизни + действие + срок/цифра) в ПРОИЗВОЛЬНОМ порядке. Уникальный набор — не повторяй комбинации из других креативов.`
|
|
106808
108644
|
},
|
|
106809
108645
|
{
|
|
106810
108646
|
name: 'Визуализация проблемы',
|
|
106811
108647
|
prompt: `ВИЗУАЛИЗАЦИЯ ПРОБЛЕМЫ (без человека): схема/иконка проблемной зоны тела, строго соответствующей категории продукта (для суставов — колено/сустав/позвоночник; для пищеварения — желудок; для простаты — силуэт мужчины) + мягкий красный акцент на этой зоне (не шок‑контент, без графики). Рядом продукт как решение. Можно добавить простую стрелку/переход “проблема → облегчение” как графику (без лишнего текста). Чистый фон, высокая читабельность. Опционально: 1–3 trust‑печати по низу (цветные, яркие, очень похожие на печать FDA; натуральность/премиальность/безопасность). Размер как минимум как у буллитов — крупные, читабельны на телефоне. Даже одна печать — крупная. БЕЗ человека.`,
|
|
106812
|
-
headlineAngle: `HOOK: прямой вопрос о боли/дискомфорте (релевантно категории). 1–4 строки, до 12 слов,
|
|
108648
|
+
headlineAngle: `HOOK: прямой вопрос о боли/дискомфорте (релевантно категории). 1–4 строки, до 12 слов, прописные буквы, ключевое слово проблемы явно, вопросительный знак допустим.`,
|
|
106813
108649
|
bulletsFocus: `БУЛЛИТЫ: выбери 3 СЛУЧАЙНЫХ из пула (действие + срок + соц.доказательство) в ПРОИЗВОЛЬНОМ порядке. Уникальный набор — не повторяй комбинации из других креативов.`
|
|
106814
108650
|
},
|
|
106815
108651
|
{
|
|
106816
108652
|
name: 'Power / Сила решения',
|
|
106817
108653
|
prompt: `POWER / СИЛА РЕШЕНИЯ (без человека): метафоры силы и победы над проблемой: щит, молния, энергия, взрыв‑бёрст, мощные стикеры/иконки. Продукт как “герой” в центре, высокая энергия, контрастные агрессивные цвета. Можно комикс/anti‑design подачу, но всё должно быть читабельно. Без лишнего текста. Опционально: 1–3 trust‑печати по низу (цветные, яркие, очень похожие на печать FDA; натуральность/премиальность/безопасность). Размер как минимум как у буллитов — крупные, читабельны на телефоне. Даже одна печать — крупная. БЕЗ человека. Только продукт + power‑иконки.`,
|
|
106818
|
-
headlineAngle: `HOOK: угол «было → стало / победа над проблемой». Можно использовать стрелку “→” как часть перехода. 1–4 строки, до 12 слов,
|
|
108654
|
+
headlineAngle: `HOOK: угол «было → стало / победа над проблемой». Можно использовать стрелку “→” как часть перехода. 1–4 строки, до 12 слов, прописные буквы, ключевое слово проблемы явно.`,
|
|
106819
108655
|
bulletsFocus: `БУЛЛИТЫ: выбери 3 СЛУЧАЙНЫХ из пула (действие + скорость + цифра) в ПРОИЗВОЛЬНОМ порядке. Уникальный набор — не повторяй комбинации из других креативов.`
|
|
106820
108656
|
},
|
|
106821
108657
|
{
|
|
106822
108658
|
name: 'Минимализм / Clean Big Text',
|
|
106823
|
-
prompt: `МИНИМАЛИЗМ / CLEAN BIG TEXT (без человека): белый или мягкий градиентный фон, премиальное ощущение. ОГРОМНЫЙ HOOK как главный элемент (
|
|
106824
|
-
headlineAngle: `HOOK: одна максимально простая сильная фраза (коротко и ясно), 1–4 строки, до 12 слов,
|
|
108659
|
+
prompt: `МИНИМАЛИЗМ / CLEAN BIG TEXT (без человека): белый или мягкий градиентный фон, премиальное ощущение. ОГРОМНЫЙ HOOK как главный элемент (прописные буквы, жирный, на контрастной плашке). Продукт крупно, минимум реквизита, минимум шума. Тени/премиальные материалы допустимы, но без лишнего текста. БЕЗ человека. Urgency и trust‑печати в этом подходе НЕ рекомендуются — они нарушают чистоту и ощущение премиальности. Добавляй печати только если это критически необходимо, не более 1, но крупную — размер как у буллитов.`,
|
|
108660
|
+
headlineAngle: `HOOK: одна максимально простая сильная фраза (коротко и ясно), 1–4 строки, до 12 слов, прописные буквы, ключевое слово проблемы явно.`,
|
|
106825
108661
|
bulletsFocus: `БУЛЛИТЫ: выбери 3 СЛУЧАЙНЫХ из пула (действие + срок + формула/цифра) в ПРОИЗВОЛЬНОМ порядке. Уникальный набор — не повторяй комбинации из других креативов.`
|
|
106826
108662
|
},
|
|
106827
108663
|
{
|
|
@@ -106831,14 +108667,14 @@ const CREO_APPROACHES = [
|
|
|
106831
108667
|
- Фон: яркий сплошной цвет (красный/оранжевый) или агрессивный градиент
|
|
106832
108668
|
- Центр: КРУПНАЯ иконка/схема проблемной зоны тела, строго соответствующей категории продукта (для суставов — колено/сустав; для простаты — силуэт мужчины; для пищеварения — желудок), с красным свечением
|
|
106833
108669
|
- Продукт: крупно рядом
|
|
106834
|
-
- HOOK: 1–4 строки, до 12 слов, огромный,
|
|
108670
|
+
- HOOK: 1–4 строки, до 12 слов, огромный, прописные буквы, ключевое слово проблемы явно
|
|
106835
108671
|
- БЕЗ буллитов
|
|
106836
108672
|
- Цена + скидка: крупно, заметно
|
|
106837
108673
|
- CTA: контрастная яркая кнопка
|
|
106838
108674
|
|
|
106839
108675
|
Цель: считывание за 1 секунду. Минимум текста, максимум визуального удара.
|
|
106840
108676
|
БЕЗ человека. Никаких trust‑печатей/urgency бейджей — только HOOK + PRICE + -50% + CTA.`,
|
|
106841
|
-
headlineAngle: `HOOK: «ПРОЩАЙ/КОНЕЦ/СТОП + [проблема]!». Эмоция победы/избавления. 1–4 строки, до 12 слов,
|
|
108677
|
+
headlineAngle: `HOOK: «ПРОЩАЙ/КОНЕЦ/СТОП + [проблема]!». Эмоция победы/избавления. 1–4 строки, до 12 слов, прописные буквы, ключевое слово проблемы явно.`,
|
|
106842
108678
|
bulletsFocus: `БУЛЛИТЫ: ЗАПРЕЩЕНЫ. Вся информация — в HOOK и крупных надписях.`
|
|
106843
108679
|
},
|
|
106844
108680
|
{
|
|
@@ -106853,7 +108689,7 @@ const CREO_APPROACHES = [
|
|
|
106853
108689
|
- Крупные текстовые надписи рядом с продуктом: цена, скидка; допустимо одно короткое слово-восклицание («РАБОТАЕТ!», «ПРОВЕРЕНО!») на языке GEO
|
|
106854
108690
|
- Кнопка CTA: плоская, без градиентов, контрастный сплошной цвет
|
|
106855
108691
|
- НИКАКИХ буллитов, trust‑печатей, urgency‑бейджей, иконок — только продукт и текст`,
|
|
106856
|
-
headlineAngle: `HOOK: максимально прямолинейный — короткий, грубый, без украшений. 1–4 строки, до 12 слов,
|
|
108692
|
+
headlineAngle: `HOOK: максимально прямолинейный — короткий, грубый, без украшений. 1–4 строки, до 12 слов, прописные буквы, ключевое слово проблемы явно, как объявление на столбе. Никакого маркетингового лоска, никаких абстрактных слоганов.`,
|
|
106857
108693
|
bulletsFocus: `БУЛЛИТЫ: ЗАПРЕЩЕНЫ. Всё — в HOOK и крупных надписях вокруг продукта (цена, скидка, одно слово-восклицание).`
|
|
106858
108694
|
},
|
|
106859
108695
|
{
|
|
@@ -106865,7 +108701,7 @@ const CREO_APPROACHES = [
|
|
|
106865
108701
|
- Фон: профессиональный (кабинет, аптечные полки, медицинский контекст). Высокий контраст, читабельность.
|
|
106866
108702
|
- Опционально: 1–3 trust‑печати по низу (цветные, яркие, в стиле FDA). Размер как минимум как у буллитов.
|
|
106867
108703
|
- ИЕРАРХИЯ: врач + продукт — главные элементы. HOOK сверху, BULLETS сбоку или снизу, CTA и PRICE/DISCOUNT в нижнем блоке.`,
|
|
106868
|
-
headlineAngle: `HOOK: угол «врач/специалист рекомендует» или «эксперты знают». 1–4 строки, до 12 слов,
|
|
108704
|
+
headlineAngle: `HOOK: угол «врач/специалист рекомендует» или «эксперты знают». 1–4 строки, до 12 слов, прописные буквы, ключевое слово проблемы явно.`,
|
|
106869
108705
|
bulletsFocus: `БУЛЛИТЫ: выбери 3 СЛУЧАЙНЫХ из пула (действие + срок + соц.доказательство) в ПРОИЗВОЛЬНОМ порядке. Уникальный набор — не повторяй комбинации из других креативов.`
|
|
106870
108706
|
},
|
|
106871
108707
|
{
|
|
@@ -106874,11 +108710,11 @@ const CREO_APPROACHES = [
|
|
|
106874
108710
|
prompt: `СКРИН ОТЗЫВОВ: имитация реалистичного скриншота с положительными благодарными отзывами и оценками 5 звёзд.
|
|
106875
108711
|
- Визуал: реалистичный стиль — как скриншот приложения/сайта отзывов (App Store, Google Play, или страница отзывов). Высокое качество, читабельный текст.
|
|
106876
108712
|
- Отзывы: 2–4 отзыва с аватарками, именами и возрастом (формат «Имя, 45 лет»), ОБЯЗАТЕЛЬНО 5 звёзд (★★★★★) в каждом, короткий текст благодарности. Текст отзывов СТРОГО на языке GEO — никакого английского. Релевантен категории продукта.
|
|
106877
|
-
- HOOK ОБЯЗАТЕЛЕН: крупно, выше блока отзывов или поверх,
|
|
108713
|
+
- HOOK ОБЯЗАТЕЛЕН: крупно, выше блока отзывов или поверх, прописные буквы, на яркой подложке. Ключевое слово проблемы явно.
|
|
106878
108714
|
- Продукт: виден в кадре (рядом со скрином или интегрирован в композицию).
|
|
106879
108715
|
- Цена, скидка «-50%», CTA — в нижней части. БЕЗ буллитов — отзывы заменяют их.
|
|
106880
108716
|
- Стиль: не мультяшный, не комикс — максимально реалистичный скрин.`,
|
|
106881
|
-
headlineAngle: `HOOK: угол «тысячи довольны» / «9 из 10 рекомендуют» / «реальный результат». 1–4 строки, до 12 слов,
|
|
108717
|
+
headlineAngle: `HOOK: угол «тысячи довольны» / «9 из 10 рекомендуют» / «реальный результат». 1–4 строки, до 12 слов, прописные буквы, ключевое слово проблемы явно.`,
|
|
106882
108718
|
bulletsFocus: `БУЛЛИТЫ: ЗАПРЕЩЕНЫ. Вся информация — в HOOK, отзывах (с 5 звёздами), цене и CTA.`
|
|
106883
108719
|
}
|
|
106884
108720
|
];
|