Commit inicial - WordPress Análisis de Precios Unitarios

- WordPress core y plugins
- Tema Twenty Twenty-Four configurado
- Plugin allow-unfiltered-html.php simplificado
- .gitignore configurado para excluir wp-config.php y uploads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-11-03 21:04:30 -06:00
commit a22573bf0b
24068 changed files with 4993111 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
export default function Divider({ className = '' }) {
return <div className={`bg-gray-200 my-8 h-[1px] ${className}`}></div>;
}

View File

@@ -0,0 +1,7 @@
export default function ErrorMessage({ message }) {
return (
<div className="p-4 mb-4 text-sm text-red-800 rounded-lg bg-red-50 dark:bg-gray-800 dark:text-red-400">
{message}
</div>
);
}

View File

@@ -0,0 +1,12 @@
import { wizard } from '@advancedAds/i18n';
export default function Preloader() {
return (
<div className="absolute inset-0 flex justify-center items-center z-10 bg-white bg-opacity-70">
<img
alt={wizard.processing}
src={`${advancedAds.endpoints.adminUrl}images/spinner-2x.gif`}
/>
</div>
);
}

View File

@@ -0,0 +1,56 @@
import { wizard } from '@advancedAds/i18n';
export default function SelectAccount({ accounts, tokenData, done, fail }) {
const params = new URLSearchParams(document.location.search);
const options = [
<option value="" key="select-account">
{wizard.selectAccount.optionZero}
</option>,
];
for (const id in accounts) {
options.push(
<option value={JSON.stringify(accounts[id])} key={id}>
{accounts[id].name} ({id})
</option>
);
}
const saveSelection = function (event) {
if (!event.target.value) {
return;
}
event.target.disabled = true;
const account = JSON.parse(event.target.value);
wp.ajax
.post('advads_gadsense_mapi_select_account', {
nonce: params.get('nonce'),
account,
token_data: tokenData,
})
.done(function (response) {
if ('function' === typeof done) {
done.call(null, response);
}
})
.fail(function (response) {
if ('function' === typeof fail) {
fail.call(null, response);
}
event.target.disabled = false;
});
};
return (
<>
<h2>{wizard.selectAccount.title}</h2>
<label htmlFor="g-account">
<select id="g-account" onChange={(ev) => saveSelection(ev)}>
{options}
</select>
</label>
</>
);
}

View File

@@ -0,0 +1,44 @@
/**
* External Dependencies
*/
import clx from 'classnames';
export default function CheckboxList({
id,
onChange,
options,
value = '',
isButton = false,
}) {
const wrapClassName = clx('advads-radio-list', { 'is-button': isButton });
return (
<div className={wrapClassName}>
{options.map((option) => {
const checkboxId = `checkbox-${option.value}-${id}`;
const props = {
type: 'checkbox',
id: checkboxId,
value: option.value,
checked: false,
};
if (value) {
props.checked = value.includes(option.value);
}
return (
<div className="advads-radio-list--item" key={option.value}>
<input
{...props}
onChange={() => onChange(option.value)}
/>
<label htmlFor={checkboxId}>
<span>{option.label}</span>
</label>
</div>
);
})}
</div>
);
}

View File

@@ -0,0 +1,49 @@
/**
* External Dependencies
*/
import clx from 'classnames';
export default function RadioList({
id,
onChange,
options,
value = '',
isButton = false,
className = '',
}) {
const wrapClassName = clx(
'advads-radio-list',
{ 'is-button': isButton },
className
);
return (
<div className={wrapClassName}>
{options.map((option) => {
const radioId = `radio-${option.value}-${id}`;
const props = {
type: 'radio',
id: radioId,
name: id,
value: option.value,
};
if (value) {
props.checked = value === option.value;
}
return (
<div className="advads-radio-list--item" key={option.value}>
<input
{...props}
onChange={() => onChange(option.value)}
/>
<label htmlFor={radioId}>
<span>{option.label}</span>
</label>
</div>
);
})}
</div>
);
}

View File

@@ -0,0 +1,108 @@
/* eslint-disable import/no-extraneous-dependencies */
import {
cloneElement,
memo,
useMemo,
useRef,
useState,
Children,
} from '@wordpress/element';
/**
* Internal Dependencies
*/
import WizardContext from './wizardContext';
const Wizard = memo(
({ header, footer, children, wrapper: Wrapper, startIndex = 1 }) => {
const [activeStep, setActiveStep] = useState(startIndex - 1);
const [isLoading, setIsLoading] = useState(false);
const hasNextStep = useRef(true);
const hasPreviousStep = useRef(false);
const nextStepHandler = useRef(() => {});
const stepCount = Children.toArray(children).length;
hasNextStep.current = activeStep < stepCount - 1;
hasPreviousStep.current = activeStep > 0;
const goToNextStep = useRef(() => {
if (hasNextStep.current) {
setActiveStep((newActiveStep) => newActiveStep + 1);
}
});
const goToPreviousStep = useRef(() => {
if (hasPreviousStep.current) {
nextStepHandler.current = null;
setActiveStep((newActiveStep) => newActiveStep - 1);
}
});
const goToStep = useRef((stepIndex) => {
if (stepIndex >= 0 && stepIndex < stepCount) {
nextStepHandler.current = null;
setActiveStep(stepIndex);
}
});
// Callback to attach the step handler
const handleStep = useRef((handler) => {
nextStepHandler.current = handler;
});
const doNextStep = useRef(async () => {
if (hasNextStep.current && nextStepHandler.current) {
try {
setIsLoading(true);
await nextStepHandler.current();
setIsLoading(false);
nextStepHandler.current = null;
goToNextStep.current();
} catch (error) {
setIsLoading(false);
throw error;
}
} else {
goToNextStep.current();
}
});
const wizardValue = useMemo(
() => ({
nextStep: doNextStep.current,
previousStep: goToPreviousStep.current,
handleStep: handleStep.current,
isLoading,
activeStep,
stepCount,
isFirstStep: !hasPreviousStep.current,
isLastStep: !hasNextStep.current,
goToStep: goToStep.current,
}),
[activeStep, stepCount, isLoading]
);
const activeStepContent = useMemo(() => {
const reactChildren = Children.toArray(children);
return reactChildren[activeStep];
}, [activeStep, children]);
const enhancedActiveStepContent = useMemo(
() =>
Wrapper
? cloneElement(Wrapper, { children: activeStepContent })
: activeStepContent,
[Wrapper, activeStepContent]
);
return (
<WizardContext.Provider value={wizardValue}>
{header}
{enhancedActiveStepContent}
{footer}
</WizardContext.Provider>
);
}
);
export default Wizard;

View File

@@ -0,0 +1,2 @@
export { default as useWizard } from './useWizard';
export { default as Wizard } from './Wizard';

View File

@@ -0,0 +1,17 @@
/* eslint-disable import/no-extraneous-dependencies */
import { useContext } from '@wordpress/element';
/**
* Internal Dependencies
*/
import WizardContext from './wizardContext';
export default function useWizard() {
const context = useContext(WizardContext);
if (!context) {
throw Error('Wrap your step with `Wizard`');
}
return context;
}

View File

@@ -0,0 +1,12 @@
/* eslint-disable import/no-extraneous-dependencies */
import { createContext } from '@wordpress/element';
const WizardContext = createContext({
isLoading: false,
isFirstStep: true,
isLastStep: false,
stepCount: 0,
activeStep: 0,
});
export default WizardContext;