├── .github
├── CONTRIBUTING.md
├── FUNDING.yml
├── ISSUE_TEMPLATE
│ ├── bug.yml
│ └── config.yml
├── SECURITY.md
├── dependabot.yml
└── workflows
│ ├── dependabot-auto-merge.yml
│ ├── fix-php-code-styling.yml
│ └── tests.yml
├── .gitignore
├── .php-cs-fixer.dist.php
├── 3x1io-tomato-accounts.md
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── LICENSE.md
├── README.md
├── SECURITY.md
├── arts
├── 3x1io-tomato-accounts.jpg
├── account-column.png
├── accounts-list.png
├── change-password.png
├── edit-account.png
└── send-notifications.png
├── composer.json
├── composer.lock
├── config
├── .gitkeep
└── filament-accounts.php
├── database
└── migrations
│ ├── .gitkeep
│ ├── 2023_02_13_134629_create_accounts_table.php
│ └── 2024_10_28_143941_add_media_if_not_exists_table.php
├── module.json
├── phpunit.xml
├── pint.json
├── publish
└── Account.php
├── resources
├── js
│ └── .gitkeep
├── lang
│ ├── .gitkeep
│ ├── ar
│ │ └── messages.php
│ └── en
│ │ └── messages.php
└── views
│ ├── .gitkeep
│ └── components
│ └── account-column.blade.php
├── src
├── Components
│ └── AccountColumn.php
├── Console
│ ├── .gitkeep
│ └── FilamentAccountsInstall.php
├── Export
│ └── ExportAccounts.php
├── Facades
│ └── FilamentAccounts.php
├── Filament
│ └── Resources
│ │ ├── AccountResource.php
│ │ └── AccountResource
│ │ ├── Actions
│ │ ├── Components
│ │ │ ├── .gitkeep
│ │ │ ├── Action.php
│ │ │ ├── CreateAction.php
│ │ │ ├── DeleteAction.php
│ │ │ ├── EditAction.php
│ │ │ ├── TypesAction.php
│ │ │ └── ViewAction.php
│ │ ├── Contracts
│ │ │ ├── .gitkeep
│ │ │ └── CanRegister.php
│ │ ├── CreatePageActions.php
│ │ ├── EditPageActions.php
│ │ ├── ManagePageActions.php
│ │ └── ViewPageActions.php
│ │ ├── Form
│ │ ├── AccountForm.php
│ │ └── Components
│ │ │ ├── .gitkeep
│ │ │ ├── Address.php
│ │ │ ├── Avatar.php
│ │ │ ├── Component.php
│ │ │ ├── Email.php
│ │ │ ├── IsActive.php
│ │ │ ├── IsLogin.php
│ │ │ ├── LoginBy.php
│ │ │ ├── Name.php
│ │ │ ├── Password.php
│ │ │ ├── PasswordConfirmation.php
│ │ │ ├── Phone.php
│ │ │ └── Type.php
│ │ ├── InfoList
│ │ ├── AccountInfoList.php
│ │ └── Entries
│ │ │ ├── .gitkeep
│ │ │ ├── Address.php
│ │ │ ├── Avatar.php
│ │ │ ├── Email.php
│ │ │ ├── Entry.php
│ │ │ ├── IsActive.php
│ │ │ ├── IsLogin.php
│ │ │ ├── LoginBy.php
│ │ │ ├── Name.php
│ │ │ ├── Phone.php
│ │ │ └── Type.php
│ │ ├── Pages
│ │ ├── AccountTypes.php
│ │ ├── CreateAccount.php
│ │ ├── EditAccount.php
│ │ ├── ListAccounts.php
│ │ ├── ManageAccounts.php
│ │ └── ViewAccount.php
│ │ └── Table
│ │ ├── AccountActions.php
│ │ ├── AccountBulkActions.php
│ │ ├── AccountFilters.php
│ │ ├── AccountHeaderActions.php
│ │ ├── AccountTable.php
│ │ ├── Actions
│ │ ├── .gitkeep
│ │ ├── Action.php
│ │ ├── ChangePasswordAction.php
│ │ ├── DeleteAction.php
│ │ ├── EditAction.php
│ │ ├── ImpersonateAction.php
│ │ └── ViewAction.php
│ │ ├── BulkActions
│ │ ├── .gitkeep
│ │ ├── Action.php
│ │ └── DeleteAction.php
│ │ ├── Columns
│ │ ├── .gitkeep
│ │ ├── Account.php
│ │ ├── Column.php
│ │ ├── CreatedAt.php
│ │ ├── Email.php
│ │ ├── Id.php
│ │ ├── IsActive.php
│ │ ├── IsLogin.php
│ │ ├── Name.php
│ │ ├── Phone.php
│ │ ├── Type.php
│ │ └── UpdatedAt.php
│ │ ├── Filters
│ │ ├── .gitkeep
│ │ ├── Filter.php
│ │ ├── IsActive.php
│ │ ├── IsLogin.php
│ │ ├── Trashed.php
│ │ └── Type.php
│ │ └── HeaderActions
│ │ ├── .gitkeep
│ │ ├── Action.php
│ │ ├── ExportAction.php
│ │ └── ImportAction.php
├── FilamentAccountsPlugin.php
├── FilamentAccountsServiceProvider.php
├── Import
│ └── ImportAccounts.php
├── Models
│ ├── .gitkeep
│ └── Account.php
└── Services
│ └── FilamentAccountsServices.php
└── tests
├── Pest.php
├── database
├── database.sqlite
└── factories
│ ├── AccountFactory.php
│ └── UserFactory.php
└── src
├── AccountResourceTest.php
├── AdminPanelProvider.php
├── DebugTest.php
├── Models
├── Account.php
└── User.php
├── PluginTest.php
└── TestCase.php
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | Contributions are **welcome** and will be fully **credited**.
4 |
5 | Please read and understand the contribution guide before creating an issue or pull request.
6 |
7 | ## Etiquette
8 |
9 | This project is open source, and as such, the maintainers give their free time to build and maintain the source code
10 | held within. They make the code freely available in the hope that it will be of use to other developers. It would be
11 | extremely unfair for them to suffer abuse or anger for their hard work.
12 |
13 | Please be considerate towards maintainers when raising issues or presenting pull requests. Let's show the
14 | world that developers are civilized and selfless people.
15 |
16 | It's the duty of the maintainer to ensure that all submissions to the project are of sufficient
17 | quality to benefit the project. Many developers have different skills, strengths, and weaknesses. Respect the maintainer's decision, and do not be upset or abusive if your submission is not used.
18 |
19 | ## Viability
20 |
21 | When requesting or submitting new features, first consider whether it might be useful to others. Open
22 | source projects are used by many developers, who may have entirely different needs to your own. Think about
23 | whether or not your feature is likely to be used by other users of the project.
24 |
25 | ## Procedure
26 |
27 | Before filing an issue:
28 |
29 | - Attempt to replicate the problem, to ensure that it wasn't a coincidental incident.
30 | - Check to make sure your feature suggestion isn't already present within the project.
31 | - Check the pull requests tab to ensure that the bug doesn't have a fix in progress.
32 | - Check the pull requests tab to ensure that the feature isn't already in progress.
33 |
34 | Before submitting a pull request:
35 |
36 | - Check the codebase to ensure that your feature doesn't already exist.
37 | - Check the pull requests to ensure that another person hasn't already submitted the feature or fix.
38 |
39 | ## Requirements
40 |
41 | If the project maintainer has any additional requirements, you will find them listed here.
42 |
43 | - **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](https://pear.php.net/package/PHP_CodeSniffer).
44 |
45 | - **Add tests!** - Your patch won't be accepted if it doesn't have tests.
46 |
47 | - **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date.
48 |
49 | - **Consider our release cycle** - We try to follow [SemVer v2.0.0](https://semver.org/). Randomly breaking public APIs is not an option.
50 |
51 | - **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
52 |
53 | - **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](https://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting.
54 |
55 | **Happy coding**!
56 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: [3x1io]
2 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug.yml:
--------------------------------------------------------------------------------
1 | name: Bug Report
2 | description: Report an Issue or Bug with the Package
3 | title: "[Bug]: "
4 | labels: ["bug"]
5 | body:
6 | - type: markdown
7 | attributes:
8 | value: |
9 | We're sorry to hear you have a problem. Can you help us solve it by providing the following details.
10 | - type: textarea
11 | id: what-happened
12 | attributes:
13 | label: What happened?
14 | description: What did you expect to happen?
15 | placeholder: I cannot currently do X thing because when I do, it breaks X thing.
16 | validations:
17 | required: true
18 | - type: textarea
19 | id: how-to-reproduce
20 | attributes:
21 | label: How to reproduce the bug
22 | description: How did this occur, please add any config values used and provide a set of reliable steps if possible.
23 | placeholder: When I do X I see Y.
24 | validations:
25 | required: true
26 | - type: input
27 | id: package-version
28 | attributes:
29 | label: Package Version
30 | description: What version of our Package are you running? Please be as specific as possible
31 | placeholder: 2.0.0
32 | validations:
33 | required: true
34 | - type: input
35 | id: php-version
36 | attributes:
37 | label: PHP Version
38 | description: What version of PHP are you running? Please be as specific as possible
39 | placeholder: 8.2.0
40 | validations:
41 | required: true
42 | - type: input
43 | id: laravel-version
44 | attributes:
45 | label: Laravel Version
46 | description: What version of Laravel are you running? Please be as specific as possible
47 | placeholder: 9.0.0
48 | validations:
49 | required: true
50 | - type: dropdown
51 | id: operating-systems
52 | attributes:
53 | label: Which operating systems does with happen with?
54 | description: You may select more than one.
55 | multiple: true
56 | options:
57 | - macOS
58 | - Windows
59 | - Linux
60 | - type: textarea
61 | id: notes
62 | attributes:
63 | label: Notes
64 | description: Use this field to provide any other notes that you feel might be relevant to the issue.
65 | validations:
66 | required: false
67 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 | - name: Ask a question
4 | url: https://github.com/tomatophp/filament-accounts/discussions/new?category=q-a
5 | about: Ask the community for help
6 | - name: Request a feature
7 | url: https://github.com/tomatophp/filament-accounts/discussions/new?category=ideas
8 | about: Share ideas for new features
9 | - name: Report a security issue
10 | url: https://github.com/tomatophp/filament-accounts/security/policy
11 | about: Learn how to notify us for sensitive bugs
12 |
--------------------------------------------------------------------------------
/.github/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | If you discover any security related issues, please email info@3x1.io instead of using the issue tracker.
4 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # Please see the documentation for all configuration options:
2 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
3 |
4 | version: 2
5 | updates:
6 |
7 | - package-ecosystem: "github-actions"
8 | directory: "/"
9 | schedule:
10 | interval: "weekly"
11 | labels:
12 | - "dependencies"
13 |
--------------------------------------------------------------------------------
/.github/workflows/dependabot-auto-merge.yml:
--------------------------------------------------------------------------------
1 | name: dependabot-auto-merge
2 | on: pull_request_target
3 |
4 | permissions:
5 | pull-requests: write
6 | contents: write
7 |
8 | jobs:
9 | dependabot:
10 | runs-on: ubuntu-latest
11 | if: ${{ github.actor == 'dependabot[bot]' }}
12 | steps:
13 |
14 | - name: Dependabot metadata
15 | id: metadata
16 | uses: dependabot/fetch-metadata@v2.4.0
17 | with:
18 | github-token: "${{ secrets.GITHUB_TOKEN }}"
19 |
20 | - name: Auto-merge Dependabot PRs for semver-minor updates
21 | if: ${{steps.metadata.outputs.update-type == 'version-update:semver-minor'}}
22 | run: gh pr merge --auto --merge "$PR_URL"
23 | env:
24 | PR_URL: ${{github.event.pull_request.html_url}}
25 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
26 |
27 | - name: Auto-merge Dependabot PRs for semver-patch updates
28 | if: ${{steps.metadata.outputs.update-type == 'version-update:semver-patch'}}
29 | run: gh pr merge --auto --merge "$PR_URL"
30 | env:
31 | PR_URL: ${{github.event.pull_request.html_url}}
32 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
33 |
--------------------------------------------------------------------------------
/.github/workflows/fix-php-code-styling.yml:
--------------------------------------------------------------------------------
1 | name: 'PHP Code Styling'
2 |
3 | on:
4 | workflow_dispatch:
5 | push:
6 | branches:
7 | - master
8 | paths:
9 | - '**.php'
10 |
11 | permissions:
12 | contents: write
13 |
14 | jobs:
15 | lint:
16 | runs-on: ubuntu-latest
17 | steps:
18 | - name: Checkout code
19 | uses: actions/checkout@v4
20 | with:
21 | ref: ${{ github.head_ref }}
22 |
23 | - name: Fix PHP code style issues
24 | uses: aglipanci/laravel-pint-action@v2
25 |
26 | - name: Commit changes
27 | uses: stefanzweifel/git-auto-commit-action@v5
28 | with:
29 | commit_message: "Format Code"
30 | commit_user_name: 'GitHub Actions'
31 |
--------------------------------------------------------------------------------
/.github/workflows/tests.yml:
--------------------------------------------------------------------------------
1 | name: "Tests"
2 |
3 | on:
4 | workflow_dispatch:
5 | push:
6 | branches:
7 | - master
8 | paths:
9 | - '**.php'
10 | pull_request:
11 | types:
12 | - opened
13 | - synchronize
14 | branches:
15 | - master
16 | paths:
17 | - '**.php'
18 | - '.github/workflows/tests.yml'
19 | - 'phpunit.xml.dist'
20 | - 'composer.json'
21 | - 'composer.lock'
22 |
23 | jobs:
24 | test:
25 | runs-on: ${{ matrix.os }}
26 | strategy:
27 | fail-fast: true
28 | matrix:
29 | os: [ubuntu-latest]
30 | php: [8.3, 8.2, 8.1]
31 | laravel: [11.*, 10.*]
32 | stability: [prefer-stable]
33 | include:
34 | - laravel: 11.*
35 | testbench: 9.*
36 | carbon: 3.*
37 | collision: 8.*
38 | - laravel: 10.*
39 | testbench: 8.*
40 | carbon: 2.*
41 | collision: 7.*
42 | exclude:
43 | - laravel: 11.*
44 | php: 8.1
45 | name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }}
46 | steps:
47 | - name: Checkout Code
48 | uses: actions/checkout@v4
49 |
50 | - name: Cache Dependencies
51 | uses: actions/cache@v4
52 | with:
53 | path: ~/.composer/cache/files
54 | key: dependencies-laravel-${{ matrix.laravel }}-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
55 |
56 | - name: Setup PHP
57 | uses: shivammathur/setup-php@v2
58 | with:
59 | php-version: ${{ matrix.php }}
60 | extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo
61 | coverage: none
62 |
63 | - name: Install Dependencies
64 | run: |
65 | echo "::add-matcher::${{ runner.tool_cache }}/php.json"
66 | echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
67 |
68 | - name: Install Dependencies
69 | run: |
70 | composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" "nesbot/carbon:${{ matrix.carbon }}" "nunomaduro/collision:${{ matrix.collision }}" --no-interaction --no-update
71 | composer update --${{ matrix.stability }} --prefer-dist --no-interaction
72 |
73 | - name: Execute tests
74 | run: vendor/bin/pest
75 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.phpunit.cache
2 | /node_modules
3 | /public/build
4 | /public/hot
5 | /public/storage
6 | /storage/*.key
7 | /storage/pail
8 | /vendor
9 | .env
10 | .env.backup
11 | .env.production
12 | .phpactor.json
13 | .phpunit.result.cache
14 | .DS_Store
15 | Homestead.json
16 | Homestead.yaml
17 | auth.json
18 | npm-debug.log
19 | yarn-error.log
20 | /.fleet
21 | /.idea
22 | /.vscode
23 | /.zed
24 |
--------------------------------------------------------------------------------
/.php-cs-fixer.dist.php:
--------------------------------------------------------------------------------
1 | notPath('bootstrap/*')
5 | ->notPath('storage/*')
6 | ->notPath('resources/view/mail/*')
7 | ->in([
8 | __DIR__ . '/src',
9 | __DIR__ . '/tests',
10 | ])
11 | ->name('*.php')
12 | ->notName('*.blade.php')
13 | ->ignoreDotFiles(true)
14 | ->ignoreVCS(true);
15 |
16 | return (new PhpCsFixer\Config())
17 | ->setRules([
18 | '@PSR2' => true,
19 | 'array_syntax' => ['syntax' => 'short'],
20 | 'ordered_imports' => ['sort_algorithm' => 'alpha'],
21 | 'no_unused_imports' => true,
22 | 'not_operator_with_successor_space' => true,
23 | 'trailing_comma_in_multiline' => true,
24 | 'phpdoc_scalar' => true,
25 | 'unary_operator_spaces' => true,
26 | 'binary_operator_spaces' => true,
27 | 'blank_line_before_statement' => [
28 | 'statements' => ['break', 'continue', 'declare', 'return', 'throw', 'try'],
29 | ],
30 | 'phpdoc_single_line_var_spacing' => true,
31 | 'phpdoc_var_without_name' => true,
32 | 'method_argument_space' => [
33 | 'on_multiline' => 'ensure_fully_multiline',
34 | 'keep_multiple_spaces_after_comma' => true,
35 | ]
36 | ])
37 | ->setFinder($finder);
38 |
--------------------------------------------------------------------------------
/3x1io-tomato-accounts.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Accounts Builder
3 | slug: 3x1io-tomato-accounts
4 | author_slug: 3x1io
5 | categories: [developer-tool]
6 | description: Manage your multi accounts inside your app using 1 table with multi auth and a lot of integrations
7 | discord_url:
8 | docs_url: https://raw.githubusercontent.com/tomatophp/filament-accounts/master/README.md
9 | github_repository: tomatophp/filament-accounts
10 | has_dark_theme: true
11 | has_translations: true
12 | versions: [3]
13 | publish_date: 2024-04-18
14 | ---
15 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomatophp/filament-accounts/7f5f11765de2781e119f826163e9dcb7a8c1a347/CHANGELOG.md
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, religion, or sexual identity
10 | and orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | * Demonstrating empathy and kindness toward other people
21 | * Being respectful of differing opinions, viewpoints, and experiences
22 | * Giving and gracefully accepting constructive feedback
23 | * Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | * Focusing on what is best not just for us as individuals, but for the
26 | overall community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | * The use of sexualized language or imagery, and sexual attention or
31 | advances of any kind
32 | * Trolling, insulting or derogatory comments, and personal or political attacks
33 | * Public or private harassment
34 | * Publishing others' private information, such as a physical or email
35 | address, without their explicit permission
36 | * Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards of
42 | acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies when
54 | an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official e-mail address,
56 | posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported to the community leaders responsible for enforcement at
63 | .
64 | All complaints will be reviewed and investigated promptly and fairly.
65 |
66 | All community leaders are obligated to respect the privacy and security of the
67 | reporter of any incident.
68 |
69 | ## Enforcement Guidelines
70 |
71 | Community leaders will follow these Community Impact Guidelines in determining
72 | the consequences for any action they deem in violation of this Code of Conduct:
73 |
74 | ### 1. Correction
75 |
76 | **Community Impact**: Use of inappropriate language or other behavior deemed
77 | unprofessional or unwelcome in the community.
78 |
79 | **Consequence**: A private, written warning from community leaders, providing
80 | clarity around the nature of the violation and an explanation of why the
81 | behavior was inappropriate. A public apology may be requested.
82 |
83 | ### 2. Warning
84 |
85 | **Community Impact**: A violation through a single incident or series
86 | of actions.
87 |
88 | **Consequence**: A warning with consequences for continued behavior. No
89 | interaction with the people involved, including unsolicited interaction with
90 | those enforcing the Code of Conduct, for a specified period of time. This
91 | includes avoiding interactions in community spaces as well as external channels
92 | like social media. Violating these terms may lead to a temporary or
93 | permanent ban.
94 |
95 | ### 3. Temporary Ban
96 |
97 | **Community Impact**: A serious violation of community standards, including
98 | sustained inappropriate behavior.
99 |
100 | **Consequence**: A temporary ban from any sort of interaction or public
101 | communication with the community for a specified period of time. No public or
102 | private interaction with the people involved, including unsolicited interaction
103 | with those enforcing the Code of Conduct, is allowed during this period.
104 | Violating these terms may lead to a permanent ban.
105 |
106 | ### 4. Permanent Ban
107 |
108 | **Community Impact**: Demonstrating a pattern of violation of community
109 | standards, including sustained inappropriate behavior, harassment of an
110 | individual, or aggression toward or disparagement of classes of individuals.
111 |
112 | **Consequence**: A permanent ban from any sort of public interaction within
113 | the community.
114 |
115 | ## Attribution
116 |
117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118 | version 2.0, available at
119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
120 |
121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct
122 | enforcement ladder](https://github.com/mozilla/diversity).
123 |
124 | [homepage]: https://www.contributor-covenant.org
125 |
126 | For answers to common questions about this code of conduct, see the FAQ at
127 | https://www.contributor-covenant.org/faq. Translations are available at
128 | https://www.contributor-covenant.org/translations.
129 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # Filament Accounts Builder
4 |
5 | [](https://github.com/tomatophp/filament-accounts/actions/workflows/dependabot/dependabot-updates)
6 | [](https://github.com/tomatophp/filament-accounts/actions/workflows/fix-php-code-styling.yml)
7 | [](https://github.com/tomatophp/filament-accounts/actions/workflows/tests.yml)
8 | [](https://packagist.org/packages/tomatophp/filament-accounts)
9 | [](https://packagist.org/packages/tomatophp/filament-accounts)
10 | [](https://packagist.org/packages/tomatophp/filament-accounts)
11 |
12 | Manage your multi accounts inside your app using 1 table with multi auth and a lot of integrations
13 |
14 | > [!CAUTION]
15 | > Don't update to v2.3 if you are using v2.2 or less because you will lose some features but you can update and use this features from integrated packages.
16 |
17 | ## Screenshots
18 |
19 | 
20 | 
21 | 
22 | 
23 |
24 | ## Features
25 |
26 | - [x] Accounts Manager
27 | - [x] Account Types `not tested`
28 | - [x] Account Login By `not tested`
29 | - [x] Account Active/Block `not tested`
30 | - [x] Account Avatar `not tested`
31 | - [x] Account Impersonate Integration `not tested`
32 | - [x] Account Table Column `not tested`
33 | - [x] Export `not tested`
34 | - [x] Import `not tested`
35 | - [ ] Account Filament Alerts Integration
36 | - [ ] Account Teams
37 | - [ ] Google Contacts Integrations
38 |
39 | ## Use Case
40 |
41 | you can use this package if you like to build a CRM or a multi-accounts app
42 |
43 | ## Installation
44 |
45 | ```bash
46 | composer require tomatophp/filament-accounts
47 | ```
48 |
49 | after install your package please run this command
50 |
51 | ```bash
52 | php artisan filament-accounts:install
53 | ```
54 |
55 | if you are not using this package as a plugin please register the plugin on `/app/Providers/Filament/AdminPanelProvider.php`
56 |
57 | ```php
58 | ->plugin(\TomatoPHP\FilamentAccounts\FilamentAccountsPlugin::make())
59 | ```
60 |
61 | ## Publish Account Model
62 |
63 | you can publish your account model to add other relations or implement some interfaces by using this command
64 |
65 | ```bash
66 | php artisan vendor:publish --tag="filament-accounts-model"
67 | ```
68 |
69 | now go to your `filament-accounts.php` config file and change the model value to the new one.
70 |
71 | if you don't find it you can publish it
72 |
73 | ```
74 | php artisan vendor:publish --tag="filament-accounts-config"
75 | ```
76 |
77 | ## Add Accounts Guard
78 |
79 | now you need to add a new guard to your auth.php config like this
80 |
81 | ```php
82 | [
91 | "notifications" => false,
92 | "loginBy" => false,
93 | "avatar" => false,
94 | "types" => false,
95 | "teams" => false,
96 | "impersonate" => [
97 | 'active'=> false,
98 | 'redirect' => '/app',
99 | ],
100 | ],
101 |
102 | /*
103 | * Accounts Configurations
104 | *
105 | * login_by: Login By Phone or Email
106 | */
107 | "login_by" => "email",
108 |
109 | /*
110 | * Accounts Configurations
111 | *
112 | * model: User Model Class
113 | */
114 | "model" => \TomatoPHP\FilamentAccounts\Models\Account::class,
115 |
116 |
117 |
118 | ];
119 |
120 | ```
121 |
122 | ## Usage
123 |
124 | this plugin makes it easy to make a starting point for your app if this app has customers to manage
125 |
126 | but here is the problem, every app has a different way of managing customers, so we built a Facade service to control the way you want to manage your customers
127 |
128 | ### Use Avatar
129 |
130 | add this method to your plugin in `AdminPanelProvider.php`
131 |
132 | ```php
133 | ->plugin(
134 | \TomatoPHP\FilamentAccounts\FilamentAccountsPlugin::make()
135 | ->useAvatar()
136 | )
137 | ```
138 |
139 | ## Hide Resource
140 |
141 | just allow `useResource->()` on the plugin
142 |
143 | ```php
144 | ->plugin(\TomatoPHP\FilamentAccounts\FilamentAccountsPlugin::make()
145 | ->useResource(false)
146 | )
147 | ```
148 |
149 | ## Use Filament Types
150 |
151 | just allow `->useResource()` on the plugin
152 |
153 | ```php
154 | ->plugin(\TomatoPHP\FilamentAccounts\FilamentAccountsPlugin::make()
155 | ->useResource()
156 | )
157 | ```
158 |
159 | ## Show Address Field
160 |
161 | you can show or hide address field on the create or edit form by using this code
162 |
163 | ```php
164 |
165 | ->plugin(\TomatoPHP\FilamentAccounts\FilamentAccountsPlugin::make()
166 | ->showAddressField()
167 | )
168 | ```
169 |
170 | ## Show Type Field
171 |
172 | you can show or hide type field on the create or edit form by using this code
173 |
174 | ```php
175 |
176 | ->plugin(\TomatoPHP\FilamentAccounts\FilamentAccountsPlugin::make()
177 | ->showTypeField()
178 | )
179 | ```
180 |
181 | ## Attach Relation To Accounts
182 |
183 | you can attach a new relation to the accounts relations manager by just passing the relation class to the facade service method
184 |
185 | ```php
186 | use TomatoPHP\FilamentAccounts\Facades\FilamentAccounts;
187 |
188 | public function boot()
189 | {
190 | FilamentAccounts::register([
191 | AccountOrdersRelationManager::make()
192 | ]);
193 | }
194 | ```
195 |
196 | ## Use Export & Import Actions
197 |
198 | now on your main panel provider add `->useExport()` , `->useImport()` to the plugin
199 |
200 | ```php
201 | ->plugin(\TomatoPHP\FilamentAccounts\FilamentAccountsPlugin::make()
202 | ...
203 | ->useExport()
204 | ->useImport()
205 | )
206 | ```
207 |
208 | ## Use Account Column
209 |
210 | 
211 |
212 | you can use the account column in any table by using this code
213 |
214 | ```php
215 | public static function table(Table $table): Table
216 | {
217 | return $table
218 | ->columns([
219 | AccountColumn::make('account.id'),
220 | ]);
221 | }
222 | ```
223 |
224 | just pass the account id to the column
225 |
226 |
227 | ### Use Filament Impersonate
228 |
229 | you can use the impersonate to impersonate the user by install it first
230 |
231 | ```bash
232 | composer require stechstudio/filament-impersonate
233 | ```
234 |
235 | now on your main panel provider add `->useImpersonate()` , `->impersonateRedirect('/app')` to the plugin
236 |
237 | ```php
238 | ->plugin(\TomatoPHP\FilamentAccounts\FilamentAccountsPlugin::make()
239 | ...
240 | ->useImpersonate()
241 | ->impersonateRedirect('/app')
242 | )
243 | ```
244 |
245 | now clear your config
246 |
247 | ```bash
248 | php artisan config:cache
249 | ```
250 |
251 | for more information check the [Filament Impersonate](https://github.com/stechstudio/filament-impersonate)
252 |
253 | ## Testing
254 |
255 | if you like to run `PEST` testing just use this command
256 |
257 | ```bash
258 | composer test
259 | ```
260 |
261 | ## Code Style
262 |
263 | if you like to fix the code style just use this command
264 |
265 | ```bash
266 | composer format
267 | ```
268 |
269 | ## PHPStan
270 |
271 | if you like to check the code by `PHPStan` just use this command
272 |
273 | ```bash
274 | composer analyse
275 | ```
276 |
277 | ## Other Filament Packages
278 |
279 | Checkout our [Awesome TomatoPHP](https://github.com/tomatophp/awesome)
280 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomatophp/filament-accounts/7f5f11765de2781e119f826163e9dcb7a8c1a347/SECURITY.md
--------------------------------------------------------------------------------
/arts/3x1io-tomato-accounts.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomatophp/filament-accounts/7f5f11765de2781e119f826163e9dcb7a8c1a347/arts/3x1io-tomato-accounts.jpg
--------------------------------------------------------------------------------
/arts/account-column.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomatophp/filament-accounts/7f5f11765de2781e119f826163e9dcb7a8c1a347/arts/account-column.png
--------------------------------------------------------------------------------
/arts/accounts-list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomatophp/filament-accounts/7f5f11765de2781e119f826163e9dcb7a8c1a347/arts/accounts-list.png
--------------------------------------------------------------------------------
/arts/change-password.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomatophp/filament-accounts/7f5f11765de2781e119f826163e9dcb7a8c1a347/arts/change-password.png
--------------------------------------------------------------------------------
/arts/edit-account.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomatophp/filament-accounts/7f5f11765de2781e119f826163e9dcb7a8c1a347/arts/edit-account.png
--------------------------------------------------------------------------------
/arts/send-notifications.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomatophp/filament-accounts/7f5f11765de2781e119f826163e9dcb7a8c1a347/arts/send-notifications.png
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tomatophp/filament-accounts",
3 | "type": "library",
4 | "description": "Manage your multi accounts inside your app using 1 table with multi auth and a lot of integrations",
5 | "keywords": [
6 | "php",
7 | "laravel",
8 | "accounts",
9 | "crm",
10 | "contacts",
11 | "notifications",
12 | "api",
13 | "filament"
14 | ],
15 | "license": "MIT",
16 | "autoload": {
17 | "psr-4": {
18 | "TomatoPHP\\FilamentAccounts\\": "src/"
19 | }
20 | },
21 | "autoload-dev": {
22 | "psr-4": {
23 | "TomatoPHP\\FilamentAccounts\\Tests\\": "tests/src/",
24 | "TomatoPHP\\FilamentAccounts\\Tests\\Database\\Factories\\": "tests/database/factories"
25 | }
26 | },
27 | "extra": {
28 | "laravel": {
29 | "providers": [
30 | "TomatoPHP\\FilamentAccounts\\FilamentAccountsServiceProvider"
31 | ]
32 | }
33 | },
34 | "authors": [
35 | {
36 | "name": "Fady Mondy",
37 | "email": "info@3x1.io"
38 | }
39 | ],
40 | "scripts": {
41 | "testbench": "vendor/bin/testbench package:discover --ansi",
42 | "analyse": "vendor/bin/phpstan analyse src tests",
43 | "test": "vendor/bin/pest",
44 | "test-coverage": "vendor/bin/pest --coverage",
45 | "format": "vendor/bin/pint"
46 | },
47 | "config": {
48 | "sort-packages": true,
49 | "allow-plugins": {
50 | "pestphp/pest-plugin": true,
51 | "phpstan/extension-installer": true
52 | }
53 | },
54 | "require": {
55 | "php": "^8.1|^8.2",
56 | "tomatophp/console-helpers": "^1.1",
57 | "filament/filament": "^3.2",
58 | "filament/notifications": "^3.2",
59 | "tomatophp/filament-types": "^2.0",
60 | "maatwebsite/excel": "^3.1",
61 | "filament/spatie-laravel-media-library-plugin": "^3.2"
62 | },
63 | "require-dev": {
64 | "laravel/pint": "^1.18",
65 | "livewire/livewire": "^2.10|^3.0",
66 | "nunomaduro/larastan": "^2.9",
67 | "orchestra/testbench": "^9.5",
68 | "pestphp/pest": "^2.36",
69 | "pestphp/pest-plugin-laravel": "^2.4",
70 | "pestphp/pest-plugin-livewire": "^2.1",
71 | "phpstan/extension-installer": "^1.4",
72 | "phpstan/phpstan-deprecation-rules": "^1.2",
73 | "phpstan/phpstan-phpunit": "^1.4"
74 | },
75 | "version": "2.3.3"
76 | }
77 |
--------------------------------------------------------------------------------
/config/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomatophp/filament-accounts/7f5f11765de2781e119f826163e9dcb7a8c1a347/config/.gitkeep
--------------------------------------------------------------------------------
/config/filament-accounts.php:
--------------------------------------------------------------------------------
1 | [
10 | 'loginBy' => false,
11 | 'avatar' => false,
12 | 'types' => false,
13 | 'teams' => false,
14 | 'impersonate' => [
15 | 'active' => false,
16 | 'redirect' => '/app',
17 | ],
18 | ],
19 |
20 | /*
21 | * Accounts Configurations
22 | *
23 | * login_by: Login By Phone or Email
24 | */
25 | 'login_by' => 'email',
26 |
27 | /*
28 | * Accounts Configurations
29 | *
30 | * model: User Model Class
31 | */
32 | 'model' => \TomatoPHP\FilamentAccounts\Models\Account::class,
33 |
34 | /*
35 | * Use Simple Resource
36 | *
37 | * simple: Enable/Disable Simple Resource
38 | */
39 | 'simple' => true,
40 |
41 | /*
42 | * Custom Resource
43 | *
44 | * to custom resource classes
45 | */
46 | 'resource' => [
47 | 'table' => [
48 | 'class' => \TomatoPHP\FilamentAccounts\Filament\Resources\AccountResource\Table\AccountTable::class,
49 | 'filters' => \TomatoPHP\FilamentAccounts\Filament\Resources\AccountResource\Table\AccountFilters::class,
50 | 'actions' => \TomatoPHP\FilamentAccounts\Filament\Resources\AccountResource\Table\AccountActions::class,
51 | 'bulkActions' => \TomatoPHP\FilamentAccounts\Filament\Resources\AccountResource\Table\AccountBulkActions::class,
52 | 'headerActions' => \TomatoPHP\FilamentAccounts\Filament\Resources\AccountResource\Table\AccountHeaderActions::class,
53 | ],
54 | 'form' => [
55 | 'class' => \TomatoPHP\FilamentAccounts\Filament\Resources\AccountResource\Form\AccountForm::class,
56 | ],
57 | 'infolist' => [
58 | 'class' => \TomatoPHP\FilamentAccounts\Filament\Resources\AccountResource\InfoList\AccountInfoList::class,
59 | ],
60 | 'pages' => [
61 | 'list' => \TomatoPHP\FilamentAccounts\Filament\Resources\AccountResource\Actions\ManagePageActions::class,
62 | 'create' => \TomatoPHP\FilamentAccounts\Filament\Resources\AccountResource\Actions\CreatePageActions::class,
63 | 'edit' => \TomatoPHP\FilamentAccounts\Filament\Resources\AccountResource\Actions\EditPageActions::class,
64 | 'view' => \TomatoPHP\FilamentAccounts\Filament\Resources\AccountResource\Actions\ViewPageActions::class,
65 | ],
66 | ],
67 | ];
68 |
--------------------------------------------------------------------------------
/database/migrations/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomatophp/filament-accounts/7f5f11765de2781e119f826163e9dcb7a8c1a347/database/migrations/.gitkeep
--------------------------------------------------------------------------------
/database/migrations/2023_02_13_134629_create_accounts_table.php:
--------------------------------------------------------------------------------
1 | id();
18 | $table->string('type')->default('account')->nullable();
19 | $table->unsignedBigInteger('parent_id')->nullable();
20 |
21 | $table->string('name')->nullable();
22 | $table->string('username')->unique();
23 | $table->string('email')->nullable();
24 | $table->string('phone')->nullable();
25 | $table->string('loginBy')->default('email')->nullable();
26 | $table->text('address')->nullable();
27 | $table->string('lang', 10)->nullable();
28 |
29 | // Login
30 | $table->string('password')->nullable();
31 | $table->string('otp_code')->nullable();
32 | $table->dateTime('otp_activated_at')->nullable();
33 | $table->dateTime('last_login')->nullable();
34 | $table->longText('agent')->nullable();
35 | $table->string('host')->nullable();
36 |
37 | // Options
38 | $table->boolean('is_login')->default(0)->nullable();
39 | $table->boolean('is_active')->default(false);
40 | $table->boolean('is_notification_active')->default(true);
41 |
42 | $table->softDeletes();
43 | $table->timestamps();
44 | });
45 | }
46 |
47 | /**
48 | * Reverse the migrations.
49 | *
50 | * @return void
51 | */
52 | public function down()
53 | {
54 | Schema::dropIfExists('accounts');
55 | }
56 | };
57 |
--------------------------------------------------------------------------------
/database/migrations/2024_10_28_143941_add_media_if_not_exists_table.php:
--------------------------------------------------------------------------------
1 | id();
19 |
20 | $table->morphs('model');
21 | $table->uuid()->nullable()->unique();
22 | $table->string('collection_name');
23 | $table->string('name');
24 | $table->string('file_name');
25 | $table->string('mime_type')->nullable();
26 | $table->string('disk');
27 | $table->string('conversions_disk')->nullable();
28 | $table->unsignedBigInteger('size');
29 | $table->json('manipulations');
30 | $table->json('custom_properties');
31 | $table->json('generated_conversions');
32 | $table->json('responsive_images');
33 | $table->unsignedInteger('order_column')->nullable()->index();
34 |
35 | $table->nullableTimestamps();
36 | });
37 | }
38 | }
39 | };
40 |
--------------------------------------------------------------------------------
/module.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "FilamentAccounts",
3 | "alias": "filament-accounts",
4 | "description": {
5 | "ar": "قم بادارة جميع العملاء والحسابات الخاصة بالنظام من مكان واحد",
6 | "en": "Manage your multi accounts inside your app using 1 table with multi auth and a lot of integrations",
7 | "gr": "Manage your multi accounts inside your app using 1 table with multi auth and a lot of integrations",
8 | "sp": "Manage your multi accounts inside your app using 1 table with multi auth and a lot of integrations"
9 | },
10 | "keywords": [],
11 | "priority": 0,
12 | "providers": [
13 | "TomatoPHP\\FilamentAccounts\\FilamentAccountsServiceProvider"
14 | ],
15 | "files": [],
16 | "title": {
17 | "ar": "الحسابات",
18 | "en": "Accounts Builder",
19 | "gr": "Accounts Builder",
20 | "sp": "Accounts Builder"
21 | },
22 | "color": "#007dff",
23 | "icon": "heroicon-c-user-circle",
24 | "placeholder": "https://raw.githubusercontent.com/tomatophp/filament-accounts/master/arts/3x1io-tomato-accounts.jpg",
25 | "type": "plugin",
26 | "version": "v2.3.0",
27 | "github" : "https://github.com/tomatophp/filament-accounts",
28 | "docs" : "https://github.com/tomatophp/filament-accounts"
29 | }
30 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 | ./tests/
15 |
16 |
17 |
18 |
19 | ./src
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/pint.json:
--------------------------------------------------------------------------------
1 | {
2 | "preset": "laravel",
3 | "rules": {
4 | "blank_line_before_statement": true,
5 | "concat_space": {
6 | "spacing": "one"
7 | },
8 | "method_argument_space": true,
9 | "single_trait_insert_per_statement": true,
10 | "types_spaces": {
11 | "space": "single"
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/publish/Account.php:
--------------------------------------------------------------------------------
1 | 'boolean',
68 | 'is_active' => 'boolean',
69 | ];
70 |
71 | protected $dates = [
72 | 'deleted_at',
73 | 'created_at',
74 | 'updated_at',
75 | 'otp_activated_at',
76 | 'last_login',
77 | ];
78 |
79 | protected $hidden = [
80 | 'password',
81 | 'remember_token',
82 | 'otp_code',
83 | 'otp_activated_at',
84 | 'host',
85 | 'agent',
86 | ];
87 |
88 | public function getFilamentAvatarUrl(): ?string
89 | {
90 | return $this->getFirstMediaUrl('avatar') ?? null;
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/resources/js/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomatophp/filament-accounts/7f5f11765de2781e119f826163e9dcb7a8c1a347/resources/js/.gitkeep
--------------------------------------------------------------------------------
/resources/lang/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomatophp/filament-accounts/7f5f11765de2781e119f826163e9dcb7a8c1a347/resources/lang/.gitkeep
--------------------------------------------------------------------------------
/resources/lang/ar/messages.php:
--------------------------------------------------------------------------------
1 | 'الحسابات',
5 | 'accounts' => [
6 | 'label' => 'الحسابات',
7 | 'single' => 'حساب',
8 | 'columns' => [
9 | 'id' => 'المعرف',
10 | 'account' => 'الحساب',
11 | 'teams' => 'الفرق',
12 | 'avatar' => 'صورة الملف الشخصي',
13 | 'name' => 'الاسم',
14 | 'email' => 'البريد الالكتروني',
15 | 'phone' => 'الهاتف',
16 | 'type' => 'النوع',
17 | 'address' => 'العنوان',
18 | 'password' => 'كلمة المرور',
19 | 'password_confirmation' => 'تأكيد كلمة المرور',
20 | 'loginBy' => 'تسجيل الدخول بواسطة',
21 | 'is_active' => 'هل نشط؟',
22 | 'is_login' => 'يمكن تسجيل الدخول؟',
23 | 'created_at' => 'تم الإنشاء في',
24 | 'updated_at' => 'تم التحديث في',
25 | ],
26 | 'filters' => [
27 | 'type' => 'حسب النوع',
28 | 'teams' => 'حسب الفريق',
29 | 'is_active' => 'هل هو مفعل؟',
30 | 'is_login' => 'هل يستطيع تسجيل الدخول؟',
31 | ],
32 | 'actions' => [
33 | 'teams' => 'إدارة الفرق',
34 | 'impersonate' => 'تسجيل الدخول',
35 | 'password' => 'تغيير كلمة المرور',
36 | 'notifications' => 'إرسال الإشعارات',
37 | 'edit' => 'تعديل',
38 | 'delete' => 'حذف',
39 | 'force_delete' => 'حذف نهائي',
40 | 'restore' => 'استعادة',
41 | ],
42 | 'notifications' => [
43 | 'use_notification_template' => 'استخدام قالب الإشعارات',
44 | 'template_id' => 'القالب',
45 | 'image' => 'الصورة',
46 | 'title' => 'العنوان',
47 | 'body' => 'النص',
48 | 'action' => 'العملية',
49 | 'url' => 'الرابط',
50 | 'icon' => 'الأيقونة',
51 | 'type' => 'النوع',
52 | 'providers' => 'ارسال عن طريق',
53 | ],
54 | 'export' => [
55 | 'title' => 'تصدير',
56 | 'columns' => 'الأعمدة',
57 | ],
58 | 'import' => [
59 | 'title' => 'استيراد',
60 | 'excel' => 'ملف اكسيل',
61 | 'hint' => 'يرجى تحميل ملف اكسيل لاستيراد الحسابات',
62 | 'success' => 'تم استيراد الحسابات بنجاح',
63 | 'body' => 'تم استيراد الحسابات بنجاح',
64 | 'error' => 'خطأ أثناء استيراد الحسابات',
65 | 'error-body' => 'حدث خطأ أثناء استيراد الحسابات',
66 | ],
67 | ],
68 | 'meta' => [
69 | 'label' => 'المعلومات',
70 | 'single' => 'معلومة',
71 | 'create' => 'إضافة معلومة',
72 | 'columns' => [
73 | 'account' => 'الحساب',
74 | 'key' => 'المفتاح',
75 | 'value' => 'القيمة',
76 | ],
77 | ],
78 | 'locations' => [
79 | 'label' => 'المواقع',
80 | 'single' => 'موقع',
81 | 'create' => 'إضافة موقع',
82 | ],
83 | 'requests' => [
84 | 'label' => 'طلبات الحساب',
85 | 'single' => 'طلب للحساب',
86 | 'columns' => [
87 | 'account' => 'الحساب',
88 | 'user' => 'المستخدم',
89 | 'type' => 'النوع',
90 | 'status' => 'الحالة',
91 | 'is_approved' => 'هل تم الموافقة؟',
92 | 'is_approved_at' => 'تمت الموافقة في',
93 | ],
94 | ],
95 | 'contacts' => [
96 | 'label' => 'اتصل بنا',
97 | 'single' => 'اتصال',
98 | 'columns' => [
99 | 'type' => 'النوع',
100 | 'status' => 'الحالة',
101 | 'name' => 'الاسم',
102 | 'email' => 'البريد الالكتروني',
103 | 'phone' => 'الهاتف',
104 | 'subject' => 'الموضوع',
105 | 'active' => 'نشط',
106 | ],
107 | ],
108 | 'profile' => [
109 | 'title' => 'تعديل الملف الشخصي',
110 | 'edit' => [
111 | 'title' => 'تعديل المعلومات',
112 | 'description' => 'تحديث معلومات الملف الشخصي وعنوان البريد الإلكتروني الخاص بحسابك.',
113 | 'name' => 'الاسم',
114 | 'email' => 'البريد الإلكتروني',
115 | ],
116 | 'password' => [
117 | 'title' => 'تغيير كلمة المرور',
118 | 'description' => 'تأكد من أن حسابك يستخدم كلمة مرور طويلة وعشوائية للبقاء آمنًا.',
119 | 'current_password' => 'كلمة المرور الحالية',
120 | 'new_password' => 'كلمة المرور الجديدة',
121 | 'confirm_password' => 'تأكيد كلمة المرور',
122 | ],
123 | 'browser' => [
124 | 'sessions_last_active' => 'اخر جلسة',
125 | 'browser_section_title' => 'جلسات المتصفح',
126 | 'browser_section_description' => 'إدارة وتسجيل الخروج من جلساتك النشطة على المتصفحات والأجهزة الأخرى.',
127 | 'browser_sessions_log_out' => 'تسجيل الخروج من جلسات المتصفح الأخرى',
128 | 'browser_sessions_confirm_pass' => 'يرجى إدخال كلمة المرور لتأكيد رغبتك في تسجيل الخروج من جلسات المتصفح الأخرى عبر جميع أجهزتك.',
129 | 'password' => 'كلمة المرور',
130 | 'confirm' => 'تأكيد',
131 | 'nevermind' => 'لا بأس',
132 | 'browser_sessions_logout_notification' => 'تم تسجيل الخروج من جلسات المتصفح الخاصة بك.',
133 | 'browser_sessions_logout_failed_notification' => 'كلمة المرور غير صحيحة.',
134 | 'sessions_device' => 'الجهاز',
135 | 'sessions_content' => 'الأجهزة المتصلة',
136 | 'incorrect_password' => 'كلمة المرور التي أدخلتها غير صحيحة.',
137 | ],
138 | 'delete' => [
139 | 'delete_account' => 'حذف الحساب',
140 | 'delete_account_description' => 'حذف حسابك بشكل دائم.',
141 | 'incorrect_password' => 'كلمة المرور التي أدخلتها غير صحيحة.',
142 | 'are_you_sure' => 'هل أنت متأكد من أنك تريد حذف حسابك؟ بمجرد حذف حسابك، سيتم حذف جميع موارده وبياناته بشكل دائم. يرجى إدخال كلمة المرور لتأكيد رغبتك في حذف حسابك نهائيًا.',
143 | 'yes_delete_it' => 'نعم، احذفه',
144 | 'password' => 'كلمة المرور',
145 | 'delete_account_card_description' => 'بمجرد حذف حسابك، سيتم حذف جميع موارده وبياناته بشكل دائم. قبل حذف حسابك، يرجى تنزيل أي بيانات أو معلومات ترغب في الاحتفاظ بها.',
146 | ],
147 | 'delete-team' => [
148 | 'title' => 'حذف الفريق',
149 | 'description' => 'حذف فريقك بشكل دائم.',
150 | 'body' => 'بمجرد حذف الفريق، سيتم حذف جميع موارده وبياناته بشكل دائم. قبل حذف هذا الفريق، يرجى تنزيل أي بيانات أو معلومات ترغب في الاحتفاظ بها.',
151 | 'delete' => 'حذف الفريق',
152 | 'delete_account' => 'حذف الفريق',
153 | 'delete_account_description' => 'هل أنت متأكد من أنك تريد حذف فريقك؟ بمجرد حذف فريقك، سيتم حذف جميع موارده وبياناته بشكل دائم. يرجى إدخال كلمة المرور لتأكيد رغبتك في حذف فريقك نهائيًا.',
154 | 'yes_delete_it' => 'نعم، احذفه',
155 | 'password' => 'كلمة المرور',
156 | 'incorrect_password' => 'كلمة المرور التي أدخلتها غير صحيحة.',
157 | 'are_you_sure' => 'هل أنت متأكد من أنك تريد حذف فريقك؟ بمجرد حذف فريقك، سيتم حذف جميع موارده وبياناته بشكل دائم. يرجى إدخال كلمة المرور لتأكيد رغبتك في حذف فريقك نهائيًا.',
158 | ],
159 | 'token' => [
160 | 'title' => 'رموز API',
161 | 'description' => 'تسمح رموز API للخدمات الخارجية بالمصادقة مع تطبيقنا نيابةً عنك.',
162 | 'name' => 'الاسم',
163 | 'created_at' => 'تم الإنشاء في',
164 | 'expires_at' => 'تنتهي في',
165 | 'abilities' => 'القدرات',
166 | 'action_label' => 'إنشاء رمز',
167 | 'create_notification' => 'تم إنشاء الرمز بنجاح!',
168 | 'modal_heading' => 'إنشاء رمز',
169 | 'empty_state_heading' => 'لا توجد رموز',
170 | 'empty_state_description' => 'إنشاء رمز جديد للمصادقة مع API.',
171 | 'delete_token' => 'حذف الرمز',
172 | 'delete_token_description' => 'هل أنت متأكد من أنك تريد حذف هذا الرمز؟',
173 | 'delete_token_confirmation' => 'نعم، احذفه',
174 | 'delete_token_notification' => 'تم حذف الرمز بنجاح!',
175 | 'modal_heading_2' => 'تم إنشاء الرمز بنجاح',
176 | 'helper_text' => 'يمكنك تعديل الرمز أدناه. تأكد من نسخه الآن، حيث لن تتمكن من رؤيته مرة أخرى.',
177 | 'token' => 'الرمز',
178 | ],
179 | ],
180 | 'teams' => [
181 | 'title' => 'إعدادات الفريق',
182 | 'actions' => [
183 | 'cancel_invitation' => 'إلغاء الدعوة',
184 | 'resend_invitation' => 'إعادة ارسال الدعوة',
185 | ],
186 | 'edit' => [
187 | 'title' => 'تعديل إسم الفريق',
188 | 'description' => 'تحديث معلومات الفريق وصورة الفريقك.',
189 | 'name' => 'الاسم',
190 | 'email' => 'البريد الإلكتروني',
191 | 'avatar' => 'الصورة الرمزية',
192 | 'save' => 'حفظ',
193 | 'owner' => 'المالك',
194 | ],
195 | 'members' => [
196 | 'title' => 'دعوة أعضاء الفريق',
197 | 'description' => 'إضافة عضو فريق جديد إلى فريقك، مما يسمح له بالتعاون معك.',
198 | 'team-members' => 'يرجى تقديم عنوان البريد الإلكتروني للشخص الذي ترغب في إضافته إلى هذا الفريق.',
199 | 'email' => 'البريد الإلكتروني',
200 | 'role' => 'الدور',
201 | 'send_invitation' => 'إرسال الدعوة',
202 | 'cancel' => 'إلغاء',
203 | 'not_in' => 'عنوان البريد الإلكتروني هو بالفعل عضو في الفريق.',
204 | 'required' => 'حقل البريد الإلكتروني مطلوب.',
205 | 'unique' => 'عنوان البريد الإلكتروني هو بالفعل عضو في الفريق.',
206 | 'role_required' => 'حقل الدور مطلوب.',
207 | 'notifications' => [
208 | 'title' => 'دعوة عضو فريق',
209 | 'body' => 'لقد تمت دعوتك للانضمام إلى فريق :team.',
210 | 'accept' => 'قبول الدعوة',
211 | 'cancel' => 'إلغاء الدعوة',
212 | ],
213 | 'leave_team' => 'مغادرة الفريق',
214 | 'remove_member' => 'إزالة عضو',
215 | 'manage_role' => 'إدارة الدور',
216 | 'list' => [
217 | 'title' => 'أعضاء الفريق',
218 | 'description' => 'جميع الأشخاص الذين هم جزء من هذا الفريق.',
219 | ],
220 | ],
221 | 'delete' => [
222 | 'title' => 'حذف الفريق',
223 | 'description' => 'حذف فريقك بشكل دائم.',
224 | 'body' => 'بمجرد حذف فريق، سيتم حذف جميع موارده وبياناته بشكل دائم. قبل حذف هذا الفريق، يرجى تنزيل أي بيانات أو معلومات تتعلق بهذا الفريق التي ترغب في الاحتفاظ بها.',
225 | 'delete' => 'حذف الفريق',
226 | 'delete_account' => 'حذف الفريق',
227 | 'delete_account_description' => 'هل أنت متأكد أنك تريد حذف فريقك؟ بمجرد حذف فريقك، سيتم حذف جميع موارده وبياناته بشكل دائم. يرجى إدخال كلمة المرور الخاصة بك لتأكيد أنك ترغب في حذف فريقك بشكل دائم.',
228 | 'yes_delete_it' => 'نعم، احذفه',
229 | 'password' => 'كلمة المرور',
230 | 'incorrect_password' => 'كلمة المرور التي أدخلتها غير صحيحة.',
231 | 'are_you_sure' => 'هل أنت متأكد أنك تريد حذف فريقك؟ بمجرد حذف فريقك، سيتم حذف جميع موارده وبياناته بشكل دائم. يرجى إدخال كلمة المرور الخاصة بك لتأكيد أنك ترغب في حذف فريقك بشكل دائم.',
232 | ],
233 | ],
234 | 'team' => [
235 | 'title' => 'الفرق',
236 | 'single' => 'فريق',
237 | 'columns' => [
238 | 'avatar' => 'الشعار',
239 | 'name' => 'الاسم',
240 | 'owner' => 'المالك',
241 | 'personal_team' => 'فريق شخصي',
242 | ],
243 | ],
244 | 'roles' => [
245 | 'admin' => [
246 | 'name' => 'مدير النظام',
247 | 'description' => 'مدير النظام يمكنه إدارة النظام بالكامل.',
248 | ],
249 | 'user' => [
250 | 'name' => 'مستخدم',
251 | 'description' => 'مستخدم عادي يمكنه القراءة والتحديث.',
252 | ],
253 | ],
254 | 'login' => [
255 | 'active' => 'عفواً برجاء تاكيد الحساب اولاً ثم اعادة تسجيل الدخول',
256 | ],
257 |
258 | 'settings' => [
259 | 'types' => [
260 | 'title' => 'أنواع الحسابات',
261 | ],
262 | ],
263 |
264 | 'address' => [
265 | 'title' => 'تعديل العناوين',
266 | ],
267 |
268 | 'account-requests' => [
269 | 'title' => 'طلبات الحساب',
270 | 'status' => 'الحالة',
271 | 'types' => 'النوع',
272 | 'button' => 'تعديل الانواع والحالات',
273 | ],
274 |
275 | 'contact-us' => [
276 | 'status' => 'تعديل حالات اتصل بنا',
277 | 'status-button' => 'إدارة الحالات',
278 | 'footer' => 'هل لديك اي مشكلة؟ او تحتاج الى مساعدة؟',
279 | 'modal' => 'برجاء مليء هذا النموذج للتواصل معانا',
280 | 'label' => 'تواصل معنا',
281 | 'form' => [
282 | 'name' => 'الاسم',
283 | 'email' => 'البريد الالكتروني',
284 | 'phone' => 'الهاتف',
285 | 'subject' => 'الموضوع',
286 | 'message' => 'الرسالة',
287 | ],
288 | 'notification' => [
289 | 'title' => 'عملية ناجحة',
290 | 'body' => 'تم ارسال الرسالة بنجاح',
291 | ],
292 | ],
293 | ];
294 |
--------------------------------------------------------------------------------
/resources/lang/en/messages.php:
--------------------------------------------------------------------------------
1 | 'Save',
5 | 'saved_successfully' => 'Saved Successfully',
6 | 'group' => 'Accounts',
7 | 'accounts' => [
8 | 'label' => 'Accounts',
9 | 'single' => 'Account',
10 | 'columns' => [
11 | 'id' => 'ID',
12 | 'avatar' => 'Avatar',
13 | 'account' => 'Account',
14 | 'teams' => 'Teams',
15 | 'name' => 'Name',
16 | 'email' => 'Email',
17 | 'phone' => 'Phone',
18 | 'type' => 'Type',
19 | 'address' => 'Address',
20 | 'password' => 'Password',
21 | 'password_confirmation' => 'Password Confirmation',
22 | 'loginBy' => 'Login By',
23 | 'is_active' => 'Is Active?',
24 | 'is_login' => 'Can Login?',
25 | 'created_at' => 'Created At',
26 | 'updated_at' => 'Updated At',
27 | ],
28 | 'filters' => [
29 | 'type' => 'Type',
30 | 'teams' => 'Teams',
31 | 'is_active' => 'Is Active?',
32 | 'is_login' => 'Can Login?',
33 | ],
34 | 'actions' => [
35 | 'teams' => 'Manage Teams',
36 | 'impersonate' => 'Login As',
37 | 'password' => 'Change Password',
38 | 'notifications' => 'Send Notifications',
39 | 'edit' => 'Edit',
40 | 'delete' => 'Delete',
41 | 'force_delete' => 'Force Delete',
42 | 'restore' => 'Restore',
43 | ],
44 | 'notifications' => [
45 | 'use_notification_template' => 'Use Notification Template',
46 | 'template_id' => 'Template',
47 | 'image' => 'Image',
48 | 'title' => 'Title',
49 | 'body' => 'Body',
50 | 'action' => 'Action',
51 | 'url' => 'URL',
52 | 'icon' => 'Icon',
53 | 'type' => 'Type',
54 | 'providers' => 'Send By',
55 | ],
56 | 'export' => [
57 | 'title' => 'Export',
58 | 'columns' => 'Columns',
59 | ],
60 | 'import' => [
61 | 'title' => 'Import',
62 | 'excel' => 'Excel',
63 | 'hint' => 'You can upload the same style of exported file',
64 | 'success' => 'Success',
65 | 'body' => 'Accounts imported successfully',
66 | 'error' => 'Error',
67 | 'error-body' => 'Error while importing accounts',
68 | ],
69 | ],
70 | 'meta' => [
71 | 'label' => 'Metas',
72 | 'single' => 'Meta',
73 | 'create' => 'Create Meta',
74 | 'columns' => [
75 | 'account' => 'Account',
76 | 'key' => 'Key',
77 | 'value' => 'Value',
78 | ],
79 | ],
80 | 'locations' => [
81 | 'label' => 'Locations',
82 | 'single' => 'Location',
83 | 'create' => 'Create Location',
84 | ],
85 | 'requests' => [
86 | 'label' => 'Account Requests',
87 | 'single' => 'Account Request',
88 | 'columns' => [
89 | 'account' => 'Account',
90 | 'user' => 'User',
91 | 'type' => 'Type',
92 | 'status' => 'Status',
93 | 'is_approved' => 'Is Approved?',
94 | 'is_approved_at' => 'Is Approved At',
95 | ],
96 | ],
97 | 'contacts' => [
98 | 'label' => 'Contacts',
99 | 'single' => 'Contact',
100 | 'columns' => [
101 | 'type' => 'Type',
102 | 'status' => 'Status',
103 | 'name' => 'Name',
104 | 'email' => 'Email',
105 | 'phone' => 'Phone',
106 | 'subject' => 'Subject',
107 | 'message' => 'Message',
108 | 'active' => 'Active',
109 | ],
110 | ],
111 | 'profile' => [
112 | 'title' => 'Edit Profile',
113 | 'edit' => [
114 | 'title' => 'Edit Information',
115 | 'description' => "Update your account's profile information and email address.",
116 | 'name' => 'Name',
117 | 'email' => 'Email',
118 | ],
119 | 'password' => [
120 | 'title' => 'Change Password',
121 | 'description' => 'Ensure your account is using a long, random password to stay secure.',
122 | 'current_password' => 'Current Password',
123 | 'new_password' => 'New Password',
124 | 'confirm_password' => 'Confirm Password',
125 | ],
126 | 'browser' => [
127 | 'sessions_last_active' => 'Last Active',
128 | 'browser_section_title' => 'Browser Sessions',
129 | 'browser_section_description' => 'Manage and log out your active sessions on other browsers and devices.',
130 | 'browser_sessions_log_out' => 'Log Out Other Browser Sessions',
131 | 'browser_sessions_confirm_pass' => 'Please enter your password to confirm you would like to log out of your other browser sessions across all of your devices.',
132 | 'password' => 'Password',
133 | 'confirm' => 'Confirm',
134 | 'nevermind' => 'Nevermind',
135 | 'browser_sessions_logout_notification' => 'Your browser sessions have been logged out.',
136 | 'browser_sessions_logout_failed_notification' => 'Your password was incorrect.',
137 | 'sessions_device' => 'Device',
138 | 'sessions_content' => 'Connected Devices',
139 | 'incorrect_password' => 'The password you entered was incorrect.',
140 | ],
141 | 'delete' => [
142 | 'delete_account' => 'Delete Account',
143 | 'delete_account_description' => 'Permanently delete your account.',
144 | 'incorrect_password' => 'The password you entered was incorrect.',
145 | 'are_you_sure' => 'Are you sure you want to delete your account? Once your account is deleted, all of its resources and data will be permanently deleted. Please enter your password to confirm you would like to permanently delete your account.',
146 | 'yes_delete_it' => 'Yes, delete it',
147 | 'password' => 'Password',
148 | 'delete_account_card_description' => 'Once your account is deleted, all of its resources and data will be permanently deleted. Before deleting your account, please download any data or information that you wish to retain.',
149 | ],
150 | 'delete-team' => [
151 | 'title' => 'Delete Team',
152 | 'description' => 'Permanently delete your team.',
153 | 'body' => 'Once a team is deleted, all of its resources and data will be permanently deleted. Before deleting this team, please download any data or information regarding this team that you wish to retain.',
154 | 'delete' => 'Delete Team',
155 | 'delete_account' => 'Delete Team',
156 | 'delete_account_description' => 'Are you sure you want to delete your team? Once your team is deleted, all of its resources and data will be permanently deleted. Please enter your password to confirm you would like to permanently delete your team.',
157 | 'yes_delete_it' => 'Yes, delete it',
158 | 'password' => 'Password',
159 | 'incorrect_password' => 'The password you entered was incorrect.',
160 | 'are_you_sure' => 'Are you sure you want to delete your team? Once your team is deleted, all of its resources and data will be permanently deleted. Please enter your password to confirm you would like to permanently delete your team.',
161 | ],
162 | 'token' => [
163 | 'title' => 'API Tokens',
164 | 'description' => 'API tokens allow third-party services to authenticate with our application on your behalf.',
165 | 'name' => 'Name',
166 | 'created_at' => 'Created At',
167 | 'expires_at' => 'Expires At',
168 | 'abilities' => 'Abilities',
169 | 'action_label' => 'Create Token',
170 | 'create_notification' => 'Token created successfully!',
171 | 'modal_heading' => 'Create Token',
172 | 'empty_state_heading' => 'No tokens',
173 | 'empty_state_description' => 'Create a new token to authenticate with the API.',
174 | 'delete_token' => 'Delete Token',
175 | 'delete_token_description' => 'Are you sure you would like to delete this token?',
176 | 'delete_token_confirmation' => 'Yes, delete it',
177 | 'delete_token_notification' => 'Token deleted successfully!',
178 | 'modal_heading_2' => 'Token Generated Successfully',
179 | 'helper_text' => "You may edit the token below. Make sure to copy it now, as you won't be able to see it again.",
180 | 'token' => 'Token',
181 | ],
182 | ],
183 | 'teams' => [
184 | 'title' => 'Team Settings',
185 | 'actions' => [
186 | 'cancel_invitation' => 'Cancel Invitation',
187 | 'resend_invitation' => 'Resend Invitation',
188 | ],
189 | 'edit' => [
190 | 'title' => 'Edit Team Name',
191 | 'description' => "Update your team's profile information and email address.",
192 | 'name' => 'Name',
193 | 'email' => 'Email',
194 | 'avatar' => 'Avatar',
195 | 'save' => 'Save',
196 | 'owner' => 'Owner',
197 | ],
198 | 'members' => [
199 | 'title' => 'Invite Team Members',
200 | 'description' => 'Add a new team member to your team, allowing them to collaborate with you.',
201 | 'team-members' => 'Please provide the email address of the person you would like to add to this team.',
202 | 'email' => 'Email',
203 | 'role' => 'Role',
204 | 'send_invitation' => 'Send Invitation',
205 | 'cancel' => 'Cancel',
206 | 'not_in' => 'The email address is already a team member.',
207 | 'required' => 'The email field is required.',
208 | 'unique' => 'The email address is already a team member.',
209 | 'role_required' => 'The role field is required.',
210 | 'notifications' => [
211 | 'title' => 'Team Member Invitation',
212 | 'body' => 'You have been invited to join the :team team.',
213 | 'accept' => 'Accept Invitation',
214 | 'cancel' => 'Cancel Invitation',
215 | ],
216 | 'leave_team' => 'Leave Team',
217 | 'remove_member' => 'Remove Member',
218 | 'manage_role' => 'Manage Role',
219 | 'list' => [
220 | 'title' => 'Team Members',
221 | 'description' => 'All of the people that are part of this team.',
222 | ],
223 | ],
224 | 'delete' => [
225 | 'title' => 'Delete Team',
226 | 'description' => 'Permanently delete your team.',
227 | 'body' => 'Once a team is deleted, all of its resources and data will be permanently deleted. Before deleting this team, please download any data or information regarding this team that you wish to retain.',
228 | 'delete' => 'Delete Team',
229 | 'delete_account' => 'Delete Team',
230 | 'delete_account_description' => 'Are you sure you want to delete your team? Once your team is deleted, all of its resources and data will be permanently deleted. Please enter your password to confirm you would like to permanently delete your team.',
231 | 'yes_delete_it' => 'Yes, delete it',
232 | 'password' => 'Password',
233 | 'incorrect_password' => 'The password you entered was incorrect.',
234 | 'are_you_sure' => 'Are you sure you want to delete your team? Once your team is deleted, all of its resources and data will be permanently deleted. Please enter your password to confirm you would like to permanently delete your team.',
235 | ],
236 | ],
237 | 'team' => [
238 | 'title' => 'Teams',
239 | 'single' => 'Team',
240 | 'columns' => [
241 | 'avatar' => 'Avatar',
242 | 'name' => 'Name',
243 | 'owner' => 'Owner',
244 | 'personal_team' => 'Personal Team',
245 | ],
246 | ],
247 |
248 | 'roles' => [
249 | 'admin' => [
250 | 'name' => 'Administrator',
251 | 'description' => 'Administrator users can perform any action.',
252 | ],
253 | 'user' => [
254 | 'name' => 'User',
255 | 'description' => 'User users can read and update data.',
256 | ],
257 | ],
258 | 'login' => [
259 | 'active' => 'Please Verify Your Account First, than try to login again',
260 | ],
261 |
262 | 'settings' => [
263 | 'types' => [
264 | 'title' => 'Accounts Types',
265 | ],
266 | ],
267 |
268 | 'address' => [
269 | 'title' => 'Edit Locations',
270 | ],
271 |
272 | 'account-requests' => [
273 | 'title' => 'Requests',
274 | 'status' => 'Request Status',
275 | 'types' => 'Request Types',
276 | 'button' => 'Manage Types & Status',
277 | ],
278 |
279 | 'contact-us' => [
280 | 'status' => 'Edit Contact Us Status',
281 | 'status-button' => 'Manage Status',
282 | 'footer' => 'Do you have any problems or questions? Please',
283 | 'modal' => 'Please Fill This Form To Contact Us',
284 | 'label' => 'Contact Us',
285 | 'form' => [
286 | 'name' => 'Name',
287 | 'email' => 'Email',
288 | 'phone' => 'Phone',
289 | 'subject' => 'Subject',
290 | 'message' => 'Message',
291 | ],
292 | 'notification' => [
293 | 'title' => 'Contact Us',
294 | 'body' => 'Your message has been sent successfully',
295 | ],
296 | ],
297 | ];
298 |
--------------------------------------------------------------------------------
/resources/views/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomatophp/filament-accounts/7f5f11765de2781e119f826163e9dcb7a8c1a347/resources/views/.gitkeep
--------------------------------------------------------------------------------
/resources/views/components/account-column.blade.php:
--------------------------------------------------------------------------------
1 | @php
2 | $account = config('filament-accounts.model')::withTrashed()->find($getState());
3 | $tenent = \Filament\Facades\Filament::getTenant()?->id;
4 | $panel = \Filament\Facades\Filament::getCurrentPanel()->getId() ?? null;
5 | if(isset(\TomatoPHP\FilamentAccounts\Filament\Resources\AccountResource::getPages()['edit'])){
6 | $url = \TomatoPHP\FilamentAccounts\Filament\Resources\AccountResource::getUrl('edit', ['record' => $account, 'tenant' => $tenent]);
7 | }
8 | else {
9 | $url = null;
10 | }
11 |
12 | @endphp
13 |
14 | @if($account)
15 | @if($url)
16 |
17 |
18 |
22 |
23 |
24 |
25 | {{ $account->name }}
26 |
27 |
28 | {{ $account->loginBy === 'email' ? $account->email : $account->phone }}
29 |
30 |
31 |
32 | @else
33 |
34 |
35 |
39 |
40 |
41 |
42 | {{ $account->name }}
43 |
44 |
45 | {{ $account->loginBy === 'email' ? $account->email : $account->phone }}
46 |
47 |
48 |
49 | @endif
50 | @endif
51 |
--------------------------------------------------------------------------------
/src/Components/AccountColumn.php:
--------------------------------------------------------------------------------
1 | avatar = $avatar;
16 |
17 | return $this;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Console/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomatophp/filament-accounts/7f5f11765de2781e119f826163e9dcb7a8c1a347/src/Console/.gitkeep
--------------------------------------------------------------------------------
/src/Console/FilamentAccountsInstall.php:
--------------------------------------------------------------------------------
1 | info('Publish Vendor Assets');
40 | $this->callSilent('optimize:clear');
41 | $this->artisanCommand(['migrate']);
42 | $this->artisanCommand(['optimize:clear']);
43 | if (config('filament-accounts.features.types') && class_exists(\TomatoPHP\FilamentTypes\Models\Type::class)) {
44 | $typesArray = [
45 | [
46 | 'name' => [
47 | 'ar' => 'عميل',
48 | 'en' => 'Customer',
49 | ],
50 | 'key' => 'customer',
51 | 'for' => 'accounts',
52 | 'type' => 'type',
53 | 'icon' => 'heroicon-c-user-group',
54 | 'color' => '#d91919',
55 | ],
56 | [
57 | 'name' => [
58 | 'ar' => 'حساب',
59 | 'en' => 'Account',
60 | ],
61 | 'key' => 'account',
62 | 'for' => 'accounts',
63 | 'type' => 'type',
64 | 'icon' => 'heroicon-c-user-circle',
65 | 'color' => '#0a56d9',
66 | ],
67 | [
68 | 'name' => [
69 | 'ar' => 'تحت المراجعة',
70 | 'en' => 'Pending',
71 | ],
72 | 'key' => 'pending',
73 | 'for' => 'contacts',
74 | 'type' => 'status',
75 | 'icon' => 'heroicon-c-pause-circle',
76 | 'color' => '#ffcf00',
77 | ],
78 | [
79 | 'name' => [
80 | 'ar' => 'جاري المتابعة',
81 | 'en' => 'Active',
82 | ],
83 | 'key' => 'active',
84 | 'for' => 'contacts',
85 | 'type' => 'status',
86 | 'icon' => 'heroicon-c-play-circle',
87 | 'color' => '#1897ff',
88 | ],
89 | [
90 | 'name' => [
91 | 'ar' => 'تم اغلاقها',
92 | 'en' => 'Closed',
93 | ],
94 | 'key' => 'closed',
95 | 'for' => 'contacts',
96 | 'type' => 'status',
97 | 'icon' => 'heroicon-c-check-circle',
98 | 'color' => '#38fc34',
99 | ],
100 | [
101 | 'name' => [
102 | 'ar' => 'الموافقة علي الحساب',
103 | 'en' => 'Account Approve',
104 | ],
105 | 'key' => 'account_approve',
106 | 'for' => 'contacts',
107 | 'type' => 'type',
108 | 'icon' => 'heroicon-c-check-circle',
109 | 'color' => '#38fc34',
110 | ],
111 | ];
112 | foreach ($typesArray as $item) {
113 | $checkFirst = Type::query()->where('key', $item['key'])->first();
114 | if (! $checkFirst) {
115 | Type::query()->create($item);
116 | }
117 | }
118 | }
119 |
120 | $this->info('Filament Accounts installed successfully.');
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/src/Export/ExportAccounts.php:
--------------------------------------------------------------------------------
1 | data['columns']);
18 | }
19 |
20 | public function collection()
21 | {
22 | $select = array_keys(collect($this->data['columns'])->filter(fn ($item, $key) => ! str($key)->contains('.'))->toArray());
23 |
24 | return config('filament-accounts.model')::query()
25 | ->select($select)
26 | ->get()
27 | ->map(function ($item) {
28 | return collect($this->data['columns'])->map(function ($column, $key) use ($item) {
29 | if (str($key)->contains('.')) {
30 | $keys = explode('.', $key);
31 | if (is_a($item->{$keys[0]}, Collection::class)) {
32 | return collect($item->{$keys[0]})->map(fn ($item) => $item->{$keys[1]})->implode(', ');
33 | } else {
34 | return $item->{$keys[0]}?->{$keys[1]};
35 | }
36 |
37 | }
38 |
39 | return $item->{$key};
40 | });
41 | });
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Facades/FilamentAccounts.php:
--------------------------------------------------------------------------------
1 | Pages\ManageAccounts::route('/'),
74 | ] : [
75 | 'index' => Pages\ListAccounts::route('/'),
76 | 'create' => Pages\CreateAccount::route('/create'),
77 | 'edit' => Pages\EditAccount::route('/{record}/edit'),
78 | 'view' => Pages\ViewAccount::route('/{record}'),
79 | ];
80 | }
81 |
82 | public static function getEloquentQuery(): Builder
83 | {
84 | return parent::getEloquentQuery()
85 | ->withoutGlobalScopes([
86 | SoftDeletingScope::class,
87 | ]);
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Actions/Components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomatophp/filament-accounts/7f5f11765de2781e119f826163e9dcb7a8c1a347/src/Filament/Resources/AccountResource/Actions/Components/.gitkeep
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Actions/Components/Action.php:
--------------------------------------------------------------------------------
1 | using(function (array $data) {
13 | if (isset($data['password'])) {
14 | $data['password'] = bcrypt($data['password']);
15 | }
16 | if (isset($data['loginBy']) && $data['loginBy'] === 'email' && ! empty($data['email'])) {
17 | $data['username'] = $data['email'];
18 | } elseif (isset($data['loginBy']) && $data['loginBy'] === 'phone' && ! empty($data['phone'])) {
19 | $data['username'] = $data['phone'];
20 | } else {
21 | $data['username'] = str($data['name'])->slug()->toString();
22 | }
23 |
24 | return config('filament-accounts.model')::query()->create($data);
25 | });
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Actions/Components/DeleteAction.php:
--------------------------------------------------------------------------------
1 | icon('heroicon-s-cog')
14 | ->tooltip('Accounts Types')
15 | ->label('Accounts Types')
16 | ->hiddenLabel()
17 | ->url(AccountTypes::getUrl());
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Actions/Components/ViewAction.php:
--------------------------------------------------------------------------------
1 | getActions();
25 | }
26 |
27 | public function getActions(): array
28 | {
29 | return collect($this->getDefaultActions())->merge(self::$actions)->map(function (StaticAction $action) {
30 | if (method_exists($action, 'record') && str($action->getName())->contains(['create', 'edit', 'view', 'impersonate'])) {
31 | $action->record(method_exists(self::$page, 'getRecord') ? self::$page->getRecord() : null)
32 | ->model(method_exists(self::$page, 'getModel') ? self::$page->getModel() : null)
33 | ->modelLabel(method_exists(self::$page, 'getModelLabel') ? get_model_label(self::$page->getModel()) : null)
34 | ->form(fn (Form $form) => app(self::$page->getResource())::form($form))
35 | ->url(fn () => isset(app(self::$page->getResource())::getPages()[$action->getName()]) ? app(app(self::$page->getResource())::getPages()[$action->getName()]->getPage())->getUrl(['record' => method_exists(self::$page, 'getRecord') ? self::$page->getRecord() : null]) : null);
36 | }
37 |
38 | return $action;
39 | })->toArray();
40 | }
41 |
42 | public static function register(StaticAction | array | \Closure $component): void
43 | {
44 | if (is_array($component)) {
45 | foreach ($component as $item) {
46 | if ($item instanceof StaticAction) {
47 | self::$actions[] = $item;
48 | }
49 | }
50 | } elseif ($component instanceof \Closure) {
51 | self::$actions[] = (new self)->evaluate($component);
52 | } else {
53 | self::$actions[] = $component;
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Actions/CreatePageActions.php:
--------------------------------------------------------------------------------
1 | schema(self::getSchema())->columns(2);
15 | }
16 |
17 | public static function getDefaultComponents(): array
18 | {
19 | return [
20 | Components\Name::make(),
21 | Components\Email::make(),
22 | Components\Phone::make(),
23 | ];
24 | }
25 |
26 | private static function getSchema(): array
27 | {
28 | return array_merge(self::getDefaultComponents(), self::$schema);
29 | }
30 |
31 | public static function register(Field | array $component): void
32 | {
33 | if (is_array($component)) {
34 | foreach ($component as $item) {
35 | if ($item instanceof Field) {
36 | self::$schema[] = $item;
37 | }
38 | }
39 |
40 | } else {
41 | self::$schema[] = $component;
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Form/Components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomatophp/filament-accounts/7f5f11765de2781e119f826163e9dcb7a8c1a347/src/Filament/Resources/AccountResource/Form/Components/.gitkeep
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Form/Components/Address.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.columns.address'))
13 | ->columnSpanFull();
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Form/Components/Avatar.php:
--------------------------------------------------------------------------------
1 | alignCenter()
13 | ->collection('avatar')
14 | ->columnSpan(2)
15 | ->label(trans('filament-accounts::messages.accounts.columns.avatar'));
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Form/Components/Component.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.columns.email'))
13 | ->required(fn (Forms\Get $get) => $get('loginBy') === 'email')
14 | ->email()
15 | ->maxLength(255);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Form/Components/IsActive.php:
--------------------------------------------------------------------------------
1 | columnSpan(2)
13 | ->label(trans('filament-accounts::messages.accounts.columns.is_active'))
14 | ->default(false)
15 | ->required();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Form/Components/IsLogin.php:
--------------------------------------------------------------------------------
1 | default(false)
12 | ->columnSpan(2)
13 | ->label(trans('filament-accounts::messages.accounts.columns.is_login'))
14 | ->live();
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Form/Components/LoginBy.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.columns.loginBy'))
13 | ->searchable()
14 | ->options([
15 | 'email' => trans('filament-accounts::messages.accounts.columns.email'),
16 | 'phone' => trans('filament-accounts::messages.accounts.columns.phone'),
17 | ])
18 | ->required()
19 | ->default('email');
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Form/Components/Name.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.columns.name'))
13 | ->columnSpan(2)
14 | ->required()
15 | ->maxLength(255);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Form/Components/Password.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.columns.password'))
13 | ->confirmed()
14 | ->visible(fn (Forms\Get $get) => $get('is_login'))
15 | ->password()
16 | ->dehydrateStateUsing(fn ($state) => bcrypt($state))
17 | ->maxLength(255);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Form/Components/PasswordConfirmation.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.columns.password_confirmation'))
13 | ->visible(fn (Forms\Get $get) => $get('is_login'))
14 | ->password()
15 | ->maxLength(255);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Form/Components/Phone.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.columns.phone'))
13 | ->required(fn (Forms\Get $get) => $get('loginBy') === 'phone')
14 | ->tel()
15 | ->maxLength(255);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Form/Components/Type.php:
--------------------------------------------------------------------------------
1 | columnSpanFull()
14 | ->label(trans('filament-accounts::messages.accounts.columns.type'))
15 | ->searchable()
16 | ->required()
17 | ->options(\TomatoPHP\FilamentTypes\Models\Type::query()->where('for', 'accounts')->where('type', 'type')->pluck('name', 'key')->toArray())
18 | ->default('account');
19 | } else {
20 | return Forms\Components\TextInput::make('type')
21 | ->columnSpanFull()
22 | ->label(trans('filament-accounts::messages.accounts.columns.type'))
23 | ->required()
24 | ->default('account');
25 | }
26 |
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/InfoList/AccountInfoList.php:
--------------------------------------------------------------------------------
1 | schema(self::getSchema())->columns(2);
15 | }
16 |
17 | public static function getDefaultComponents(): array
18 | {
19 | return [
20 | Entries\Name::make(),
21 | Entries\Email::make(),
22 | Entries\Phone::make(),
23 | ];
24 | }
25 |
26 | private static function getSchema(): array
27 | {
28 | return array_merge(self::getDefaultComponents(), self::$schema);
29 | }
30 |
31 | public static function register(Entry | array $component): void
32 | {
33 | if (is_array($component)) {
34 | foreach ($component as $item) {
35 | if ($item instanceof Entry) {
36 | self::$schema[] = $item;
37 | }
38 | }
39 |
40 | } else {
41 | self::$schema[] = $component;
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/InfoList/Entries/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomatophp/filament-accounts/7f5f11765de2781e119f826163e9dcb7a8c1a347/src/Filament/Resources/AccountResource/InfoList/Entries/.gitkeep
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/InfoList/Entries/Address.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.columns.address'))
13 | ->columnSpanFull();
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/InfoList/Entries/Avatar.php:
--------------------------------------------------------------------------------
1 | alignCenter()
13 | ->collection('avatar')
14 | ->columnSpan(2)
15 | ->columnSpanFull()
16 | ->label(trans('filament-accounts::messages.accounts.columns.avatar'));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/InfoList/Entries/Email.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.columns.email'));
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/InfoList/Entries/Entry.php:
--------------------------------------------------------------------------------
1 | columnSpan(2)
13 | ->label(trans('filament-accounts::messages.accounts.columns.is_active'))
14 | ->boolean();
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/InfoList/Entries/IsLogin.php:
--------------------------------------------------------------------------------
1 | default(false)
12 | ->columnSpan(2)
13 | ->label(trans('filament-accounts::messages.accounts.columns.is_login'))
14 | ->boolean();
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/InfoList/Entries/LoginBy.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.columns.loginBy'));
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/InfoList/Entries/Name.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.columns.name'))
13 | ->columnSpan(2);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/InfoList/Entries/Phone.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.columns.phone'));
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/InfoList/Entries/Type.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.columns.type'));
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Pages/AccountTypes.php:
--------------------------------------------------------------------------------
1 | $parameters
13 | */
14 | public static function getUrl(array $parameters = [], bool $isAbsolute = true, ?string $panel = null, ?Model $tenant = null): string
15 | {
16 | if (blank($panel) || Filament::getPanel($panel)->hasTenancy()) {
17 | $parameters['tenant'] ??= ($tenant ?? Filament::getTenant());
18 | }
19 |
20 | return route(static::getRouteName($panel), $parameters, $isAbsolute);
21 | }
22 |
23 | public function getTitle(): string
24 | {
25 | return trans('filament-accounts::messages.settings.types.title');
26 | }
27 |
28 | public function getType(): string
29 | {
30 | return 'type';
31 | }
32 |
33 | public function getFor(): string
34 | {
35 | return 'accounts';
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Pages/CreateAccount.php:
--------------------------------------------------------------------------------
1 | slug()->toString();
23 | }
24 |
25 | return $data;
26 | }
27 |
28 | protected function getHeaderActions(): array
29 | {
30 | return config('filament-accounts.resource.pages.create') ? config('filament-accounts.resource.pages.create')::make($this) : AccountResource\Actions\CreatePageActions::make($this);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Pages/EditAccount.php:
--------------------------------------------------------------------------------
1 | deferLoading()
16 | ->bulkActions(config('filament-accounts.resource.table.bulkActions') ? config('filament-accounts.resource.table.bulkActions')::make() : AccountBulkActions::make())
17 | ->actions(config('filament-accounts.resource.table.actions') ? config('filament-accounts.resource.table.actions')::make() : AccountActions::make())
18 | ->filters(config('filament-accounts.resource.table.filters') ? config('filament-accounts.resource.table.filters')::make() : AccountFilters::make())
19 | ->headerActions(config('filament-accounts.resource.table.headerActions') ? config('filament-accounts.resource.table.headerActions')::make() : AccountHeaderActions::make())
20 | ->defaultSort('id', 'desc')
21 | ->columns(self::getColumns());
22 | }
23 |
24 | public static function getDefaultColumns(): array
25 | {
26 | return [
27 | Columns\Id::make(),
28 | Columns\Name::make(),
29 | Columns\Email::make(),
30 | Columns\Phone::make(),
31 | Columns\CreatedAt::make(),
32 | Columns\UpdatedAt::make(),
33 | ];
34 | }
35 |
36 | private static function getColumns(): array
37 | {
38 | return array_merge(self::getDefaultColumns(), self::$columns);
39 | }
40 |
41 | public static function register(Column | array $column): void
42 | {
43 | if (is_array($column)) {
44 | foreach ($column as $item) {
45 | if ($item instanceof Column) {
46 | self::$columns[] = $item;
47 | }
48 | }
49 | } else {
50 | self::$columns[] = $column;
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Table/Actions/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomatophp/filament-accounts/7f5f11765de2781e119f826163e9dcb7a8c1a347/src/Filament/Resources/AccountResource/Table/Actions/.gitkeep
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Table/Actions/Action.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.actions.password'))
14 | ->icon('heroicon-s-lock-closed')
15 | ->iconButton()
16 | ->tooltip(trans('filament-accounts::messages.accounts.actions.password'))
17 | ->color('danger')
18 | ->form([
19 | Forms\Components\TextInput::make('password')
20 | ->label(trans('filament-accounts::messages.accounts.columns.password'))
21 | ->password()
22 | ->required()
23 | ->confirmed()
24 | ->maxLength(255),
25 | Forms\Components\TextInput::make('password_confirmation')
26 | ->label(trans('filament-accounts::messages.accounts.columns.password_confirmation'))
27 | ->password()
28 | ->required()
29 | ->maxLength(255),
30 | ])
31 | ->action(function (array $data, $record) {
32 | $record->password = bcrypt($data['password']);
33 | $record->save();
34 |
35 | Notification::make()
36 | ->title('Account Password Changed')
37 | ->body('Account password changed successfully')
38 | ->success()
39 | ->send();
40 | });
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Table/Actions/DeleteAction.php:
--------------------------------------------------------------------------------
1 | iconButton()
13 | ->tooltip(__('filament-actions::delete.single.label'));
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Table/Actions/EditAction.php:
--------------------------------------------------------------------------------
1 | iconButton()
13 | ->tooltip(__('filament-actions::edit.single.label'));
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Table/Actions/ImpersonateAction.php:
--------------------------------------------------------------------------------
1 | guard('accounts')
14 | ->color('info')
15 | ->tooltip(trans('filament-accounts::messages.accounts.actions.impersonate'))
16 | ->redirectTo(config('filament-accounts.features.impersonate.redirect'));
17 | } else {
18 | return \Filament\Tables\Actions\Action::make('impersonate');
19 | }
20 |
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Table/Actions/ViewAction.php:
--------------------------------------------------------------------------------
1 | iconButton()
13 | ->tooltip(__('filament-actions::view.single.label'));
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Table/BulkActions/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomatophp/filament-accounts/7f5f11765de2781e119f826163e9dcb7a8c1a347/src/Filament/Resources/AccountResource/Table/BulkActions/.gitkeep
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Table/BulkActions/Action.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.columns.account'))
14 | ->toggleable()
15 | ->sortable();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Table/Columns/Column.php:
--------------------------------------------------------------------------------
1 | dateTime()
13 | ->description(fn ($record) => $record->created_at->diffForHumans())
14 | ->toggleable(isToggledHiddenByDefault: true)
15 | ->sortable();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Table/Columns/Email.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.columns.email'))
13 | ->toggleable(isToggledHiddenByDefault: filament('filament-accounts')->useAvatar)
14 | ->sortable()
15 | ->searchable();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Table/Columns/Id.php:
--------------------------------------------------------------------------------
1 | sortable();
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Table/Columns/IsActive.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.columns.is_active'))
13 | ->toggleable(isToggledHiddenByDefault: true)
14 | ->sortable()
15 | ->boolean();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Table/Columns/IsLogin.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.columns.is_login'))
13 | ->toggleable(isToggledHiddenByDefault: true)
14 | ->sortable()
15 | ->boolean();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Table/Columns/Name.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.columns.name'))
13 | ->toggleable(isToggledHiddenByDefault: filament('filament-accounts')->useAvatar)
14 | ->sortable()
15 | ->searchable();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Table/Columns/Phone.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.columns.phone'))
13 | ->toggleable(isToggledHiddenByDefault: filament('filament-accounts')->useAvatar)
14 | ->sortable()
15 | ->searchable();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Table/Columns/Type.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.columns.type'))
14 | ->toggleable()
15 | ->sortable()
16 | ->searchable();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Table/Columns/UpdatedAt.php:
--------------------------------------------------------------------------------
1 | dateTime()
13 | ->description(fn ($record) => $record->updated_at->diffForHumans())
14 | ->toggleable(isToggledHiddenByDefault: true)
15 | ->sortable();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Table/Filters/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomatophp/filament-accounts/7f5f11765de2781e119f826163e9dcb7a8c1a347/src/Filament/Resources/AccountResource/Table/Filters/.gitkeep
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Table/Filters/Filter.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.filters.is_active'));
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Table/Filters/IsLogin.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.filters.is_login'));
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Table/Filters/Trashed.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.filters.type'))
11 | ->searchable()
12 | ->preload()
13 | ->options(\TomatoPHP\FilamentTypes\Models\Type::query()->where('for', 'accounts')->where('type', 'type')->pluck('name', 'key')->toArray());
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Table/HeaderActions/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomatophp/filament-accounts/7f5f11765de2781e119f826163e9dcb7a8c1a347/src/Filament/Resources/AccountResource/Table/HeaderActions/.gitkeep
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Table/HeaderActions/Action.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.export.title'))
15 | ->requiresConfirmation()
16 | ->color('info')
17 | ->icon('heroicon-o-arrow-down-on-square')
18 | ->fillForm([
19 | 'columns' => [
20 | 'id' => trans('filament-accounts::messages.accounts.columns.id'),
21 | 'name' => trans('filament-accounts::messages.accounts.columns.name'),
22 | 'email' => trans('filament-accounts::messages.accounts.columns.email'),
23 | 'phone' => trans('filament-accounts::messages.accounts.columns.phone'),
24 | 'address' => trans('filament-accounts::messages.accounts.columns.address'),
25 | 'type' => trans('filament-accounts::messages.accounts.columns.type'),
26 | 'is_login' => trans('filament-accounts::messages.accounts.columns.is_login'),
27 | 'is_active' => trans('filament-accounts::messages.accounts.columns.is_active'),
28 | 'created_at' => trans('filament-accounts::messages.accounts.columns.created_at'),
29 | 'updated_at' => trans('filament-accounts::messages.accounts.columns.updated_at'),
30 | ],
31 | ])
32 | ->form([
33 | Forms\Components\KeyValue::make('columns')
34 | ->label(trans('filament-accounts::messages.accounts.export.columns'))
35 | ->required()
36 | ->editableKeys(false)
37 | ->addable(false),
38 | ])
39 | ->action(function (array $data) {
40 | return Excel::download(new ExportAccounts($data), 'accounts.csv');
41 | });
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Filament/Resources/AccountResource/Table/HeaderActions/ImportAction.php:
--------------------------------------------------------------------------------
1 | label(trans('filament-accounts::messages.accounts.import.title'))
16 | ->form([
17 | Forms\Components\FileUpload::make('excel')
18 | ->hint(trans('filament-accounts::messages.accounts.import.hint'))
19 | ->label(trans('filament-accounts::messages.accounts.import.excel'))
20 | ->acceptedFileTypes(['text/csv', 'application/vnd.ms-excel'])
21 | ->required(),
22 | ])
23 | ->action(function (array $data) {
24 | try {
25 | Excel::import(new ImportAccounts, storage_path('app/public/' . $data['excel']));
26 |
27 | Notification::make()
28 | ->title(trans('filament-accounts::messages.accounts.import.success'))
29 | ->body(trans('filament-accounts::messages.accounts.import.body'))
30 | ->success()
31 | ->send();
32 | } catch (\Exception $e) {
33 | Notification::make()
34 | ->title(trans('filament-accounts::messages.accounts.import.error'))
35 | ->body(trans('filament-accounts::messages.accounts.import.error-body'))
36 | ->danger()
37 | ->send();
38 | }
39 |
40 | })
41 | ->color('warning')
42 | ->icon('heroicon-o-arrow-up-on-square');
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/FilamentAccountsPlugin.php:
--------------------------------------------------------------------------------
1 | useTypes) {
56 | $panel->pages([
57 | AccountResource\Pages\AccountTypes::class,
58 | ]);
59 | }
60 |
61 | if ($this->useResource) {
62 | $panel->resources($resources);
63 | }
64 |
65 | }
66 |
67 | public function useExport(bool $useExport = true): static
68 | {
69 | $this->useExport = $useExport;
70 |
71 | return $this;
72 | }
73 |
74 | public function useResource(bool $useResource = true): static
75 | {
76 | $this->useResource = $useResource;
77 |
78 | return $this;
79 | }
80 |
81 | public function useImport(bool $useImport = true): static
82 | {
83 | $this->useImport = $useImport;
84 |
85 | return $this;
86 | }
87 |
88 | public function useTeams(bool $useTeams = true): static
89 | {
90 | $this->useTeams = $useTeams;
91 |
92 | return $this;
93 | }
94 |
95 | public function useNotifications(bool $useNotifications = true): static
96 | {
97 | $this->useNotifications = $useNotifications;
98 |
99 | return $this;
100 | }
101 |
102 | public function useTypes(bool $useTypes = true): static
103 | {
104 | $this->useTypes = $useTypes;
105 |
106 | return $this;
107 | }
108 |
109 | public function useAvatar(bool $useAvatar = true): static
110 | {
111 | $this->useAvatar = $useAvatar;
112 |
113 | return $this;
114 | }
115 |
116 | public function useLoginBy(bool $useLoginBy = true): static
117 | {
118 | $this->useLoginBy = $useLoginBy;
119 |
120 | return $this;
121 | }
122 |
123 | public function showAddressField(bool $showAddressField = true): static
124 | {
125 | $this->showAddressField = $showAddressField;
126 |
127 | return $this;
128 | }
129 |
130 | public function canLogin(bool $canLogin = true): static
131 | {
132 | $this->canLogin = $canLogin;
133 |
134 | return $this;
135 | }
136 |
137 | public function canBlocked(bool $canBlocked = true): static
138 | {
139 | $this->canBlocked = $canBlocked;
140 |
141 | return $this;
142 | }
143 |
144 | public function useImpersonate(bool $useImpersonate = true): static
145 | {
146 | $this->useImpersonate = $useImpersonate;
147 |
148 | return $this;
149 | }
150 |
151 | public function impersonateRedirect(?string $impersonateRedirect): static
152 | {
153 | $this->impersonateRedirect = $impersonateRedirect;
154 |
155 | return $this;
156 | }
157 |
158 | public function showTypeField(bool $showTypeField = true): static
159 | {
160 | $this->showTypeField = $showTypeField;
161 |
162 | return $this;
163 | }
164 |
165 | public function boot(Panel $panel): void
166 | {
167 | Config::set('filament-accounts.features.notifications', $this->useNotifications);
168 | Config::set('filament-accounts.features.loginBy', $this->useLoginBy);
169 | Config::set('filament-accounts.features.types', $this->useTypes);
170 | Config::set('filament-accounts.features.avatar', $this->useAvatar);
171 | Config::set('filament-accounts.features.impersonate.active', $this->useImpersonate);
172 | Config::set('filament-accounts.features.impersonate.redirect', $this->impersonateRedirect);
173 |
174 | if ($this->showAddressField) {
175 | AccountResource\Form\AccountForm::register(AccountResource\Form\Components\Address::make());
176 | AccountResource\InfoList\AccountInfoList::register(AccountResource\InfoList\Entries\Address::make());
177 | }
178 |
179 | if ($this->useAvatar) {
180 | AccountResource\Form\AccountForm::register(AccountResource\Form\Components\Avatar::make());
181 | AccountResource\InfoList\AccountInfoList::register(AccountResource\InfoList\Entries\Avatar::make());
182 | AccountResource\Table\AccountTable::register(AccountResource\Table\Columns\Account::make());
183 | }
184 |
185 | if ($this->useTypes) {
186 | FilamentTypes::register(
187 | TypeFor::make('accounts')
188 | ->label('Accounts')
189 | ->types([
190 | TypeOf::make('type')
191 | ->label('Type')
192 | ->register([
193 | Type::make('customer')
194 | ->name([
195 | 'ar' => 'عميل',
196 | 'en' => 'Customer',
197 | ])
198 | ->icon('heroicon-c-user-group')
199 | ->color('#d91919'),
200 | Type::make('account')
201 | ->name([
202 | 'ar' => 'حساب',
203 | 'en' => 'Account',
204 | ])
205 | ->icon('heroicon-c-user-circle')
206 | ->color('#0a56d9'),
207 | ]),
208 | ])
209 | );
210 | AccountResource\Table\AccountFilters::register(AccountResource\Table\Filters\Type::make());
211 | AccountResource\Form\AccountForm::register(AccountResource\Form\Components\Type::make());
212 | AccountResource\Table\AccountTable::register(AccountResource\Table\Columns\Type::make());
213 | AccountResource\InfoList\AccountInfoList::register(AccountResource\InfoList\Entries\Type::make());
214 | AccountResource\Actions\ManagePageActions::register(AccountResource\Actions\Components\TypesAction::make());
215 | }
216 |
217 | if ($this->canLogin) {
218 | AccountResource\Table\AccountFilters::register(AccountResource\Table\Filters\IsLogin::make());
219 | AccountResource\Form\AccountForm::register(AccountResource\Form\Components\IsLogin::make());
220 | AccountResource\Form\AccountForm::register(AccountResource\Form\Components\Password::make());
221 | AccountResource\Form\AccountForm::register(AccountResource\Form\Components\PasswordConfirmation::make());
222 | AccountResource\Table\AccountTable::register(AccountResource\Table\Columns\IsLogin::make());
223 | AccountResource\Table\AccountActions::register(AccountResource\Table\Actions\ChangePasswordAction::make());
224 | AccountResource\InfoList\AccountInfoList::register(AccountResource\InfoList\Entries\IsLogin::make());
225 | }
226 |
227 | if ($this->canBlocked) {
228 | AccountResource\Table\AccountFilters::register(AccountResource\Table\Filters\IsActive::make());
229 | AccountResource\Form\AccountForm::register(AccountResource\Form\Components\IsActive::make());
230 | AccountResource\Table\AccountTable::register(AccountResource\Table\Columns\IsActive::make());
231 | AccountResource\InfoList\AccountInfoList::register(AccountResource\InfoList\Entries\IsActive::make());
232 | }
233 |
234 | if ($this->useLoginBy) {
235 | AccountResource\Form\AccountForm::register(AccountResource\Form\Components\LoginBy::make());
236 | AccountResource\InfoList\AccountInfoList::register(AccountResource\InfoList\Entries\LoginBy::make());
237 | }
238 |
239 | if ($this->useExport) {
240 | AccountResource\Table\AccountHeaderActions::register(AccountResource\Table\HeaderActions\ExportAction::make());
241 | }
242 |
243 | if ($this->useImport) {
244 | AccountResource\Table\AccountHeaderActions::register(AccountResource\Table\HeaderActions\ImportAction::make());
245 | }
246 |
247 | if ($this->useImpersonate) {
248 | AccountResource\Table\AccountActions::register(AccountResource\Table\Actions\ImpersonateAction::make());
249 | }
250 | }
251 |
252 | public static function make(): FilamentAccountsPlugin
253 | {
254 | return new FilamentAccountsPlugin;
255 | }
256 | }
257 |
--------------------------------------------------------------------------------
/src/FilamentAccountsServiceProvider.php:
--------------------------------------------------------------------------------
1 | commands([
13 | \TomatoPHP\FilamentAccounts\Console\FilamentAccountsInstall::class,
14 | ]);
15 |
16 | // Register Config file
17 | $this->mergeConfigFrom(__DIR__ . '/../config/filament-accounts.php', 'filament-accounts');
18 |
19 | // Publish Config
20 | $this->publishes([
21 | __DIR__ . '/../config/filament-accounts.php' => config_path('filament-accounts.php'),
22 | ], 'filament-accounts-config');
23 |
24 | // Register Migrations
25 | $this->loadMigrationsFrom(__DIR__ . '/../database/migrations');
26 |
27 | // Publish Migrations
28 | $this->publishes([
29 | __DIR__ . '/../database/migrations' => database_path('migrations'),
30 | ], 'filament-accounts-migrations');
31 | // Register views
32 | $this->loadViewsFrom(__DIR__ . '/../resources/views', 'filament-accounts');
33 |
34 | // Publish Views
35 | $this->publishes([
36 | __DIR__ . '/../resources/views' => resource_path('views/vendor/filament-accounts'),
37 | ], 'filament-accounts-views');
38 |
39 | // Register Langs
40 | $this->loadTranslationsFrom(__DIR__ . '/../resources/lang', 'filament-accounts');
41 |
42 | // Publish Lang
43 | $this->publishes([
44 | __DIR__ . '/../resources/lang' => base_path('lang/vendor/filament-accounts'),
45 | ], 'filament-accounts-lang');
46 |
47 | $this->publishes([
48 | __DIR__ . '/../publish/Account.php' => app_path('Models/Account.php'),
49 | ], 'filament-accounts-model');
50 |
51 | $this->app->bind('filament-accounts', function () {
52 | return new \TomatoPHP\FilamentAccounts\Services\FilamentAccountsServices;
53 | });
54 | }
55 |
56 | public function boot(): void
57 | {
58 | //
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/Import/ImportAccounts.php:
--------------------------------------------------------------------------------
1 | contains(trans('filament-accounts::messages.accounts.columns.id'))) {
15 | continue;
16 | } else {
17 | $account = Account::query()->firstOrCreate([
18 | 'email' => $row[2] ?? null,
19 | 'phone' => $row[3] ?? null,
20 | 'username' => $row[2] ?? null,
21 | ], [
22 | 'name' => $row[1],
23 | 'email' => $row[2] ?? null,
24 | 'phone' => $row[3] ?? null,
25 | 'username' => $row[2] ?? null,
26 | 'address' => $row[4] ?? null,
27 | 'type' => $row[5] ?? 'account',
28 | 'is_active' => $row[6] ?? false,
29 | ]);
30 |
31 | if ($account->exists) {
32 | $account->update([
33 | 'name' => $row[1],
34 | 'email' => $row[2] ?? null,
35 | 'phone' => $row[3] ?? null,
36 | 'username' => $row[2] ?? null,
37 | 'address' => $row[4] ?? null,
38 | 'type' => $row[5] ?? 'account',
39 | 'is_active' => $row[6] ?? false,
40 | ]);
41 | }
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/Models/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomatophp/filament-accounts/7f5f11765de2781e119f826163e9dcb7a8c1a347/src/Models/.gitkeep
--------------------------------------------------------------------------------
/src/Models/Account.php:
--------------------------------------------------------------------------------
1 | 'boolean',
68 | 'is_active' => 'boolean',
69 | ];
70 |
71 | protected $dates = [
72 | 'deleted_at',
73 | 'created_at',
74 | 'updated_at',
75 | 'otp_activated_at',
76 | 'last_login',
77 | ];
78 |
79 | protected $hidden = [
80 | 'password',
81 | 'remember_token',
82 | 'otp_code',
83 | 'otp_activated_at',
84 | 'host',
85 | 'agent',
86 | ];
87 |
88 | public function getFilamentAvatarUrl(): ?string
89 | {
90 | return $this->getFirstMediaUrl('avatar') ?? null;
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/Services/FilamentAccountsServices.php:
--------------------------------------------------------------------------------
1 | relations[] = $item;
14 | }
15 | } else {
16 | $this->relations[] = $relation;
17 | }
18 | }
19 |
20 | public function getRelations(): array
21 | {
22 | return $this->relations;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/Pest.php:
--------------------------------------------------------------------------------
1 | in(__DIR__);
6 |
--------------------------------------------------------------------------------
/tests/database/database.sqlite:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomatophp/filament-accounts/7f5f11765de2781e119f826163e9dcb7a8c1a347/tests/database/database.sqlite
--------------------------------------------------------------------------------
/tests/database/factories/AccountFactory.php:
--------------------------------------------------------------------------------
1 | faker->unique()->safeEmail();
16 |
17 | return [
18 | 'name' => $this->faker->name(),
19 | 'type' => 'account',
20 | 'address' => $this->faker->address(),
21 | 'phone' => $this->faker->unique()->phoneNumber(),
22 | 'email' => $email,
23 | 'username' => $email,
24 | 'loginBy' => 'email',
25 | 'password' => Hash::make($this->faker->password(8)), // password
26 | 'is_active' => 1,
27 | ];
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/tests/database/factories/UserFactory.php:
--------------------------------------------------------------------------------
1 | $this->faker->name(),
17 | 'email' => $this->faker->unique()->safeEmail(),
18 | 'email_verified_at' => now(),
19 | 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
20 | 'remember_token' => Str::random(10),
21 | ];
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/tests/src/AccountResourceTest.php:
--------------------------------------------------------------------------------
1 | create());
18 | });
19 |
20 | it('can render account resource', function () {
21 | get(AccountResource::getUrl())->assertSuccessful();
22 | });
23 |
24 | it('can list posts', function () {
25 | Account::query()->delete();
26 | $accounts = Account::factory()->count(10)->create();
27 |
28 | livewire(Pages\ListAccounts::class)
29 | ->loadTable()
30 | ->assertCanSeeTableRecords($accounts)
31 | ->assertCountTableRecords(10);
32 | });
33 |
34 | it('can render account name/email/phone column in table', function () {
35 | Account::factory()->count(10)->create();
36 |
37 | livewire(Pages\ListAccounts::class)
38 | ->loadTable()
39 | ->assertCanRenderTableColumn('id')
40 | ->assertCanRenderTableColumn('name')
41 | ->assertCanRenderTableColumn('phone')
42 | ->assertCanRenderTableColumn('email');
43 | });
44 |
45 | it('can render account list page', function () {
46 | livewire(Pages\ListAccounts::class)->assertSuccessful();
47 | });
48 |
49 | it('can render view account action', function () {
50 | livewire(Pages\ManageAccounts::class, [
51 | 'record' => Account::factory()->create(),
52 | ])
53 | ->mountAction('view')
54 | ->assertSuccessful();
55 | });
56 |
57 | it('can render view account page', function () {
58 | get(AccountResource::getUrl('view', [
59 | 'record' => Account::factory()->create(),
60 | ]))->assertSuccessful();
61 | });
62 |
63 | it('can render account create action', function () {
64 | livewire(Pages\ManageAccounts::class)
65 | ->mountAction('create')
66 | ->assertSuccessful();
67 | });
68 |
69 | it('can render account create page', function () {
70 | get(AccountResource::getUrl('create'))->assertSuccessful();
71 | });
72 |
73 | it('can create new account', function () {
74 | $newData = Account::factory()->make();
75 |
76 | $password = str()->random(10);
77 |
78 | livewire(Pages\CreateAccount::class)
79 | ->fillForm([
80 | 'name' => $newData->name,
81 | 'email' => $newData->email,
82 | 'phone' => $newData->phone,
83 | ])
84 | ->call('create')
85 | ->assertHasNoFormErrors();
86 |
87 | assertDatabaseHas(Account::class, [
88 | 'name' => $newData->name,
89 | 'email' => $newData->email,
90 | 'phone' => $newData->phone,
91 | ]);
92 | });
93 |
94 | it('can validate account input', function () {
95 | livewire(Pages\CreateAccount::class)
96 | ->fillForm([
97 | 'name' => null,
98 | ])
99 | ->call('create')
100 | ->assertHasFormErrors([
101 | 'name' => 'required',
102 | ]);
103 | });
104 |
105 | it('can render account edit action', function () {
106 | livewire(Pages\ManageAccounts::class, [
107 | 'record' => Account::factory()->create(),
108 | ])
109 | ->mountAction('edit')
110 | ->assertSuccessful();
111 | });
112 |
113 | it('can render account edit page', function () {
114 | get(AccountResource::getUrl('edit', [
115 | 'record' => Account::factory()->create(),
116 | ]))->assertSuccessful();
117 | });
118 |
119 | it('can retrieve account data', function () {
120 | $account = Account::factory()->create();
121 |
122 | livewire(Pages\EditAccount::class, [
123 | 'record' => $account->getRouteKey(),
124 | ])
125 | ->assertFormSet([
126 | 'name' => $account->name,
127 | 'email' => $account->email,
128 | ]);
129 | });
130 |
131 | it('can validate edit account input', function () {
132 | $account = Account::factory()->create();
133 |
134 | livewire(Pages\EditAccount::class, [
135 | 'record' => $account->getRouteKey(),
136 | ])
137 | ->fillForm([
138 | 'name' => null,
139 | ])
140 | ->call('save')
141 | ->assertHasFormErrors([
142 | 'name' => 'required',
143 | ]);
144 | });
145 |
146 | it('can save account data', function () {
147 | $account = Account::factory()->create();
148 | $newData = Account::factory()->make();
149 |
150 | livewire(Pages\EditAccount::class, [
151 | 'record' => $account->getRouteKey(),
152 | ])
153 | ->fillForm([
154 | 'name' => $newData->name,
155 | 'email' => $newData->email,
156 | ])
157 | ->call('save')
158 | ->assertHasNoFormErrors();
159 |
160 | expect($account->refresh())
161 | ->name->toBe($newData->name)
162 | ->email->toBe($newData->email);
163 | });
164 |
165 | it('can delete account', function () {
166 | $account = Account::factory()->create();
167 |
168 | livewire(Pages\EditAccount::class, [
169 | 'record' => $account->getRouteKey(),
170 | ])
171 | ->callAction('deleteSelectedAccount');
172 |
173 | assertNotEmpty(Account::query()->withTrashed()->find($account->getRouteKey())->deleted_at);
174 | });
175 |
--------------------------------------------------------------------------------
/tests/src/AdminPanelProvider.php:
--------------------------------------------------------------------------------
1 | default()
26 | ->id('admin')
27 | ->path('admin')
28 | ->login()
29 | ->pages([
30 | Pages\Dashboard::class,
31 | ])
32 | ->plugin(
33 | FilamentAccountsPlugin::make()
34 | )
35 | ->middleware([
36 | EncryptCookies::class,
37 | AddQueuedCookiesToResponse::class,
38 | StartSession::class,
39 | AuthenticateSession::class,
40 | ShareErrorsFromSession::class,
41 | VerifyCsrfToken::class,
42 | SubstituteBindings::class,
43 | DisableBladeIconComponents::class,
44 | DispatchServingFilamentEvent::class,
45 | ])
46 | ->authMiddleware([
47 | Authenticate::class,
48 | ]);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/tests/src/DebugTest.php:
--------------------------------------------------------------------------------
1 | each->not->toBeUsed();
5 | });
6 |
--------------------------------------------------------------------------------
/tests/src/Models/Account.php:
--------------------------------------------------------------------------------
1 | 'boolean',
69 | 'is_active' => 'boolean',
70 | ];
71 |
72 | protected $dates = [
73 | 'deleted_at',
74 | 'created_at',
75 | 'updated_at',
76 | 'otp_activated_at',
77 | 'last_login',
78 | ];
79 |
80 | protected $hidden = [
81 | 'password',
82 | 'remember_token',
83 | 'otp_code',
84 | 'otp_activated_at',
85 | 'host',
86 | 'agent',
87 | ];
88 |
89 | public function getFilamentAvatarUrl(): ?string
90 | {
91 | return $this->getFirstMediaUrl('avatar') ?? null;
92 | }
93 |
94 | protected static function newFactory(): AccountFactory
95 | {
96 | return AccountFactory::new();
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/tests/src/Models/User.php:
--------------------------------------------------------------------------------
1 | plugins([
10 | FilamentAccountsPlugin::make(),
11 | ]);
12 |
13 | expect($panel->getPlugin('filament-accounts'))
14 | ->not()
15 | ->toThrow(Exception::class);
16 | });
17 |
18 | // it('can modify avatar', function ($condition) {
19 | // $plugin = FilamentAccountsPlugin::make()
20 | // ->useAvatar($condition);
21 | //
22 | // expect($plugin::hasAvatar())->toBe($condition);
23 | // })->with([
24 | // false,
25 | // fn () => true,
26 | // ]);
27 |
--------------------------------------------------------------------------------
/tests/src/TestCase.php:
--------------------------------------------------------------------------------
1 | loadMigrationsFrom(__DIR__ . '/../../database/migrations');
54 | }
55 |
56 | public function getEnvironmentSetUp($app): void
57 | {
58 | $app['config']->set('filament-accounts.simple', false);
59 | $app['config']->set('database.default', 'sqlite');
60 | $app['config']->set('database.connections.sqlite.database', __DIR__ . '/../database/database.sqlite');
61 |
62 | $app['config']->set('view.paths', [
63 | ...$app['config']->get('view.paths'),
64 | __DIR__ . '/../resources/views',
65 | ]);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------