Build and Push Docker Images / Build and Push Docker Images (push) Failing after 8s
184 lines
14 KiB
Markdown
184 lines
14 KiB
Markdown
# UI Copy Inventory
|
|
|
|
Every hardcoded user-facing string in `app/` and `components/` (excludes `components/ui/` primitives). Interpolated parts marked `{like_this}`. Includes messages that originate in `actions/`, `queries/`, `lib/schemas.ts` where they surface in the UI. This feeds i18n and the framework port.
|
|
|
|
## 1. Auth & onboarding
|
|
|
|
**login-form** — `Enter phone number` (placeholder), `Login` (button).
|
|
|
|
**verify-otp-form** — `Login OTP Sent to {phone_number}`, `Enter the OTP` (sr-only), `Enter OTP` (placeholder), `Login`, `Change` / `phone number` (link), toasts: `The token you entered isn't valid.`, `Unable to log in. Please try again or contact support.`
|
|
|
|
**verify-registration-otp-form** — `Account verification OTP sent to [{phone_number}]`, `Enter the OTP`, `Enter OTP`, `Request verification`, `Go to` / `login`.
|
|
|
|
**signup-form** — `SAR Link by OmegaTech Solutions`, `Register your account`, `Pay for your devices and track your bills.`; labels/placeholders: `Full Name`, `ID Card`, `Atoll`/`Select atoll`/`Atolls`, `Island`/`Select island`/`Islands`, `Address`, `Date of Birth`/`Date of birth`, `Account Number`/`Account no`, `Phone Number`/`Phone number`; `i accept` + `terms and conditions`, `i undertand` (sic) + `the privacy policy`; `Submit`; `Already have an account?` / `login`.
|
|
|
|
**auth-actions** (surfaced via forms/toasts) — `Please enter a phone number`, `Your account is on pending verification. Please wait for a response from admin or contact shihaam.` (hardcoded name), `Invalid form data`, `You must be at least 18 years old to register.`, `ID card already exists.`, `Phone number already exists.`, `User created successfully`.
|
|
|
|
**queries/authentication** — `OTP is required.`, `Your account has been successfully verified! You may login now.`, `Your account could not be verified. Please wait for you verification to be processed.` (sic).
|
|
|
|
## 2. Devices
|
|
|
|
**devices page** — `My Devices`; `Device Filter` / `Filter devices by name, MAC address, or vendor.`; `Device Name`/`Enter device name`, `MAC Address`/`Enter MAC address`, `Vendor`/`Enter vendor name`; table: `Device Name`, `Mac Address`, `Vendor`, `#`.
|
|
|
|
**device detail** — `Device active until {expiry_date}`, `ACTIVE`.
|
|
|
|
**user-devices page** — `User Devices`; filter `Device User`/`User name or id card`; `loading....`.
|
|
|
|
**device-card** — `Active until {expiry_date}`, `Device Inactive`, `Payment Pending`, `Blocked by admin` + `{reason}`.
|
|
|
|
**device-cart** — `Pay {count} device` / `Pay {count} devices`, `Cancel`.
|
|
|
|
**devices-table** — `No active devices` / `No devices.`; `Total {count} device(s).`.
|
|
|
|
**devices-to-pay** — `Devices to pay` / `Devices Paid`, `Please send the following amount to the payment address`, bank `Baraveli Dev` / `90101400028321000`, `Payment Verified`, `Processing payment...`, `Pay with wallet`, `I have paid`; rows: `Payment created`, `Total Devices`, `Duration`, `{count} Months`, `Total Due`.
|
|
|
|
**devices-for-payment** — `Set No of Months`, `Go to payment`.
|
|
|
|
**block-device-dialog** — `Unblock`/`Unblocking`, `Block`/`Blocking`/`Blocking...`, `Block 🚫` (title), `Please provide a reason for blocking this device`, `Reason for blocking`.
|
|
|
|
**how-to-get-mac** — `How do I find my MAC Address?` + description; per-device steps (iPhone/Redmi/Samsung/Windows/Other); support phone `9198026`.
|
|
|
|
**device-filter** — `Filter`, `Device Filters`, `Select your desired filters here`; placeholders `Device name ...`, `Device Mac address ...`, `Device vendor ...`; `Apply Filters`, `Clear Filters`, `Cancel`; chips `Device Name: {v}` etc., `Remove`.
|
|
|
|
**admin-devices-table** — `No devices.`; headers `Device Name`,`User`,`MAC Address`,`Vendor`,`#`; `Comment` (block reason); `Total {count} device(s).`.
|
|
|
|
**add-device-dialog** — `Add Device`, `New Device`, `To add a new device, enter the device name and mac address below. Click save when you are done.`, `Device Name`/`eg: iPhone X`, `Mac Address`/`Mac address of your device`, `Save`.
|
|
|
|
**queries/devices** — `Device name is required and must be at least 2 characters.`, `Validation failed.`, `Authentication required.`, `Device successfully added!`, `An unexpected error occurred.`, `Reason for blocking is required and must be at least 5 characters.`, `Reason is required and must be at least 5 characters.`, `Device blocked successfully!` / `Device unblocked successfully!`.
|
|
|
|
## 3. Payments / billing
|
|
|
|
**payments page** — `My Subscriptions`; `Payment` (`All`/`Paid`/`Unpaid`), `Payment Method` (`All`/`Transfer`/`Wallet`), `Number of months`; headers `Details`,`Duration`,`Status`,`Amount`.
|
|
|
|
**payment detail** — `Payment`; `Payment Pending` / `Payment Expired` / `Payment Cancelled`.
|
|
|
|
**user-payments page** — `User Payments`; filters `User`/`Enter user name`, `MIB Reference`/`Enter MIB Reference`, `Amount Range`, `Duration Range`, `Payment Status`, `Payment Method`; `loading....`.
|
|
|
|
**payments-table** — `No Payments.`; `View Details`, `Devices`, `Months`, `Expired`, `MVR`; `Total {n} payment(s).`.
|
|
|
|
**account-information** — `Account Information`, `Account Name`, `Account No`, `Account number copied!`, `Copy Account Number`.
|
|
|
|
**cancel-payment-button** — `Payment cancelled successfully!`, `Your payment of {amount} MVR has been cancelled.`, `Cancel Payment`.
|
|
|
|
**cancel-topup-button** — `Topup cancelled successfully!`, `Your topup of {amount} MVR has been cancelled.`, `Cancel Topup`.
|
|
|
|
**expiry-time-countdown** — `Time left: {t}`, `{label} has expired.`.
|
|
|
|
**user-payments-table** — `No user payments yet.`; headers `Devices paid`,`User`,`Amount`,`Duration`,`Payment Status`,`Payment Method`,`MIB Reference`,`Paid At`,`Action`; `MVR`, `Months`, `Details`; `Total {n} payment(s).`.
|
|
|
|
**actions/payment** — `Payment ID is required`, `Payment method is required`, `Payment completed successfully using wallet!`, `Payment verification successful!`, `Unable to verify payment. Please try again or contact support.`, `Topup ID is required`, `Topup payment verified successfully`, `An error occurred.`.
|
|
|
|
## 4. Wallet / topups
|
|
|
|
**wallet page** — `Transaction History`; `Type` (`All`/`Debit`/`Credit`), `Topup Amount`; headers `Description`,`Amount`,`Transaction Type`,`View Details`.
|
|
|
|
**top-ups page** — `My Topups`; `Status` (`All`/`Pending`/`Cancelled`/`Paid`), `Topup Expiry` (`Expired`/`Not Expired`), `Topup Amount`; headers `Details`,`Status`,`Amount`.
|
|
|
|
**topup detail** — `Topup`; `Payment Pending` / `Topup Expired` / `Topup Cancelled`.
|
|
|
|
**user-topups page** — `User Topups`; `Filter user topups by status, topup expiry, or amount.`; `loading....`.
|
|
|
|
**wallet** — `Wallet`, `Your wallet balance is {balance}`, `Set amount to top up`, `Go to payment`, `Cancel`, `Something went wrong.`.
|
|
|
|
**wallet-transactions-table** — `No transactions yet.`, `Total Debit`, `Total Credit`; headers `Description`,`Amount`,`Transaction Type`,`View Details`,`Created at`; `Total {n} transaction(s).`.
|
|
|
|
**topups-table** — `No topups.`; headers `Details`,`Status`,`Amount`; `View Details`; `Total {n} topup(s).`.
|
|
|
|
**topup-to-pay** — `Topup successful!`, `Your topup payment has been verified successfully using {sourceBank} bank transfer on {trxDate}.`, `Topup Payment Verification Failed`, `Please send the following amount to the payment address`, bank `Baraveli Dev` / `90101400028321000`, `Topup Payment Verified`, `I have paid`, `Processing payment...`; rows `Topup created`, `Payment received`, `MIB Reference`, `Total Due`.
|
|
|
|
**admin-topup-form** — `Add cash topup`, `New Manual Topup`, `To add a new manual topup, enter the amount below. Click save when you are done.`, `Topup Amount`, `Topup Description`, `Save`.
|
|
|
|
**admin-topup-table** — `No topups yet.`; headers `User`,`Status`,`Amount`,`Action`; `View Details`; `Total {n} topup(s).`.
|
|
|
|
## 5. Admin / user management
|
|
|
|
**users page** — `Users`; `User Filter` / `Filter users by id card, name, or house name and more.`; filters `User First Name`, `User Last Name`, `ID Card`, `House Name`, `Phone Number`, `User Status` (`All`/`Verified`/`Unverified`); `loading....`.
|
|
|
|
**user details** — `User Information`; `Update User`, `Update Agreement`, `View Agreement`, `Verified`; sections `Database Information`, `National Information`; fields `ID Card`,`Name`,`House Name`,`Island`,`Atoll`,`DOB`,`Phone Number`; `id photo` (alt).
|
|
|
|
**user update page** — `Verify user`.
|
|
|
|
**user agreement page** — `Upload user user agreement` (sic).
|
|
|
|
**user-table** — `No Users yet.`; headers `Name`,`ID Card`,`Atoll`,`Island`,`House Name`,`Status`,`Dob`,`Phone Number`,`Action`; `Verified`/`Unverified`, `Details`; `Total {n} user(s).`.
|
|
|
|
**user-update-form** — `Go Back`, `Update User Information`; labels `ID Card`,`First Name`,`Last Name`,`House Name`,`DOB`,`Phone Number`; `Update User`; toasts `Success` / `User updated successfully`, `Error in {field}: {error}`.
|
|
|
|
**user-agreement-form** — `Go Back`, `Upload User agreement`, `Agreement Document`, `Update Agreement`; toasts `Success` / `User agreement updated successfully`, `Error in {field}: {error}`.
|
|
|
|
**user-verify-dialog** — `Verify` / `Verified`, `Verify User`, `Are you sure you want to verify the following user?`, dynamic `Name/ID Card/Address/DOB/Phone Number`, `Verifying...`, `User Verified!`, `The following fields do not match`.
|
|
|
|
**user-reject-dialog** — `Reject`, `Are you sure?`, dynamic user lines, `Rejection details`, `User rejected successfully!`.
|
|
|
|
**actions/user-actions** — `User verification failed`, `An unexpected error occurred.`, `An error occurred while updating the user.`, `User updated successfully`, `An error occurred while updating the user agreement.`, `User agreement updated successfully`, `Amount is required`, `An error occurred while topping up the user.`, `User topped up successfully`.
|
|
|
|
## 6. Profile
|
|
|
|
**profile page** — `Profile`, `Profile Status`; fields `Full Name`,`ID Card`,`Island`,`Date of Birth`,`Address`,`Phone Number`,`Account Number`; status `Verified`/`Not Verified`/`Unknown`.
|
|
|
|
## 7. Layout / navigation / shared
|
|
|
|
**root metadata** — `SAR Link Portal` (title), `Sarlink Portal` (description).
|
|
|
|
**dashboard error** — `Something went wrong!`, `Try again`.
|
|
|
|
**account-popover** — `{first} {last}`, `Logout`, `View Profile`.
|
|
|
|
**welcome-banner** — `Welcome, {firstName} {lastName}`.
|
|
|
|
**theme-toggle** — `Toggle theme`, `Light`, `Dark`, `System`.
|
|
|
|
**generic-filter** — `Filters`, `Select your desired filters here`, `Filter`, `Applying...`, `Apply Filters`, `Clear Filters`, `Cancel`, `Remove`.
|
|
|
|
**search** — `Search...`. **pagination** — `...`.
|
|
|
|
**client-error-message** — `You do not have permission to perform this action.`, `Please contact the administrator to give you permissions.`, support phone `919-8026`.
|
|
|
|
Generic fallbacks: `An unexpected error occurred.`, `An error occurred.`, `Something went wrong!` / `.`, `Please try again or contact support.`, `loading....`.
|
|
|
|
## 8. Price calculator
|
|
|
|
`Price Calculator`; labels `Initial Price`,`Number of Devices`,`Number of Days`,`Discount Percentage`,`Total`; `Price for {n} device(s) over {d} day(s): MVR {price}`, `Result`.
|
|
|
|
## 9. Agreements
|
|
|
|
**agreements page** — `Agreements`, `An error occurred while fetching agreements: {error}`, `No agreement found.`, `Print`.
|
|
|
|
**agreement-card** — `Sarlink User Agreement`, `User agreement for Sarlink services.`, `View Agreement`.
|
|
|
|
## 10. Parental control
|
|
|
|
`Parental Control`; `Device Filter` + name/MAC/vendor filters; table `Device Name`,`Mac Address`,`Vendor`,`#`.
|
|
|
|
## 11. Validation messages
|
|
|
|
**lib/schemas.ts** (`signUpFormSchema`) — `Name is required.`, `ID Card is required`, `Please enter a valid ID Card number.` (`^[A][0-9]{6}$`), `Atoll is required.`, `Island is required.`, `address is required.` (sic), `Date of birth is required.`, `Phone number is required.`, `Please enter a valid phone number` (`^[79][0-9]{2}[0-9]{4}$`), `You must accept the terms and conditions`, `You must accept the privacy policy`, `Account number is required.`, `Please enter a valid account number` (`^(7\d{12}|9\d{16})$`).
|
|
|
|
**auth-actions** — `Please enter a valid phone number` (`^[7|9][0-9]{2}-[0-9]{4}$` — hyphenated variant), `You must be at least 18 years old to register.`
|
|
|
|
**verify-otp-form** — `Your one-time password must be 6 characters.`
|
|
|
|
## 12. Hardcoded contacts / brand / bank
|
|
|
|
| String | Type | Location |
|
|
|---|---|---|
|
|
| `SAR Link Portal` / `Sarlink Portal` | brand | `app/layout.tsx` |
|
|
| `SAR Link by OmegaTech Solutions` | company | signup-form |
|
|
| `SAR Link` | brand | how-to-get-mac |
|
|
| `Sarlink User Agreement` | brand | agreement-card |
|
|
| `Baraveli Dev` | bank account name | devices-to-pay, topup-to-pay |
|
|
| `90101400028321000` | bank account number | devices-to-pay, topup-to-pay |
|
|
| `9198026` | support phone | how-to-get-mac |
|
|
| `919-8026` | support phone | client-error-message |
|
|
| `shihaam` | personal name (in pending-verification message) | auth-actions |
|
|
| `MVR` | currency | payments/topups/calculator |
|
|
|
|
## Cross-cutting notes (for i18n / port)
|
|
|
|
- **Pluralization** is inline `count === 1 ? "X." : "Xs."` everywhere — use ICU plurals.
|
|
- **Interpolation** via bare template literals — extract as named placeholders.
|
|
- **Two phone regexes**: `^[79][0-9]{2}[0-9]{4}$` (schemas) vs hyphenated `^[7|9][0-9]{2}-[0-9]{4}$` (auth-actions) — reconcile.
|
|
- **Duplicated label sets** (`Full Name`/`Name`/`First Name`, `DOB`/`Date of Birth`/`Dob`, `House Name`/`Address`) — inconsistent wording/casing for the same concept; unify into shared keys.
|
|
- **Source-text defects to fix during extraction:** `i undertand`, `Upload user user agreement`, `for you verification`, lowercase `address is required.`, and the hardcoded name `shihaam` in a user-facing message.
|
|
- **Server-owned copy:** many messages come from `actions/*` / `queries/*` or pass through backend `message`/`detail` — the i18n layer must cover both, and backend-originated strings can't be translated on the frontend.
|