pip install dash-credit-cards
- This package was developed to allow the developer to do something more enjoyable than coding… which is collect payment information from your users
Stylish in design this is an elegant solution for a professional in house for collecting users payment information.
This package actually offers 3 unique components:
DashCreditCards
- That fancy card you see at the top. Reference of the basis of this is: GitHub - amaroteam/react-credit-cards: Beautiful credit cards for your payment forms
DashCreditCardInput
- The middle component for entering the card information based on this repo: react-credit-card-input - npm
DashParallaxTilt
- That fancy tilt and shine used when hovering over the card. (also can be used on any component) built off this: @storybook/cli - Storybook
- Most of the props are setup for all these components so use these links to get an idea of what you should be able to access to specialize within the individual components
The example code I’ve built out was designed with dash-mantine-comonents
though you could easily replace it with html or dash-bootstrap-components
if you’d so like.
The code below uses Dash-Mantine-Components v0.13 or older
This is an example of how to get the project running in a quick development instance:
pip install dash-credit-cards dash-mantine-components==0.13.0a2
from dash import *
from dash_credit_cards import DashCreditCards, DashParallaxTilt, DashCreditCardInput
import dash_mantine_components as dmc
import json
app = Dash(__name__)
app.layout = html.Div([
DashParallaxTilt(
id='input',
children=[
DashCreditCards(
id='credit_card',
name='',
number='',
expiry='',
cvc='',
focused='',
preview=True,
issuer='visa',
locale={"valid": "VALID THRU"},
)
],
tiltReverse=True,
glareEnable=True,
glareMaxOpacity=0.8,
glareColor='#ffffff',
glareBorderRadius='20px',
glarePosition='bottom',
glareReverse=True,
),
dmc.Space(h=10),
dmc.Grid([
dmc.Col(lg=4, md=2, sm=1),
dmc.Col(dmc.TextInput(
id='first_name_form',
# label="First Name",
# style={"width": 200},
placeholder="Your First Name",
), lg=2, md=4, sm=5),
dmc.Col(dmc.TextInput(
id='last_name_form',
# label="Last Name",
# style={"width": 200},
placeholder="Your Last Name",
), lg=2, md=4, sm=5),
dmc.Col(lg=4, md=2, sm=1)
]),
dmc.Space(h=10),
html.Center(
DashCreditCardInput(
id='credit_card_input',
cardNumber='',
cvc='',
expiry='',
cardNumberInputProps={'value': ''},
cardExpiryInputProps={'value': ''},
cardCVCInputProps={'value': ''},
fieldClassName="input",
)
),
dmc.Space(h=10),
dmc.Grid([
dmc.Button("Clear", color="red", id="clear"),
dmc.Space(w=10),
dmc.Button("Submit", color="green", id="submit")
], justify="center"),
dmc.Space(h=10),
html.Center(
dmc.JsonInput(
id='json_output',
label="Your json data",
placeholder="This component will auto-size to fit the content.",
validationError="Invalid json",
formatOnBlur=True,
autosize=True,
minRows=4,
style={"width": "20vw"}
))
], style={'display': 'flex', 'flexDirection': 'column', 'justifyContent': 'center', 'height': '100vh'})
@callback(
Output('credit_card', 'name', allow_duplicate=True),
Output('credit_card', 'number', allow_duplicate=True),
Output('credit_card', 'expiry', allow_duplicate=True),
Output('credit_card', 'cvc', allow_duplicate=True),
Output('credit_card', 'issuer', allow_duplicate=True),
Output('credit_card', 'focused', allow_duplicate=True),
Input('first_name_form', 'value'),
Input('last_name_form', 'value'),
Input('credit_card_input', 'cardNumber'),
Input('credit_card_input', 'expiry'),
Input('credit_card_input', 'cvc'),
prevent_initial_call=True,
)
def update_credit_card(first_name, last_name, card_input, expiry, cvc):
if not any([card_input, expiry, cvc, first_name, last_name]):
return no_update
# Remove spaces and slash from expiry
expiry = expiry.replace(" ", "").replace("/", "")
first_digit = card_input[0] if card_input else ''
if first_digit == '2' or first_digit == '5':
issuer = 'mastercard'
elif first_digit == '4':
issuer = 'visa'
elif first_digit == '3':
issuer = 'amex'
elif first_digit == '6':
issuer = 'discover'
else:
issuer = ''
# print(expiry, cvc)
ctx = callback_context
triggered_component = ctx.triggered[0]["prop_id"].split(".")[0]
input_focus = None
if triggered_component == 'credit_card_input':
input_field = ctx.triggered[0]["prop_id"].split(".")[1]
if input_field == 'cvc':
input_focus = "cvc"
else:
input_focus = "name"
name = f"{first_name} {last_name}"
return name, card_input, expiry, cvc, issuer, input_focus
@callback(
Output('json_output', 'value'),
Output('first_name_form', 'value'),
Output('last_name_form', 'value'),
Output('credit_card_input', 'cardNumber'),
Output('credit_card_input', 'expiry'),
Output('credit_card_input', 'cvc'),
Output('credit_card', 'name'),
Output('credit_card', 'number'),
Output('credit_card', 'expiry'),
Output('credit_card', 'cvc'),
Output('credit_card', 'focused'),
Output('credit_card', 'issuer'),
Input('submit', 'n_clicks'),
Input('clear', 'n_clicks'),
State('first_name_form', 'value'),
State('last_name_form', 'value'),
State('credit_card_input', 'cardNumber'),
State('credit_card_input', 'expiry'),
State('credit_card_input', 'cvc'),
prevent_initial_call=True,
)
def update_output(submit_n_clicks, clear_n_clicks, first_name, last_name, card_number, expiry, cvc):
ctx = callback_context
if not ctx.triggered:
return no_update
button_id = ctx.triggered[0]['prop_id'].split('.')[0]
if button_id == 'submit':
data = {
'first_name': first_name,
'last_name': last_name,
'card_number': card_number,
'expiry': expiry,
'cvc': cvc,
}
return (json.dumps(data, indent=2), no_update, no_update, no_update, no_update, no_update, no_update, no_update,
no_update, no_update, no_update, no_update)
elif button_id == 'clear':
return '', '', '', '', '', '', '', '', '', '', '', ''
if __name__ == '__main__':
app.run_server(debug=True, port='2123')
You can find the full source code of this project on my github repo located here ():
Special thanks to @AnnMarieW, as she built out practically the same DashCreditCards
component like 4 years go and her repo was used as a refrence in some aspects of the design of this package.
Hope to see some rich developers within the plotly community. When you make it big make sure to throw some back to me