[英]Get the ID of a selected Card element and pass it to a modal to select the element
我有一個代碼可以在卡片中呈現多個計划。 這是代碼:
import React, { useEffect, useState } from 'react';
import { I18nText, Card, BaseModal, Button } from '@wtag/react-comp-lib';
import PropTypes from 'prop-types';
import greenCheck from 'affiliateIcons/green-check.svg';
import doneMark from '../../../../assets/images/done-24px.svg';
import routes from '../../../shared/routes';
import httpClient from '../../../shared/libraries/httpClient';
const Plans = ({ affiliateId }) => {
const [plans, setPlans] = useState([]);
const [currentPlan, setCurrentPlan] = useState([]);
const [modalOpen, setModalOpen] = useState(false);
const fetchPlans = async () => {
const { data } = await httpClient.get(
routes.billing.changePlan.fetch({ affiliate_id: affiliateId }),
);
setPlans(data.plans);
setCurrentPlan(data.currentPlan);
};
const selectPlan = async plan => {
const { data } = await httpClient.put(
routes.billing.changePlan.update({
id: plan.id,
affiliate_id: affiliateId,
}),
);
if (data.error === null) {
fetchPlans(data.currentPlan);
setModalOpen(false);
}
};
useEffect(() => {
fetchPlans();
}, []);
const data = [
{
id: 0,
identifier: 'free-2020',
name: <I18nText id="pricing.plans.name.free" />,
planTitle: 'free',
price: '00',
freeSearches: <I18nText id="pricing.plans.features.unlimited" />,
freeBookings: <I18nText id="pricing.plans.features.unlimited" />,
travelerProfiles: <I18nText id="pricing.plans.features.unlimited" />,
supportTickets: <I18nText id="pricing.plans.features.available" />,
supportByPhone: '-',
supplierChannels: '-',
customDomain: '-',
active: true,
},
{
id: 1,
identifier: 'basic-2020',
name: <I18nText id="pricing.plans.name.basic" />,
planTitle: 'basic',
price: '29',
freeSearches: <I18nText id="pricing.plans.features.unlimited" />,
freeBookings: <I18nText id="pricing.plans.features.unlimited" />,
travelerProfiles: <I18nText id="pricing.plans.features.unlimited" />,
supportTickets: <I18nText id="pricing.plans.features.available" />,
supportByPhone: '-',
supplierChannels: '1',
customDomain: '-',
active: false,
},
{
id: 2,
identifier: 'standard-2020',
name: <I18nText id="pricing.plans.name.standard" />,
planTitle: 'standard',
price: '59',
freeSearches: <I18nText id="pricing.plans.features.unlimited" />,
freeBookings: <I18nText id="pricing.plans.features.unlimited" />,
travelerProfiles: <I18nText id="pricing.plans.features.unlimited" />,
supportTickets: <I18nText id="pricing.plans.features.available" />,
supportByPhone: '1hr/mo',
supplierChannels: '2',
customDomain: '-',
active: false,
},
{
id: 3,
identifier: 'professional-2020',
name: <I18nText id="pricing.plans.name.professional" />,
planTitle: 'professional',
price: '99',
freeSearches: <I18nText id="pricing.plans.features.unlimited" />,
freeBookings: <I18nText id="pricing.plans.features.unlimited" />,
travelerProfiles: <I18nText id="pricing.plans.features.unlimited" />,
supportTickets: <I18nText id="pricing.plans.features.available" />,
supportByPhone: '3hr/mo',
supplierChannels: '5',
customDomain: 'Yes',
active: false,
},
{
id: 4,
identifier: 'custom-2020',
name: <I18nText id="pricing.plans.name.custom" />,
planTitle: 'custom',
price: '-',
freeSearches: <I18nText id="pricing.plans.features.unlimited" />,
freeBookings: <I18nText id="pricing.plans.features.unlimited" />,
travelerProfiles: <I18nText id="pricing.plans.features.unlimited" />,
supportTickets: <I18nText id="pricing.plans.features.available" />,
supportByPhone: <I18nText id="pricing.plans.features.unlimited" />,
supplierChannels: <I18nText id="pricing.plans.features.unlimited" />,
customDomain: <I18nText id="pricing.plans.features.available" />,
active: false,
},
];
const planData = data.map(d => {
const correspondingPlan = plans.filter(
plan => d.identifier === plan.identifier,
)[0];
if (correspondingPlan) {
return { ...d, ...correspondingPlan };
}
return d;
});
const tableHeader = [
{ id: 0, name: <I18nText id="pricing.table.header.free" /> },
{ id: 1, name: <I18nText id="pricing.table.header.basic" /> },
{ id: 2, name: <I18nText id="pricing.table.header.standard" /> },
{ id: 3, name: <I18nText id="pricing.table.header.professional" /> },
{ id: 4, name: <I18nText id="pricing.table.header.custom" /> },
];
const planOptions = [
{
id: 0,
name: <I18nText id="pricing.table.feature.subscription.search" />,
isFree: doneMark,
isBasic: doneMark,
isStandard: doneMark,
isProfessional: doneMark,
isCustom: doneMark,
},
{
id: 1,
name: <I18nText id="pricing.table.feature.subscription.bookings" />,
isFree: doneMark,
isBasic: doneMark,
isStandard: doneMark,
isProfessional: doneMark,
isCustom: doneMark,
},
{
id: 2,
name: <I18nText id="pricing.table.feature.subscription.traveler" />,
isFree: doneMark,
isBasic: doneMark,
isStandard: doneMark,
isProfessional: doneMark,
isCustom: doneMark,
},
{
id: 3,
name: <I18nText id="pricing.table.feature.subscription.corporate" />,
isFree: doneMark,
isBasic: doneMark,
isStandard: doneMark,
isProfessional: doneMark,
isCustom: doneMark,
},
{
id: 4,
name: <I18nText id="pricing.table.feature.subscription.quotes" />,
isFree: doneMark,
isBasic: doneMark,
isStandard: doneMark,
isProfessional: doneMark,
isCustom: doneMark,
},
{
id: 5,
name: <I18nText id="pricing.table.feature.subscription.ndc" />,
isFree: doneMark,
isBasic: doneMark,
isStandard: doneMark,
isProfessional: doneMark,
isCustom: doneMark,
},
];
const getCurrentPlan = currentPlan && currentPlan.name;
const newPlansCard = planData.map(plan => {
const matchPlan = plan.name === getCurrentPlan;
return (
<>
<Card
className="billing-plans__plans-card"
size="normal"
version="v2"
title={plan.name}
headerCenter={true}
key={plan.id}
>
{matchPlan ? (
<div className="billing-plans__current-plan-icon">
<img src={greenCheck} alt="check" />
</div>
) : null}
<div className="billing-plans__plans-card-title">
<sup>US$</sup>
{plan.price}
<sub>
/<I18nText id="pricing.plans.misc.month" />
</sub>
</div>
<div className="billing-plans__plans-card-features-wrapper">
<div className="billing-plans__plans-card-features">
<I18nText id="pricing.plans.features.searches" />
<span className="billing-plans__features-access">
{plan.freeSearches}
</span>
</div>
<div className="billing-plans__plans-card-features">
<I18nText id="pricing.plans.features.bookings" />
<span className="billing-plans__features-access">
{plan.freeBookings}
</span>
</div>
<div className="billing-plans__plans-card-features">
<I18nText id="pricing.plans.features.profiles" />
<span className="billing-plans__features-access">
{plan.travelerProfiles}
</span>
</div>
<div className="billing-plans__plans-card-features">
<I18nText id="pricing.plans.features.tickets" />
<span className="billing-plans__features-access">
{plan.supportTickets}
</span>
</div>
<div className="billing-plans__plans-card-features">
<I18nText id="pricing.plans.features.phone" />
<span className="billing-plans__features-access">
{plan.supportByPhone}
</span>
</div>
<div className="billing-plans__plans-card-features">
<I18nText id="pricing.plans.features.channels" />
<span className="billing-plans__features-access">
{plan.supplierChannels}
</span>
</div>
<div className="billing-plans__plans-card-features">
<I18nText id="pricing.plans.features.domain" />
<span className="billing-plans__features-access">
{plan.customDomain}
</span>
</div>
</div>
<div className="billing-plans__plans-card-actions">
{!matchPlan ? (
<div>
<BaseModal
linkText={<I18nText id="pricing.plans.actions.select" />}
linkClassName="billing-plans__plans-card-actions-button"
open={modalOpen}
onModalClose={() => setModalOpen(false)}
onModalOpen={() => setModalOpen(true)}
header={
<I18nText id="pricing.plans.actions.confirmationText" />
}
size="small"
showCloseIcon={false}
key={plan.id}
>
<div className="col-12">
<Button
version="v2"
type="accent"
size="normal"
label={I18n.t('shared.action.confirm')}
key={plan.id}
onClick={() => {
selectPlan(plan);
}}
/>
<Button
version="v2"
size="normal"
label={I18n.t('shared.action.cancel')}
onClick={() => setModalOpen(false)}
/>
</div>
</BaseModal>
</div>
) : null}
</div>
</Card>
</>
);
});
const pricingTable = () => {
return (
<div>
<div className="container-full billing-plans__pricing-table">
<Card size="full" version="v2" key={planOptions.id}>
<div className="billing-plans__table-header">
<I18nText id="pricing.plans.sub_title" />
</div>
<table className="billing-plans__table-body">
<thead>
<tr>
<th className="billing-plans__table-sub-header">
<I18nText id="pricing.table.feature.header" />
</th>
{tableHeader.map(({ name, id }) => (
<th className="billing-plans__table-sub-header" key={id}>
{name}
</th>
))}
</tr>
</thead>
<tbody>
{planOptions.map(
({
id,
name,
isFree,
isBasic,
isStandard,
isProfessional,
isCustom,
}) => (
<tr key={id}>
<td className="billing-plans__table-data">{name}</td>
<td className="billing-plans__table-plan">
<img src={isFree} alt="check" />
</td>
<td className="billing-plans__table-plan">
<img src={isBasic} alt="check" />
</td>
<td className="billing-plans__table-plan">
<img src={isStandard} alt="check" />
</td>
<td className="billing-plans__table-plan">
<img src={isProfessional} alt="check" />
</td>
<td className="billing-plans__table-plan">
<img src={isCustom} alt="check" />
</td>
</tr>
),
)}
</tbody>
</table>
</Card>
</div>
</div>
);
};
return (
<div className="billing-plans">
<div>
<div className="grid">
<div className="col-12 offset-xlg-1 offset-lg-1 offset-md-1 offset-sm-1 offset-xs-1 offset-xxs-1">
<div className="billing-plans__plans-header">
<I18nText id="pricing.plans.title" />
</div>
</div>
</div>
<div className="billing-plans__plans-wrapper">
{currentPlan && newPlansCard}
</div>
</div>
{pricingTable()}
</div>
);
};
Plans.propTypes = {
currentPlan: PropTypes.shape({
name: PropTypes.string,
identifier: PropTypes.string,
id: PropTypes.number,
}).isRequired,
affiliateId: PropTypes.number.isRequired,
};
export default Plans;
我想獲取所選卡的 ID 並將其傳遞給模態。 當第一個按鈕即:卡片模式的確認按鈕被點擊時,卡片將顯示為帶有勾號的選中狀態。 就像在每張卡片中一樣,有選擇計划按鈕,它打開模式對話框以確認用戶是否真的想要選擇計划。 如果他選擇是,則獲取特定卡的 ID,然后將該 ID 傳遞給 selectPlan 函數以選擇特定卡作為計划。 在模式的第一個按鈕的現有代碼庫中,我有一個 onClick 函數,它將特定的選定計划發送到 selectPlan 函數,例如selectPlan(plan)
。 但是現在,無論我使用各自的模式選擇哪張卡,我都只會得到 ID 為 2 或 6 的卡,盡管有 5 張 ID 為 2、3、4、5、6 的卡。這意味着在獲取特定卡時存在一些問題在當前實現中選擇了 Card ID。 我想知道我應該在當前代碼中更改什么以獲取特定選定的卡 ID,並使用 onClick 函數將其傳遞給相應的模式按鈕,以使用selectPlan(plan)
函數將計划表示為選定的selectPlan(plan)
。 這是計划用戶界面:
const [plans, setPlans] = useState([]);
const [currentPlan, setCurrentPlan] = useState([]);
const [modalOpen, setModalOpen] = useState(false);
const [selectedPlan, setSelectedPlan] = useState();
const fetchPlans = async () => {
const { data } = await httpClient.get(
const Plans = ({ affiliateId }) => {
linkClassName="billing-plans__plans-card-actions-button"
open={modalOpen}
onModalClose={() => setModalOpen(false)}
onModalOpen={() => {
setSelectedPlan(plan);
setModalOpen(true);
}}
header={
<I18nText id="pricing.plans.actions.confirmationText" />
}
const Plans = ({ affiliateId }) => {
label={I18n.t('shared.action.confirm')}
key={plan.id}
onClick={() => {
selectPlan(selectedPlan);
}}
/>
<Button
import React, { useEffect, useState } from 'react';
import { I18nText, Card, BaseModal, Button } from '@wtag/react-comp-lib';
import PropTypes from 'prop-types';
import greenCheck from 'affiliateIcons/green-check.svg';
import doneMark from '../../../../assets/images/done-24px.svg';
import routes from '../../../shared/routes';
import httpClient from '../../../shared/libraries/httpClient';
const Plans = ({ affiliateId }) => {
const [plans, setPlans] = useState([]);
const [currentPlan, setCurrentPlan] = useState([]);
const [modalOpen, setModalOpen] = useState(false);
const [selectedPlan, setSelectedPlan] = useState();
const fetchPlans = async () => {
const { data } = await httpClient.get(
routes.billing.changePlan.fetch({ affiliate_id: affiliateId }),
);
setPlans(data.plans);
setCurrentPlan(data.currentPlan);
};
const selectPlan = async plan => {
const { data } = await httpClient.put(
routes.billing.changePlan.update({
id: plan.id,
affiliate_id: affiliateId,
}),
);
if (data.error === null) {
fetchPlans(data.currentPlan);
setModalOpen(false);
}
};
useEffect(() => {
fetchPlans();
}, []);
const data = [
{
id: 0,
identifier: 'free-2020',
name: <I18nText id="pricing.plans.name.free" />,
planTitle: 'free',
price: '00',
freeSearches: <I18nText id="pricing.plans.features.unlimited" />,
freeBookings: <I18nText id="pricing.plans.features.unlimited" />,
travelerProfiles: <I18nText id="pricing.plans.features.unlimited" />,
supportTickets: <I18nText id="pricing.plans.features.available" />,
supportByPhone: '-',
supplierChannels: '-',
customDomain: '-',
active: true,
},
{
id: 1,
identifier: 'basic-2020',
name: <I18nText id="pricing.plans.name.basic" />,
planTitle: 'basic',
price: '29',
freeSearches: <I18nText id="pricing.plans.features.unlimited" />,
freeBookings: <I18nText id="pricing.plans.features.unlimited" />,
travelerProfiles: <I18nText id="pricing.plans.features.unlimited" />,
supportTickets: <I18nText id="pricing.plans.features.available" />,
supportByPhone: '-',
supplierChannels: '1',
customDomain: '-',
active: false,
},
{
id: 2,
identifier: 'standard-2020',
name: <I18nText id="pricing.plans.name.standard" />,
planTitle: 'standard',
price: '59',
freeSearches: <I18nText id="pricing.plans.features.unlimited" />,
freeBookings: <I18nText id="pricing.plans.features.unlimited" />,
travelerProfiles: <I18nText id="pricing.plans.features.unlimited" />,
supportTickets: <I18nText id="pricing.plans.features.available" />,
supportByPhone: '1hr/mo',
supplierChannels: '2',
customDomain: '-',
active: false,
},
{
id: 3,
identifier: 'professional-2020',
name: <I18nText id="pricing.plans.name.professional" />,
planTitle: 'professional',
price: '99',
freeSearches: <I18nText id="pricing.plans.features.unlimited" />,
freeBookings: <I18nText id="pricing.plans.features.unlimited" />,
travelerProfiles: <I18nText id="pricing.plans.features.unlimited" />,
supportTickets: <I18nText id="pricing.plans.features.available" />,
supportByPhone: '3hr/mo',
supplierChannels: '5',
customDomain: 'Yes',
active: false,
},
{
id: 4,
identifier: 'custom-2020',
name: <I18nText id="pricing.plans.name.custom" />,
planTitle: 'custom',
price: '-',
freeSearches: <I18nText id="pricing.plans.features.unlimited" />,
freeBookings: <I18nText id="pricing.plans.features.unlimited" />,
travelerProfiles: <I18nText id="pricing.plans.features.unlimited" />,
supportTickets: <I18nText id="pricing.plans.features.available" />,
supportByPhone: <I18nText id="pricing.plans.features.unlimited" />,
supplierChannels: <I18nText id="pricing.plans.features.unlimited" />,
customDomain: <I18nText id="pricing.plans.features.available" />,
active: false,
},
];
const planData = data.map(d => {
const correspondingPlan = plans.filter(
plan => d.identifier === plan.identifier,
)[0];
if (correspondingPlan) {
return { ...d, ...correspondingPlan };
}
return d;
});
const tableHeader = [
{ id: 0, name: <I18nText id="pricing.table.header.free" /> },
{ id: 1, name: <I18nText id="pricing.table.header.basic" /> },
{ id: 2, name: <I18nText id="pricing.table.header.standard" /> },
{ id: 3, name: <I18nText id="pricing.table.header.professional" /> },
{ id: 4, name: <I18nText id="pricing.table.header.custom" /> },
];
const planOptions = [
{
id: 0,
name: <I18nText id="pricing.table.feature.subscription.search" />,
isFree: doneMark,
isBasic: doneMark,
isStandard: doneMark,
isProfessional: doneMark,
isCustom: doneMark,
},
{
id: 1,
name: <I18nText id="pricing.table.feature.subscription.bookings" />,
isFree: doneMark,
isBasic: doneMark,
isStandard: doneMark,
isProfessional: doneMark,
isCustom: doneMark,
},
{
id: 2,
name: <I18nText id="pricing.table.feature.subscription.traveler" />,
isFree: doneMark,
isBasic: doneMark,
isStandard: doneMark,
isProfessional: doneMark,
isCustom: doneMark,
},
{
id: 3,
name: <I18nText id="pricing.table.feature.subscription.corporate" />,
isFree: doneMark,
isBasic: doneMark,
isStandard: doneMark,
isProfessional: doneMark,
isCustom: doneMark,
},
{
id: 4,
name: <I18nText id="pricing.table.feature.subscription.quotes" />,
isFree: doneMark,
isBasic: doneMark,
isStandard: doneMark,
isProfessional: doneMark,
isCustom: doneMark,
},
{
id: 5,
name: <I18nText id="pricing.table.feature.subscription.ndc" />,
isFree: doneMark,
isBasic: doneMark,
isStandard: doneMark,
isProfessional: doneMark,
isCustom: doneMark,
},
];
const getCurrentPlan = currentPlan && currentPlan.name;
const newPlansCard = planData.map(plan => {
const matchPlan = plan.name === getCurrentPlan;
return (
<>
<Card
className="billing-plans__plans-card"
size="normal"
version="v2"
title={plan.name}
headerCenter={true}
key={plan.id}
>
{matchPlan ? (
<div className="billing-plans__current-plan-icon">
<img src={greenCheck} alt="check" />
</div>
) : null}
<div className="billing-plans__plans-card-title">
<sup>US$</sup>
{plan.price}
<sub>
/<I18nText id="pricing.plans.misc.month" />
</sub>
</div>
<div className="billing-plans__plans-card-features-wrapper">
<div className="billing-plans__plans-card-features">
<I18nText id="pricing.plans.features.searches" />
<span className="billing-plans__features-access">
{plan.freeSearches}
</span>
</div>
<div className="billing-plans__plans-card-features">
<I18nText id="pricing.plans.features.bookings" />
<span className="billing-plans__features-access">
{plan.freeBookings}
</span>
</div>
<div className="billing-plans__plans-card-features">
<I18nText id="pricing.plans.features.profiles" />
<span className="billing-plans__features-access">
{plan.travelerProfiles}
</span>
</div>
<div className="billing-plans__plans-card-features">
<I18nText id="pricing.plans.features.tickets" />
<span className="billing-plans__features-access">
{plan.supportTickets}
</span>
</div>
<div className="billing-plans__plans-card-features">
<I18nText id="pricing.plans.features.phone" />
<span className="billing-plans__features-access">
{plan.supportByPhone}
</span>
</div>
<div className="billing-plans__plans-card-features">
<I18nText id="pricing.plans.features.channels" />
<span className="billing-plans__features-access">
{plan.supplierChannels}
</span>
</div>
<div className="billing-plans__plans-card-features">
<I18nText id="pricing.plans.features.domain" />
<span className="billing-plans__features-access">
{plan.customDomain}
</span>
</div>
</div>
<div className="billing-plans__plans-card-actions">
{!matchPlan ? (
<div>
<BaseModal
linkText={<I18nText id="pricing.plans.actions.select" />}
linkClassName="billing-plans__plans-card-actions-button"
open={modalOpen}
onModalClose={() => setModalOpen(false)}
onModalOpen={() => {
setSelectedPlan(plan);
setModalOpen(true);
}}
header={
<I18nText id="pricing.plans.actions.confirmationText" />
}
size="small"
showCloseIcon={false}
key={plan.id}
>
<div className="col-12">
<Button
version="v2"
type="accent"
size="normal"
label={I18n.t('shared.action.confirm')}
key={plan.id}
onClick={() => {
selectPlan(selectedPlan);
}}
/>
<Button
version="v2"
size="normal"
label={I18n.t('shared.action.cancel')}
onClick={() => setModalOpen(false)}
/>
</div>
</BaseModal>
</div>
) : null}
</div>
</Card>
</>
);
});
const pricingTable = () => {
return (
<div>
<div className="container-full billing-plans__pricing-table">
<Card size="full" version="v2" key={planOptions.id}>
<div className="billing-plans__table-header">
<I18nText id="pricing.plans.sub_title" />
</div>
<table className="billing-plans__table-body">
<thead>
<tr>
<th className="billing-plans__table-sub-header">
<I18nText id="pricing.table.feature.header" />
</th>
{tableHeader.map(({ name, id }) => (
<th className="billing-plans__table-sub-header" key={id}>
{name}
</th>
))}
</tr>
</thead>
<tbody>
{planOptions.map(
({
id,
name,
isFree,
isBasic,
isStandard,
isProfessional,
isCustom,
}) => (
<tr key={id}>
<td className="billing-plans__table-data">{name}</td>
<td className="billing-plans__table-plan">
<img src={isFree} alt="check" />
</td>
<td className="billing-plans__table-plan">
<img src={isBasic} alt="check" />
</td>
<td className="billing-plans__table-plan">
<img src={isStandard} alt="check" />
</td>
<td className="billing-plans__table-plan">
<img src={isProfessional} alt="check" />
</td>
<td className="billing-plans__table-plan">
<img src={isCustom} alt="check" />
</td>
</tr>
),
)}
</tbody>
</table>
</Card>
</div>
</div>
);
};
return (
<div className="billing-plans">
<div>
<div className="grid">
<div className="col-12 offset-xlg-1 offset-lg-1 offset-md-1 offset-sm-1 offset-xs-1 offset-xxs-1">
<div className="billing-plans__plans-header">
<I18nText id="pricing.plans.title" />
</div>
</div>
</div>
<div className="billing-plans__plans-wrapper">
{currentPlan && newPlansCard}
</div>
</div>
{pricingTable()}
</div>
);
};
Plans.propTypes = {
currentPlan: PropTypes.shape({
name: PropTypes.string,
identifier: PropTypes.string,
id: PropTypes.number,
}).isRequired,
affiliateId: PropTypes.number.isRequired,
};
export default Plans;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.