• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / mender-server / 1593959582

18 Dec 2024 10:51AM UTC coverage: 73.514% (+0.7%) from 72.829%
1593959582

Pull #253

gitlab-ci

mineralsfree
feat: updated billing section in My Organization settings

Ticket: MEN-7466
Changelog: None

Signed-off-by: Mikita Pilinka <mikita.pilinka@northern.tech>
Pull Request #253: MEN-7466-feat: updated billing section in My Organization settings

4257 of 6185 branches covered (68.83%)

Branch coverage included in aggregate %.

53 of 87 new or added lines in 11 files covered. (60.92%)

43 existing lines in 11 files now uncovered.

40083 of 54130 relevant lines covered (74.05%)

22.98 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

46.3
/frontend/src/js/components/settings/PlanExpanded.tsx
1
// Copyright 2024 Northern.tech AS
2
//
3
//    Licensed under the Apache License, Version 2.0 (the "License");
4
//    you may not use this file except in compliance with the License.
5
//    You may obtain a copy of the License at
6
//
7
//        http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//    Unless required by applicable law or agreed to in writing, software
10
//    distributed under the License is distributed on an "AS IS" BASIS,
11
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//    See the License for the specific language governing permissions and
13
//    limitations under the License.
14
import { useRef, useState } from 'react';
15
import { useSelector } from 'react-redux';
16

17
import { Button, Divider, Drawer } from '@mui/material';
18

19
import { DrawerTitle } from '@northern.tech/common-ui/DrawerTitle';
20
import Form from '@northern.tech/common-ui/forms/form';
21
import storeActions from '@northern.tech/store/actions';
22
import { Plan } from '@northern.tech/store/constants';
23
import { BillingProfile, Card, Organization } from '@northern.tech/store/organizationSlice/types';
24
import { getCurrentUser } from '@northern.tech/store/selectors';
25
import { useAppDispatch } from '@northern.tech/store/store';
26
import { completeUpgrade, editBillingProfile, startUpgrade } from '@northern.tech/store/thunks';
27

28
import CardSection from './CardSection';
29
import { PlanExpandedForm } from './PlanExpandedForm';
30
import OrganizationPaymentSettings from './organization/OrganizationPaymentSettings';
31

32
const { setSnackbar } = storeActions;
8✔
33

34
interface PlanExpandedPropsBase {
35
  organization: Organization;
36
  onCloseClick: () => void;
37
  isEdit: boolean;
38
}
39
interface ProfileEditProps extends PlanExpandedPropsBase {
40
  isEdit: true;
41
  currentBillingProfile: BillingProfile;
42
  card: Card;
43
}
44

45
interface PlanProps extends PlanExpandedPropsBase {
46
  isEdit: false;
47
  plan: Plan;
48
}
49

50
const successMessage = (plan: string) =>
8✔
51
  `Thank you! You have successfully subscribed to the ${plan} plan.  You can view and edit your billing details on the Organization and billing page.`;
×
52

53
export const PlanExpanded = (props: ProfileEditProps | PlanProps) => {
8✔
54
  const { onCloseClick, isEdit } = props;
2✔
55
  const organization = !isEdit ? props.organization : null;
1!
56
  const [isValid, setIsValid] = useState(isEdit);
1✔
57
  const [updatingCard, setUpdatingCard] = useState(false);
1✔
58
  const selectedPlan = isEdit ? null : props.plan;
1!
59
  const dispatch = useAppDispatch();
1✔
60
  const formSubmitRef = useRef<() => void | null>(null);
1✔
61
  const { email } = useSelector(getCurrentUser);
1✔
62
  const handleUpgrade = () => {
1✔
63
    if (formSubmitRef.current) {
×
64
      formSubmitRef.current();
×
65
    }
66
  };
67
  const initialValues = isEdit
1!
68
    ? { ...props.currentBillingProfile.address, name: props.currentBillingProfile.name, email: props.currentBillingProfile.email }
69
    : { email, name: organization?.name || '', line1: '', state: '', city: '', postal_code: '', country: '' };
1!
70
  const handleSubmit = async values => {
1✔
NEW
71
    const { email, name, state, city, line1, postal_code } = values;
×
NEW
72
    const code: string = values.country.code ? values.country.code : values.country;
×
73
    const billing_profile = { email, name, address: { country: code, state, city, line1, postal_code } };
×
NEW
74
    if (isEdit) {
×
NEW
75
      await dispatch(editBillingProfile({ billingProfile: billing_profile }));
×
76
    } else {
NEW
77
      await dispatch(completeUpgrade({ tenantId: (organization as Organization).id, plan: (selectedPlan as Plan).id, billing_profile }));
×
NEW
78
      dispatch(setSnackbar(successMessage((selectedPlan as Plan).name)));
×
79
    }
UNCOV
80
    onCloseClick();
×
81
  };
82

83
  return (
1✔
84
    <Drawer anchor="right" open={true} PaperProps={{ style: { minWidth: '75vw' } }}>
85
      <DrawerTitle title={<>{selectedPlan ? `Subscribe to Mender ${selectedPlan.name}` : 'Edit billing details'}</>} onClose={onCloseClick} />
1!
86
      <Divider className="margin-bottom" />
87
      {selectedPlan && (
2✔
88
        <div>
89
          Complete checkout to subscribe to <b>{selectedPlan.name}</b> at <b>{selectedPlan.price}</b>
90
        </div>
91
      )}
92
      <Form submitRef={formSubmitRef} onSubmit={handleSubmit} defaultValues={initialValues} showButtons={false} autocomplete="off">
93
        <PlanExpandedForm setIsValid={setIsValid} />
94
      </Form>
95
      {isEdit ? (
1!
96
        <>
97
          <OrganizationPaymentSettings onComplete={handleUpgrade} updatingCard={updatingCard} setUpdatingCard={setUpdatingCard} isValid={isValid} />
98
        </>
99
      ) : (
100
        isValid &&
1!
101
        organization && (
102
          <>
103
            <h4>Card Details</h4>
104
            <CardSection
105
              organization={organization}
106
              onCardConfirmed={handleUpgrade}
NEW
107
              onSubmit={() => dispatch(startUpgrade(organization.id)).unwrap()}
×
108
              isSignUp
109
            />
110
          </>
111
        )
112
      )}
113
      {isEdit && !updatingCard && (
1!
114
        <div className="margin-top">
115
          <Button className="margin-right-small" onClick={onCloseClick}>
116
            Cancel
117
          </Button>
NEW
118
          <Button onClick={() => handleUpgrade()} color="secondary" variant="contained" disabled={!isValid}>
×
119
            Save
120
          </Button>
121
        </div>
122
      )}
123
    </Drawer>
124
  );
125
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc