mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-30 02:23:47 +00:00
feat: partner-campaign integration in admin UI
- Add partner badge to campaigns list - Add partner selector dropdown in campaign edit - Support ?partnerId= query param in campaign create (replaces separate page) - Filter already-assigned campaigns in partner assign flow - Show taken campaigns greyed out with partner name - Delete AdminPartnerCampaignCreate (replaced by query param approach) - Add partner translations (ru, en, zh, fa)
This commit is contained in:
@@ -8,6 +8,7 @@ import {
|
||||
CampaignBonusType,
|
||||
ServerSquadInfo,
|
||||
TariffListItem,
|
||||
AvailablePartner,
|
||||
} from '../api/campaigns';
|
||||
import { AdminBackButton } from '../components/admin';
|
||||
import { CheckIcon, CampaignIcon } from '../components/icons';
|
||||
@@ -124,6 +125,40 @@ function TariffSelector({
|
||||
);
|
||||
}
|
||||
|
||||
// Partner selector component
|
||||
function PartnerSelector({
|
||||
partners,
|
||||
value,
|
||||
onChange,
|
||||
}: {
|
||||
partners: AvailablePartner[];
|
||||
value: number | null;
|
||||
onChange: (id: number | null) => void;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<label className="mb-2 block text-sm font-medium text-dark-300">
|
||||
{t('admin.campaigns.form.partner')}
|
||||
</label>
|
||||
<select
|
||||
value={value || ''}
|
||||
onChange={(e) => onChange(e.target.value ? parseInt(e.target.value) : null)}
|
||||
className="input"
|
||||
>
|
||||
<option value="">{t('admin.campaigns.form.noPartner')}</option>
|
||||
{partners.map((p) => (
|
||||
<option key={p.user_id} value={p.user_id}>
|
||||
{p.first_name || p.username || `#${p.user_id}`}
|
||||
{p.username ? ` (@${p.username})` : ''}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function AdminCampaignEdit() {
|
||||
const { t } = useTranslation();
|
||||
const { id } = useParams<{ id: string }>();
|
||||
@@ -155,6 +190,12 @@ export default function AdminCampaignEdit() {
|
||||
queryFn: () => campaignsApi.getAvailableTariffs(),
|
||||
});
|
||||
|
||||
// Fetch partners
|
||||
const { data: partners = [] } = useQuery({
|
||||
queryKey: ['admin-campaigns-partners'],
|
||||
queryFn: () => campaignsApi.getAvailablePartners(),
|
||||
});
|
||||
|
||||
// Form state
|
||||
const [name, setName] = useState('');
|
||||
const [startParameter, setStartParameter] = useState('');
|
||||
@@ -174,6 +215,10 @@ export default function AdminCampaignEdit() {
|
||||
const [tariffId, setTariffId] = useState<number | null>(null);
|
||||
const [tariffDays, setTariffDays] = useState<number | ''>(30);
|
||||
|
||||
// Partner
|
||||
const [partnerUserId, setPartnerUserId] = useState<number | null>(null);
|
||||
const [initialPartnerUserId, setInitialPartnerUserId] = useState<number | null>(null);
|
||||
|
||||
// Initialize form when campaign loads
|
||||
useEffect(() => {
|
||||
if (campaign) {
|
||||
@@ -188,6 +233,8 @@ export default function AdminCampaignEdit() {
|
||||
setSelectedSquads(campaign.subscription_squads || []);
|
||||
setTariffId(campaign.tariff_id || null);
|
||||
setTariffDays(campaign.tariff_duration_days || 30);
|
||||
setPartnerUserId(campaign.partner_user_id ?? null);
|
||||
setInitialPartnerUserId(campaign.partner_user_id ?? null);
|
||||
}
|
||||
}, [campaign]);
|
||||
|
||||
@@ -215,6 +262,11 @@ export default function AdminCampaignEdit() {
|
||||
is_active: isActive,
|
||||
};
|
||||
|
||||
// Only send partner_user_id when it was actually changed
|
||||
if (partnerUserId !== initialPartnerUserId) {
|
||||
data.partner_user_id = partnerUserId;
|
||||
}
|
||||
|
||||
if (bonusType === 'balance') {
|
||||
data.balance_bonus_kopeks = Math.round(toNumber(balanceBonusRubles) * 100);
|
||||
} else if (bonusType === 'subscription') {
|
||||
@@ -344,6 +396,11 @@ export default function AdminCampaignEdit() {
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Partner */}
|
||||
{partners.length > 0 && (
|
||||
<PartnerSelector partners={partners} value={partnerUserId} onChange={setPartnerUserId} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Bonus Type */}
|
||||
|
||||
Reference in New Issue
Block a user