diff --git a/app/assets/stylesheets/pages/home.scss b/app/assets/stylesheets/pages/home.scss index af0d12fc0e..3c5c9e7d76 100644 --- a/app/assets/stylesheets/pages/home.scss +++ b/app/assets/stylesheets/pages/home.scss @@ -1199,3 +1199,48 @@ h6 { .screenshot { max-width: 300px; } + +.payout-progress { + display: flex; + align-items: center; + + .icon { + width: 18px; + height: 18px; + border-radius: 50%; + + &.active { + background: $braveBrand; + } + + &.inactive { + border: 1px solid $braveGray-8; + } + + &.animated { + animation: colorchange 3s linear infinite; + + @keyframes colorchange + { + 0% {background: $braveBrand;} + 50% {background: $braveBrand-Light;} + 100% {background: $braveBrand;} + } + } + } + + progress { + width: auto; + flex-grow: 1; + height: 1px; + background: $braveGray-8; + -webkit-appearance: none; + } + progress::-webkit-progress-bar { + background: $braveGray-8; + } + progress::-webkit-progress-value { + background: $braveBrand; + } + +} diff --git a/app/controllers/publishers_controller.rb b/app/controllers/publishers_controller.rb index cc71a57bcf..e511b4458a 100644 --- a/app/controllers/publishers_controller.rb +++ b/app/controllers/publishers_controller.rb @@ -136,6 +136,10 @@ def home uphold_connection = UpholdConnection.create!(publisher: current_publisher) end + if payout_in_progress? || Date.today.day < 12 # Let's display the payout for 5 days after it should complete (on the 8th) + @payout_report = PayoutReport.where(final: true, manual: false).order(created_at: :desc).first + end + # ensure the wallet has been fetched, which will check if Uphold needs to be re-authorized # ToDo: rework this process? @wallet = current_publisher.wallet @@ -299,4 +303,8 @@ def require_verified_email return if current_publisher.email_verified? redirect_to(publisher_next_step_path(current_publisher), alert: t(".email_verification_required")) end + + def payout_in_progress? + !!Rails.cache.fetch('payout_in_progress') + end end diff --git a/app/helpers/payout_helper.rb b/app/helpers/payout_helper.rb new file mode 100644 index 0000000000..55e8e54464 --- /dev/null +++ b/app/helpers/payout_helper.rb @@ -0,0 +1,73 @@ +module PayoutHelper + + PREPARING = I18n.t('.publishers.payout_status.statuses.preparing') + REVIEWING = I18n.t('.publishers.payout_status.statuses.reviewing') + IN_PROGRESS = I18n.t('.publishers.payout_status.statuses.in_progress') + DONE = I18n.t('.publishers.payout_status.statuses.done') + + def icon_class(statuses, current, index) + selected = index <= statuses.find_index(current) + + return 'inactive' unless selected + return "animated" if statuses[index] == current && current != I18n.t(".publishers.payout_status.statuses.done") + + "active" + end + + def current_status_and_percent(report_created_at) + status = nil + progress_percentage = nil + + status = DONE if !Rails.cache.fetch('payout_in_progress') + days_ago = (Date.today - report_created_at.to_date).to_i if status.blank? + + if days_ago < 3 + status = PREPARING + progress_percentage = days_ago / 3.to_f + elsif days_ago < 7 + status = REVIEWING + progress_percentage = ((days_ago - 3.to_f) / 4) + elsif days_ago < 11 + status = IN_PROGRESS + progress_percentage = (((days_ago - 7.to_f) / 4)) + else + progress_percentage = 1 + status = DONE + end + + [status, progress_percentage] + end + + def percent_complete(created, selected_status, index) + statuses = I18n.t(".publishers.payout_status.statuses").values + selected = index <= statuses.find_index(selected_status) + + return 0 unless selected + return current_status_and_percent(created).second if selected_status == statuses[index] + 100 + end + + def payout_warning(payout_report) + found_payout = payout_report.potential_payments.where(publisher: current_publisher).first + + return I18n.t('.publishers.payout_status.information.not_found') if found_payout.blank? + + if found_payout.uphold_status.blank? + I18n.t('.publishers.payout_status.information.connect_uphold') + elsif found_payout.reauthorization_needed + I18n.t('.publishers.payout_status.information.reauthorize_uphold') + elsif found_payout.uphold_member.blank? + I18n.t('.publishers.payout_status.information.kyc_required') + end + end + + def payout_amount(payout_report) + amount = payout_report.potential_payments. + where(publisher: current_publisher). + select(&:amount). + map { |x| x.amount.to_d }. + sum + + (amount / 1E18).round(2) + end +end diff --git a/app/views/publishers/_payout_status.html.slim b/app/views/publishers/_payout_status.html.slim new file mode 100644 index 0000000000..d963753438 --- /dev/null +++ b/app/views/publishers/_payout_status.html.slim @@ -0,0 +1,38 @@ +.dashboard-panel--wrapper + .dashboard-panel--header= t('.heading') + div + .d-flex + = t('.amount') + small * + h4.font-weight-light + span= payout_amount(payout_report) + small.font-weight-light= " BAT" + + - payout_warning = payout_warning(payout_report) + - if payout_warning + .alert.alert-warning + = payout_warning + .font-weight-bold=t('.information.no_payment') + + - if payout_warning.blank? + / We're going to do some magic to make the user feel like things are actually happening + + .d-flex.my-3 + - statuses = t('.statuses').values + - current = current_status_and_percent(payout_report.created_at)[0] + - statuses.each_with_index do |status, index| + - last = index == (statuses.size - 1) + - selected = status == current + .payout-progress class=(last ? "" : "flex-grow-1") + .icon class=icon_class(statuses, current, index) + .px-2 class=(selected ? "" : "d-sm-block d-none") + = status + - unless last + progress.connector value=percent_complete(payout_report.created_at, current, index) class=icon_class(statuses, current, index) + + .pt-2 + = t('.description') + + + .mt-4 + small=t('.amount_description', time: payout_report.created_at.strftime("%Y-%m-%d")) diff --git a/app/views/publishers/home.html.slim b/app/views/publishers/home.html.slim index d20e3842e2..376f906407 100644 --- a/app/views/publishers/home.html.slim +++ b/app/views/publishers/home.html.slim @@ -92,6 +92,11 @@ script type="text/html" id="confirm_default_currency_modal_wrapper" .col-md.mb-4 .add-channel-cta = t ".add_channel_cta" + + - if @payout_report.present? + .row + .col-md.mb-4 + = render partial: 'payout_status', locals: { payout_report: @payout_report } .row - unless @publisher.excluded_from_payout? .col-md.mb-4 diff --git a/config/locales/en.yml b/config/locales/en.yml index 6c9dd26e88..300187ecc1 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -411,7 +411,22 @@ en: ago: " ago" support: "Brave Rewards Support" attachments: "Attachments" - + payout_status: + heading: Payout Progress + description: We're working hard to get your pending balance paid out. Please be patient while we prepare, review, and send your payouts. + statuses: + preparing: Preparing + reviewing: Reviewing + in_progress: In Progress + done: Done + amount: Amount + amount_description: "* The amount to be paid is based on our report generated at %{time}." + information: + not_found: At the time we generated the payout report, there were no pending payouts for your account. + connect_uphold: At the time we generated the payout report, you did not have your Uphold account connected. + reauthorize_uphold: At the time we generated the payout report, your Uphold account needed to be reconnected. + kyc_required: At the time we generated the payout report, your identity was not yet verified through Uphold. + no_payment: You will not be able to receive payment for this cycle. change_email: login_email: Login Email login_email_message: We need your valid email address for account access and recovery purposes.