diff --git a/apps/expo/.cache/.prettiercache b/apps/expo/.cache/.prettiercache index 4fbe789..c82e2fa 100644 --- a/apps/expo/.cache/.prettiercache +++ b/apps/expo/.cache/.prettiercache @@ -1 +1 @@ -[["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21"],{"key":"22","value":"23"},{"key":"24","value":"25"},{"key":"26","value":"27"},{"key":"28","value":"29"},{"key":"30","value":"31"},{"key":"32","value":"33"},{"key":"34","value":"35"},{"key":"36","value":"37"},{"key":"38","value":"39"},{"key":"40","value":"41"},{"key":"42","value":"43"},{"key":"44","value":"45"},{"key":"46","value":"47"},{"key":"48","value":"49"},{"key":"50","value":"51"},{"key":"52","value":"53"},{"key":"54","value":"55"},{"key":"56","value":"57"},{"key":"58","value":"59"},{"key":"60","value":"61"},{"key":"62","value":"63"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/package.json",{"size":2249,"mtime":1766222924000,"hash":"64","data":"65"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/index.ts",{"size":28,"mtime":1768155639384,"hash":"66","data":"67"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/metro.config.js",{"size":511,"mtime":1768155639442,"hash":"68","data":"69"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/src/app/index.tsx",{"size":5019,"mtime":1768155639734,"hash":"70","data":"71"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/turbo.json",{"size":163,"mtime":1766222924000,"hash":"72","data":"73"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/postcss.config.js",{"size":66,"mtime":1768155639501,"hash":"74","data":"75"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/eas.json",{"size":567,"mtime":1766222924000,"hash":"76","data":"77"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/.expo-shared/assets.json",{"size":155,"mtime":1766222924000,"hash":"78","data":"79"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/src/app/_layout.tsx",{"size":927,"mtime":1768155639581,"hash":"80","data":"81"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/nativewind-env.d.ts",{"size":246,"mtime":1766222924000,"hash":"82","data":"83"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/src/utils/auth.ts",{"size":398,"mtime":1768155639911,"hash":"84","data":"85"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/src/app/post/[id].tsx",{"size":757,"mtime":1768155639785,"hash":"86","data":"87"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/src/styles.css",{"size":90,"mtime":1768155639819,"hash":"88","data":"89"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/src/utils/session-store.ts",{"size":272,"mtime":1768155639965,"hash":"90","data":"91"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/assets/icon-dark.png",{"size":19633,"mtime":1766222924000,"hash":"92"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/eslint.config.mts",{"size":275,"mtime":1768155639360,"hash":"93","data":"94"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/src/utils/api.tsx",{"size":1326,"mtime":1768155639881,"hash":"95","data":"96"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/src/utils/base-url.ts",{"size":880,"mtime":1768155639943,"hash":"97","data":"98"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/app.config.ts",{"size":1333,"mtime":1768155639275,"hash":"99","data":"100"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/assets/icon-light.png",{"size":19133,"mtime":1766222924000,"hash":"101"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/tsconfig.json",{"size":387,"mtime":1766228480000,"hash":"102","data":"103"},"d8763702c14cdc382dcfb84f6f9a068f",{"hashOfOptions":"104"},"11cdbef6afa001cd39bc187041ca6865",{"hashOfOptions":"105"},"dbe97bcde588a81538bbcd6a9befdddd",{"hashOfOptions":"106"},"1c10eb388cf5dcbc87d2d63770a227f1",{"hashOfOptions":"107"},"c7d4dcf839dfeaa02e0407adfd5e47a6",{"hashOfOptions":"108"},"b7edffce093c4c84092cc93f3dc208ef",{"hashOfOptions":"109"},"a3c1487f8318513ae7c156acc857fde2",{"hashOfOptions":"110"},"0f7f54c7161b8403d3bc42d91f59cd91",{"hashOfOptions":"111"},"8e407b4b1b0c0bd9c862a00243344be3",{"hashOfOptions":"112"},"d4d589c153ac8b5e7bf0fb130a5b5a7d",{"hashOfOptions":"113"},"cecbed1604a530a7cc099fecddddd76c",{"hashOfOptions":"114"},"4fcefde979d34a7339f7a266d3ec931b",{"hashOfOptions":"115"},"52a1d72379b952dd802f47e1865bd0da",{"hashOfOptions":"116"},"1bc3e15a40c117eecc51294886ea9b38",{"hashOfOptions":"117"},"1e8ac0d261e95efb19d290ffcf70ce36","1c1710ce3de3ce02e8054cc3787c8579",{"hashOfOptions":"118"},"5ff899a601102659dcbd2900e415ce8b",{"hashOfOptions":"119"},"dd2007a211e323deabb3f7fa7d16313f",{"hashOfOptions":"120"},"4f49c6df7733f874fbe72b4e20b3092b",{"hashOfOptions":"121"},"863da15dbd856008b7c24077ca746d91","6937fb7370f1e17491df649888d6ecc9",{"hashOfOptions":"122"},"2742538293","3367041120","3963086909","3173464737","3850474653","3346849767","2045418596","3048291867","3525769784","4000169781","471581913","1427279653","2305419495","818733105","2587128410","1262173017","408469422","2836740315","2315460658"] \ No newline at end of file +[["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22"],{"key":"23","value":"24"},{"key":"25","value":"26"},{"key":"27","value":"28"},{"key":"29","value":"30"},{"key":"31","value":"32"},{"key":"33","value":"34"},{"key":"35","value":"36"},{"key":"37","value":"38"},{"key":"39","value":"40"},{"key":"41","value":"42"},{"key":"43","value":"44"},{"key":"45","value":"46"},{"key":"47","value":"48"},{"key":"49","value":"50"},{"key":"51","value":"52"},{"key":"53","value":"54"},{"key":"55","value":"56"},{"key":"57","value":"58"},{"key":"59","value":"60"},{"key":"61","value":"62"},{"key":"63","value":"64"},{"key":"65","value":"66"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/package.json",{"size":2249,"mtime":1766222924000,"hash":"67","data":"68"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/index.ts",{"size":28,"mtime":1768155639000,"hash":"69","data":"70"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/metro.config.js",{"size":511,"mtime":1768155639000,"hash":"71","data":"72"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/src/app/index.tsx",{"size":5019,"mtime":1768155639000,"hash":"73","data":"74"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/turbo.json",{"size":163,"mtime":1766222924000,"hash":"75","data":"76"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/postcss.config.js",{"size":66,"mtime":1768155639000,"hash":"77","data":"78"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/.cache/.prettiercache",{"size":4787,"mtime":1768171236840,"hash":"79"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/eas.json",{"size":567,"mtime":1766222924000,"hash":"80","data":"81"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/.expo-shared/assets.json",{"size":155,"mtime":1766222924000,"hash":"82","data":"83"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/src/app/_layout.tsx",{"size":927,"mtime":1768155639000,"hash":"84","data":"85"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/nativewind-env.d.ts",{"size":246,"mtime":1766222924000,"hash":"86","data":"87"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/src/utils/auth.ts",{"size":398,"mtime":1768155639000,"hash":"88","data":"89"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/src/app/post/[id].tsx",{"size":757,"mtime":1768155639000,"hash":"90","data":"91"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/src/styles.css",{"size":90,"mtime":1768155639000,"hash":"92","data":"93"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/src/utils/session-store.ts",{"size":272,"mtime":1768155639000,"hash":"94","data":"95"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/assets/icon-dark.png",{"size":19633,"mtime":1766222924000,"hash":"96"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/eslint.config.mts",{"size":275,"mtime":1768155639000,"hash":"97","data":"98"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/src/utils/api.tsx",{"size":1326,"mtime":1768155639000,"hash":"99","data":"100"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/src/utils/base-url.ts",{"size":880,"mtime":1768155639000,"hash":"101","data":"102"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/app.config.ts",{"size":1333,"mtime":1768155639000,"hash":"103","data":"104"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/assets/icon-light.png",{"size":19133,"mtime":1766222924000,"hash":"105"},"/home/gib/Documents/Code/convex-monorepo/apps/expo/tsconfig.json",{"size":387,"mtime":1766228480000,"hash":"106","data":"107"},"d8763702c14cdc382dcfb84f6f9a068f",{"hashOfOptions":"108"},"11cdbef6afa001cd39bc187041ca6865",{"hashOfOptions":"109"},"dbe97bcde588a81538bbcd6a9befdddd",{"hashOfOptions":"110"},"1c10eb388cf5dcbc87d2d63770a227f1",{"hashOfOptions":"111"},"c7d4dcf839dfeaa02e0407adfd5e47a6",{"hashOfOptions":"112"},"b7edffce093c4c84092cc93f3dc208ef",{"hashOfOptions":"113"},"75e4e9158c89e7a7bc04e94fd2366743","a3c1487f8318513ae7c156acc857fde2",{"hashOfOptions":"114"},"0f7f54c7161b8403d3bc42d91f59cd91",{"hashOfOptions":"115"},"8e407b4b1b0c0bd9c862a00243344be3",{"hashOfOptions":"116"},"d4d589c153ac8b5e7bf0fb130a5b5a7d",{"hashOfOptions":"117"},"cecbed1604a530a7cc099fecddddd76c",{"hashOfOptions":"118"},"4fcefde979d34a7339f7a266d3ec931b",{"hashOfOptions":"119"},"52a1d72379b952dd802f47e1865bd0da",{"hashOfOptions":"120"},"1bc3e15a40c117eecc51294886ea9b38",{"hashOfOptions":"121"},"1e8ac0d261e95efb19d290ffcf70ce36","1c1710ce3de3ce02e8054cc3787c8579",{"hashOfOptions":"122"},"5ff899a601102659dcbd2900e415ce8b",{"hashOfOptions":"123"},"dd2007a211e323deabb3f7fa7d16313f",{"hashOfOptions":"124"},"4f49c6df7733f874fbe72b4e20b3092b",{"hashOfOptions":"125"},"863da15dbd856008b7c24077ca746d91","6937fb7370f1e17491df649888d6ecc9",{"hashOfOptions":"126"},"2742538293","3367041120","3963086909","3173464737","3850474653","3346849767","2045418596","3048291867","3525769784","4000169781","471581913","1427279653","2305419495","818733105","2587128410","1262173017","408469422","2836740315","2315460658"] \ No newline at end of file diff --git a/apps/next/.cache/.prettiercache b/apps/next/.cache/.prettiercache index a0d928f..58e2df1 100644 --- a/apps/next/.cache/.prettiercache +++ b/apps/next/.cache/.prettiercache @@ -1 +1 @@ -[["1","2","3","4","5","6","7","8","9","10","11"],{"key":"12","value":"13"},{"key":"14","value":"15"},{"key":"16","value":"17"},{"key":"18","value":"19"},{"key":"20","value":"21"},{"key":"22","value":"23"},{"key":"24","value":"25"},{"key":"26","value":"27"},{"key":"28","value":"29"},{"key":"30","value":"31"},{"key":"32","value":"33"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/env.ts",{"size":1676,"mtime":1768155639474,"hash":"34","data":"35"},"/home/gib/Documents/Code/convex-monorepo/apps/next/postcss.config.js",{"size":63,"mtime":1766225879000,"hash":"36","data":"37"},"/home/gib/Documents/Code/convex-monorepo/apps/next/public/favicon.ico",{"size":103027,"mtime":1766225172000,"hash":"38"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/app/layout.tsx",{"size":1885,"mtime":1768155639311,"hash":"39","data":"40"},"/home/gib/Documents/Code/convex-monorepo/apps/next/public/t3-icon.svg",{"size":923,"mtime":1766225172000,"hash":"41"},"/home/gib/Documents/Code/convex-monorepo/apps/next/next.config.js",{"size":2062,"mtime":1768155639139,"hash":"42","data":"43"},"/home/gib/Documents/Code/convex-monorepo/apps/next/package.json",{"size":1506,"mtime":1768154671185,"hash":"44","data":"45"},"/home/gib/Documents/Code/convex-monorepo/apps/next/tsconfig.json",{"size":297,"mtime":1766225936000,"hash":"46","data":"47"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/app/styles.css",{"size":596,"mtime":1768155639429,"hash":"48","data":"49"},"/home/gib/Documents/Code/convex-monorepo/apps/next/eslint.config.ts",{"size":369,"mtime":1768155639048,"hash":"50","data":"51"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/app/page.tsx",{"size":1169,"mtime":1768155639357,"hash":"52","data":"53"},"08dcc17ca04632a7262728b699450d5d",{"hashOfOptions":"54"},"d9fa362e836306677416d4e30dfb1528",{"hashOfOptions":"55"},"36aa513994f9883f30ff408fe777cec6","f819b8d99aba405d3975e6e5d3adf796",{"hashOfOptions":"56"},"44418c5550aee51cfdf0a321ad70ae47","1f2ba5c5e807955994fd4dfca4c709be",{"hashOfOptions":"57"},"6dba01a7cb29904291cb3c9930fc1ac3",{"hashOfOptions":"58"},"785dd21512a5bdf43635be77f6a483ae",{"hashOfOptions":"59"},"48e377494d0046d38b923af54e109529",{"hashOfOptions":"60"},"a9eecac327a9c09dd26e82c515134edc",{"hashOfOptions":"61"},"3847ea1421b6ea4079a526d7e44c946d",{"hashOfOptions":"62"},"1049592143","533286024","3492548434","1155092478","4045122132","2138361299","3590205716","4261166930","1190248983"] \ No newline at end of file +[["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32"],{"key":"33","value":"34"},{"key":"35","value":"36"},{"key":"37","value":"38"},{"key":"39","value":"40"},{"key":"41","value":"42"},{"key":"43","value":"44"},{"key":"45","value":"46"},{"key":"47","value":"48"},{"key":"49","value":"50"},{"key":"51","value":"52"},{"key":"53","value":"54"},{"key":"55","value":"56"},{"key":"57","value":"58"},{"key":"59","value":"60"},{"key":"61","value":"62"},{"key":"63","value":"64"},{"key":"65","value":"66"},{"key":"67","value":"68"},{"key":"69","value":"70"},{"key":"71","value":"72"},{"key":"73","value":"74"},{"key":"75","value":"76"},{"key":"77","value":"78"},{"key":"79","value":"80"},{"key":"81","value":"82"},{"key":"83","value":"84"},{"key":"85","value":"86"},{"key":"87","value":"88"},{"key":"89","value":"90"},{"key":"91","value":"92"},{"key":"93","value":"94"},{"key":"95","value":"96"},"/home/gib/Documents/Code/convex-monorepo/apps/next/public/misc/auth/gibs_auth_wide_header.png",{"size":74049,"mtime":1768226576453,"hash":"97"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/app/(auth)/sign-in/page.tsx",{"size":16469,"mtime":1768239263791,"hash":"98","data":"99"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/app/(auth)/profile/layout.tsx",{"size":276,"mtime":1768236979857,"hash":"100","data":"101"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/app/(auth)/forgot-password/page.tsx",{"size":10607,"mtime":1768239263673,"hash":"102","data":"103"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/components/layout/auth/profile/avatar-upload.tsx",{"size":6845,"mtime":1768239263940,"hash":"104","data":"105"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/components/layout/auth/profile/header.tsx",{"size":775,"mtime":1768239263951,"hash":"106","data":"107"},"/home/gib/Documents/Code/convex-monorepo/apps/next/postcss.config.js",{"size":63,"mtime":1766225879000,"hash":"108","data":"109"},"/home/gib/Documents/Code/convex-monorepo/apps/next/public/favicon.ico",{"size":103027,"mtime":1766225172000,"hash":"110"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/app/layout.tsx",{"size":1711,"mtime":1768186401942,"hash":"111","data":"112"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/components/providers/ConvexClientProvider.tsx",{"size":462,"mtime":1768239264017,"hash":"113","data":"114"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/app/(auth)/sign-in/layout.tsx",{"size":274,"mtime":1768236849421,"hash":"115","data":"116"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/components/layout/auth/profile/user-info.tsx",{"size":4103,"mtime":1768239264007,"hash":"117","data":"118"},"/home/gib/Documents/Code/convex-monorepo/apps/next/public/t3-icon.svg",{"size":923,"mtime":1766225172000,"hash":"119"},"/home/gib/Documents/Code/convex-monorepo/apps/next/.cache/.prettiercache",{"size":2439,"mtime":1768171236840,"hash":"120"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/app/(auth)/forgot-password/layout.tsx",{"size":298,"mtime":1768236967188,"hash":"121","data":"122"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/components/layout/auth/profile/index.tsx",{"size":230,"mtime":1768238412936,"hash":"123","data":"124"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/components/layout/auth/profile/sign-out.tsx",{"size":613,"mtime":1768239263988,"hash":"125","data":"126"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/components/providers/index.tsx",{"size":63,"mtime":1768171856108,"hash":"127","data":"128"},"/home/gib/Documents/Code/convex-monorepo/apps/next/next.config.js",{"size":1898,"mtime":1768239263537,"hash":"129","data":"130"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/lib/metadata.ts",{"size":3088,"mtime":1768239264052,"hash":"131","data":"132"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/lib/middleware/ban-sus-ips.ts",{"size":4894,"mtime":1768226323845,"hash":"133","data":"134"},"/home/gib/Documents/Code/convex-monorepo/apps/next/package.json",{"size":1484,"mtime":1768173526007,"hash":"135","data":"136"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/middleware.ts",{"size":1124,"mtime":1768239264082,"hash":"137","data":"138"},"/home/gib/Documents/Code/convex-monorepo/apps/next/tsconfig.json",{"size":297,"mtime":1766225936000,"hash":"139","data":"140"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/app/(auth)/profile/page.tsx",{"size":797,"mtime":1768239263701,"hash":"141","data":"142"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/components/layout/auth/buttons/gibs-auth.tsx",{"size":1074,"mtime":1768239263891,"hash":"143","data":"144"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/app/styles.css",{"size":595,"mtime":1768186094852,"hash":"145","data":"146"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/components/layout/auth/buttons/index.tsx",{"size":52,"mtime":1768188510036,"hash":"147","data":"148"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/components/layout/auth/profile/reset-password.tsx",{"size":5632,"mtime":1768239263980,"hash":"149","data":"150"},"/home/gib/Documents/Code/convex-monorepo/apps/next/eslint.config.ts",{"size":369,"mtime":1768155639000,"hash":"151","data":"152"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/app/page.tsx",{"size":157,"mtime":1768239263848,"hash":"153","data":"154"},"/home/gib/Documents/Code/convex-monorepo/apps/next/src/env.js",{"size":1676,"mtime":1768155639000,"hash":"155","data":"156"},"e1c508db2444a6d09f568af18b7d3266","e677478209bdd53e6d0e6c9052f4562b",{"hashOfOptions":"157"},"f931981cf65d01e80e4daea7c602bd3e",{"hashOfOptions":"158"},"68d789a9dd7ad7d0d7729a3bf25fbe76",{"hashOfOptions":"159"},"700a9441d9f17d9ecb2fc6049f5444f3",{"hashOfOptions":"160"},"0f4c9b5ddbf4dae05f8f48c5c8380756",{"hashOfOptions":"161"},"d9fa362e836306677416d4e30dfb1528",{"hashOfOptions":"162"},"36aa513994f9883f30ff408fe777cec6","e13f033c82ca4bdf1d389f0a32f3917f",{"hashOfOptions":"163"},"a11baac0b3f4295a9a850cc059cffcdc",{"hashOfOptions":"164"},"693d4b19ca786d9ba8633745187e61f4",{"hashOfOptions":"165"},"b12d072a183d67bd42d05e6b77be6560",{"hashOfOptions":"166"},"44418c5550aee51cfdf0a321ad70ae47","457b7d922bf75f4774267e782ffcb372","9f05c3eace62672b5bc6d3335eba9fd0",{"hashOfOptions":"167"},"34dec2764b76a2881b36ee552b80f532",{"hashOfOptions":"168"},"98c5aeb5593c05017dea6103f0f044fb",{"hashOfOptions":"169"},"53c4570985ddffc2d83d6325d42bdc71",{"hashOfOptions":"170"},"613de2866c4439d2e5f7ffad956efed6",{"hashOfOptions":"171"},"4ab0f081908a12192395e4962de317c5",{"hashOfOptions":"172"},"5225199ffcca0402c852ffd8d19e2cee",{"hashOfOptions":"173"},"62343aef61431d56eca0bb4c64c6bd4f",{"hashOfOptions":"174"},"3769084c693c271b5fc40f2afb1cbfda",{"hashOfOptions":"175"},"785dd21512a5bdf43635be77f6a483ae",{"hashOfOptions":"176"},"ce1278c9a17a71f9cec2df813f4a524b",{"hashOfOptions":"177"},"6acaebe693767ab30f06c7558ab539a3",{"hashOfOptions":"178"},"dfff38be9a12d6e3dcf5756661542bdf",{"hashOfOptions":"179"},"f030cda6238b76472047d1372aa19ebc",{"hashOfOptions":"180"},"35e06367ed917379d4ae69bfed6cccac",{"hashOfOptions":"181"},"a9eecac327a9c09dd26e82c515134edc",{"hashOfOptions":"182"},"a51f2195dd4e62053342e5c9554a79f9",{"hashOfOptions":"183"},"08dcc17ca04632a7262728b699450d5d",{"hashOfOptions":"184"},"3338265647","4012463030","2232720991","920617102","3380867500","533286024","3492548434","2402919655","2517935466","1184381001","2517976986","517543883","3538032477","2914265382","1155092478","3844821799","3020989665","4045122132","4282643438","2138361299","3127638139","2273639987","3590205716","2476887939","3250799064","4261166930","1190248983","3396252889"] \ No newline at end of file diff --git a/apps/next/next.config.js b/apps/next/next.config.js index eab557c..b18f7d3 100644 --- a/apps/next/next.config.js +++ b/apps/next/next.config.js @@ -1,5 +1,6 @@ import { withSentryConfig } from '@sentry/nextjs'; import { withPlausibleProxy } from 'next-plausible'; + import { env } from './src/env.js'; /** @type {import("next").NextConfig} */ diff --git a/apps/next/src/app/(auth)/forgot-password/layout.tsx b/apps/next/src/app/(auth)/forgot-password/layout.tsx new file mode 100644 index 0000000..55cd61c --- /dev/null +++ b/apps/next/src/app/(auth)/forgot-password/layout.tsx @@ -0,0 +1,14 @@ +import type { Metadata } from 'next'; + +export const generateMetadata = (): Metadata => { + return { + title: 'Forgot Password', + }; +}; + +const ForgotPasswordLayout = ({ + children, +}: Readonly<{ children: React.ReactNode }>) => { + return <>{children}; +}; +export default ForgotPasswordLayout; diff --git a/apps/next/src/app/(auth)/forgot-password/page.tsx b/apps/next/src/app/(auth)/forgot-password/page.tsx new file mode 100644 index 0000000..1b5f32e --- /dev/null +++ b/apps/next/src/app/(auth)/forgot-password/page.tsx @@ -0,0 +1,300 @@ +'use client'; + +import { useState } from 'react'; +import { useRouter } from 'next/navigation'; +import { useAuthActions } from '@convex-dev/auth/react'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { useForm } from 'react-hook-form'; +import { toast } from 'sonner'; +import { z } from 'zod'; + +import { PASSWORD_MAX, PASSWORD_MIN } from '@gib/backend/types'; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, + Input, + InputOTP, + InputOTPGroup, + InputOTPSeparator, + InputOTPSlot, + SubmitButton, +} from '@gib/ui'; + +const forgotPasswordSchema = z.object({ + email: z.email({ message: 'Invalid email.' }), +}); + +const resetVerificationSchema = z + .object({ + code: z.string({ message: 'Invalid code.' }), + newPassword: z + .string() + .min(PASSWORD_MIN, { + message: `Password must be at least ${PASSWORD_MIN} characters.`, + }) + .max(PASSWORD_MAX, { + message: `Password must be no more than ${PASSWORD_MAX} characters.`, + }) + .regex(/^\S+$/, { + message: 'Password must not contain whitespace.', + }) + .regex(/[0-9]/, { + message: 'Password must contain at least one digit.', + }) + .regex(/[a-z]/, { + message: 'Password must contain at least one lowercase letter.', + }) + .regex(/[A-Z]/, { + message: 'Password must contain at least one uppercase letter.', + }) + .regex(/[\p{P}\p{S}]/u, { + message: 'Password must contain at least one symbol.', + }), + confirmPassword: z.string().min(PASSWORD_MIN, { + message: `Password must be at least ${PASSWORD_MIN} characters.`, + }), + }) + .refine((data) => data.newPassword === data.confirmPassword, { + message: 'Passwords do not match!', + path: ['confirmPassword'], + }); + +const ForgotPassword = () => { + const { signIn } = useAuthActions(); + const [flow, setFlow] = useState<'reset' | 'reset-verification'>('reset'); + const [email, setEmail] = useState(''); + const [loading, setLoading] = useState(false); + const [code, setCode] = useState(''); + const router = useRouter(); + + const forgotPasswordForm = useForm>({ + resolver: zodResolver(forgotPasswordSchema), + defaultValues: { email }, + }); + + const resetVerificationForm = useForm< + z.infer + >({ + resolver: zodResolver(resetVerificationSchema), + defaultValues: { code, newPassword: '', confirmPassword: '' }, + }); + + const handleForgotPasswordSubmit = async ( + values: z.infer, + ) => { + const formData = new FormData(); + formData.append('email', values.email); + formData.append('flow', flow); + setLoading(true); + try { + await signIn('password', formData).then(() => { + setEmail(values.email); + setFlow('reset-verification'); + }); + } catch (error) { + console.error('Error resetting password: ', error); + toast.error('Error resetting password.'); + } finally { + forgotPasswordForm.reset(); + setLoading(false); + } + }; + + const handleResetVerificationSubmit = async ( + values: z.infer, + ) => { + const formData = new FormData(); + formData.append('code', code); + formData.append('newPassword', values.newPassword); + formData.append('email', email); + formData.append('flow', flow); + setLoading(true); + try { + await signIn('password', formData); + router.push('/'); + } catch (error) { + console.error('Error resetting password: ', error); + toast.error('Error resetting password.'); + } finally { + resetVerificationForm.reset(); + setLoading(false); + } + }; + + return ( +
+ + + {flow === 'reset' ? ( + <> + + Forgot Password + + + Enter your email address and we will send you a link to reset + your password. + + + ) : ( + <> + + Reset Password + + + Enter your code and new password and we will reset your + password. + + + )} + + + + + {flow === 'reset' ? ( +
+ + ( + + Email + + + +
+ +
+
+ )} + /> + + Send Email + + + + ) : ( +
+ + ( + + Code + + setCode(value)} + > + + + + + + + + + + + + + Please enter the one-time password sent to your + phone. + +
+ +
+
+ )} + /> + ( + + + New Password + + + + +
+ +
+
+ )} + /> + ( + + + Confirm Passsword + + + + +
+ +
+
+ )} + /> + + Reset Password + + + + )} +
+
+
+
+
+ ); +}; +export default ForgotPassword; diff --git a/apps/next/src/app/(auth)/profile/layout.tsx b/apps/next/src/app/(auth)/profile/layout.tsx new file mode 100644 index 0000000..09e67d4 --- /dev/null +++ b/apps/next/src/app/(auth)/profile/layout.tsx @@ -0,0 +1,14 @@ +import type { Metadata } from 'next'; + +export const generateMetadata = (): Metadata => { + return { + title: 'Profile', + }; +}; + +const ProfileLayout = ({ + children, +}: Readonly<{ children: React.ReactNode }>) => { + return <>{children}; +}; +export default ProfileLayout; diff --git a/apps/next/src/app/(auth)/profile/page.tsx b/apps/next/src/app/(auth)/profile/page.tsx new file mode 100644 index 0000000..5d723eb --- /dev/null +++ b/apps/next/src/app/(auth)/profile/page.tsx @@ -0,0 +1,29 @@ +'use server'; + +import { + AvatarUpload, + ProfileHeader, + ResetPasswordForm, + SignOutForm, + UserInfoForm, +} from '@/components/layout/auth/profile'; +import { preloadQuery } from 'convex/nextjs'; + +import { api } from '@gib/backend/convex/_generated/api.js'; +import { Card, Separator } from '@gib/ui'; + +const Profile = async () => { + const preloadedUser = await preloadQuery(api.auth.getUser); + return ( + + + + + + + + + + ); +}; +export default Profile; diff --git a/apps/next/src/app/(auth)/sign-in/layout.tsx b/apps/next/src/app/(auth)/sign-in/layout.tsx new file mode 100644 index 0000000..e0e429a --- /dev/null +++ b/apps/next/src/app/(auth)/sign-in/layout.tsx @@ -0,0 +1,14 @@ +import type { Metadata } from 'next'; + +export const generateMetadata = (): Metadata => { + return { + title: 'Sign In', + }; +}; + +const SignInLayout = ({ + children, +}: Readonly<{ children: React.ReactNode }>) => { + return <>{children}; +}; +export default SignInLayout; diff --git a/apps/next/src/app/(auth)/sign-in/page.tsx b/apps/next/src/app/(auth)/sign-in/page.tsx index fce0a5e..5ce3722 100644 --- a/apps/next/src/app/(auth)/sign-in/page.tsx +++ b/apps/next/src/app/(auth)/sign-in/page.tsx @@ -1,12 +1,17 @@ 'use client'; -import { z } from 'zod'; -import { zodResolver } from '@hookform/resolvers/zod'; -import { useForm } from 'react-hook-form'; -import Link from 'next/link'; -import { useAuthActions } from '@convex-dev/auth/react'; -import { useRouter } from 'next/navigation'; -import { ConvexError } from 'convex/values'; + import { useState } from 'react'; +import Link from 'next/link'; +import { useRouter } from 'next/navigation'; +import { GibsAuthSignInButton } from '@/components/layout/auth/buttons'; +import { useAuthActions } from '@convex-dev/auth/react'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { ConvexError } from 'convex/values'; +import { useForm } from 'react-hook-form'; +import { toast } from 'sonner'; +import { z } from 'zod'; + +import { PASSWORD_MAX, PASSWORD_MIN, PASSWORD_REGEX } from '@gib/backend/types'; import { Card, CardContent, @@ -20,8 +25,8 @@ import { Input, InputOTP, InputOTPGroup, - InputOTPSlot, InputOTPSeparator, + InputOTPSlot, Separator, SubmitButton, Tabs, @@ -29,11 +34,6 @@ import { TabsList, TabsTrigger, } from '@gib/ui'; -import { toast } from 'sonner'; -import { - GibsAuthSignInButton, -} from '@/components/layout/auth/buttons'; -import { PASSWORD_MIN, PASSWORD_MAX, PASSWORD_REGEX } from '@gib/backend/types'; const signInFormSchema = z.object({ email: z.email({ @@ -179,24 +179,24 @@ const SignIn = () => { if (flow === 'email-verification') { return ( -
- +
+ -
-

Verify Your Email

-

We sent a code to {email}

+
+

Verify Your Email

+

We sent a code to {email}

( - Code + Code { Please enter the one-time password sent to your email. -
- +
+
)} /> Verify Email -
+
@@ -247,207 +247,204 @@ const SignIn = () => { } return ( -
- +
+ setFlow(value as 'signIn' | 'signUp')} - className='items-center' + className="items-center" > - + Sign In Sign Up - - + +
( - Email + Email -
- +
+
)} /> ( -
- Password - +
+ Password + Forgot Password?
-
- +
+
)} /> Sign In -
-
- - or - +
+
+ + or +
-
+
- - + +
( - Name + Name -
- +
+
)} /> ( - Email + Email -
- +
+
)} /> ( - Password + Password -
- +
+
)} /> ( - + Confirm Passsword -
- +
+
)} /> Sign Up -
-
- - or - +
+
+ + or +
-
- +
+
diff --git a/apps/next/src/app/page.tsx b/apps/next/src/app/page.tsx index c1aacb6..a9facd1 100644 --- a/apps/next/src/app/page.tsx +++ b/apps/next/src/app/page.tsx @@ -1,10 +1,12 @@ -'use client'; +'use server'; -const Home = () => { +const Home = async () => { return ( -
+
Hello! -
+ ); }; diff --git a/apps/next/src/components/layout/auth/buttons/gibs-auth.tsx b/apps/next/src/components/layout/auth/buttons/gibs-auth.tsx index 590cdb6..e55d006 100644 --- a/apps/next/src/components/layout/auth/buttons/gibs-auth.tsx +++ b/apps/next/src/components/layout/auth/buttons/gibs-auth.tsx @@ -1,9 +1,10 @@ +import type { VariantProps } from 'class-variance-authority'; +import type { ComponentProps } from 'react'; import Image from 'next/image'; import { useAuthActions } from '@convex-dev/auth/react'; + import type { buttonVariants } from '@gib/ui'; import { Button } from '@gib/ui'; -import type { ComponentProps } from 'react'; -import type { VariantProps } from 'class-variance-authority'; interface Props { buttonProps?: Omit, 'onClick'> & @@ -11,7 +12,7 @@ interface Props { asChild?: boolean; }; type?: 'signIn' | 'signUp'; -}; +} export const GibsAuthSignInButton = ({ buttonProps, @@ -20,22 +21,16 @@ export const GibsAuthSignInButton = ({ const { signIn } = useAuthActions(); return ( +
+ +
+ )} + + {/* Cropped preview + actions */} + {croppedImage && ( +
+ + + +
+ + +
+
+ )} + + {/* Uploading indicator */} + {isUploading && !croppedImage && ( +
+ + Uploading... +
+ )} +
+ + ); +}; diff --git a/apps/next/src/components/layout/auth/profile/header.tsx b/apps/next/src/components/layout/auth/profile/header.tsx new file mode 100644 index 0000000..656900a --- /dev/null +++ b/apps/next/src/components/layout/auth/profile/header.tsx @@ -0,0 +1,27 @@ +'use client'; + +import type { Preloaded } from 'convex/react'; +import { usePreloadedQuery } from 'convex/react'; + +import type { api } from '@gib/backend/convex/_generated/api.js'; +import { CardDescription, CardHeader, CardTitle } from '@gib/ui'; + +interface ProfileCardProps { + preloadedUser: Preloaded; +} + +const ProfileHeader = ({ preloadedUser }: ProfileCardProps) => { + const user = usePreloadedQuery(preloadedUser); + return ( + + + {user?.name ?? user?.email ?? 'Your Profile'} + + + Manage your personal information & how it appears to others. + + + ); +}; + +export { ProfileHeader }; diff --git a/apps/next/src/components/layout/auth/profile/index.tsx b/apps/next/src/components/layout/auth/profile/index.tsx new file mode 100644 index 0000000..0384bcb --- /dev/null +++ b/apps/next/src/components/layout/auth/profile/index.tsx @@ -0,0 +1,5 @@ +export { AvatarUpload } from './avatar-upload'; +export { ProfileHeader } from './header'; +export { ResetPasswordForm } from './reset-password'; +export { SignOutForm } from './sign-out'; +export { UserInfoForm } from './user-info'; diff --git a/apps/next/src/components/layout/auth/profile/reset-password.tsx b/apps/next/src/components/layout/auth/profile/reset-password.tsx new file mode 100644 index 0000000..cb86a35 --- /dev/null +++ b/apps/next/src/components/layout/auth/profile/reset-password.tsx @@ -0,0 +1,189 @@ +'use client'; + +import type { Preloaded } from 'convex/react'; +import { useState } from 'react'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { useAction, usePreloadedQuery } from 'convex/react'; +import { useForm } from 'react-hook-form'; +import { toast } from 'sonner'; +import { z } from 'zod'; + +import { api } from '@gib/backend/convex/_generated/api.js'; +import { PASSWORD_MAX, PASSWORD_MIN, PASSWORD_REGEX } from '@gib/backend/types'; +import { + CardContent, + CardDescription, + CardHeader, + CardTitle, + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, + Input, + Separator, + SubmitButton, +} from '@gib/ui'; + +const formSchema = z + .object({ + currentPassword: z.string().regex(PASSWORD_REGEX, { + message: 'Incorrect current password. Does not meet requirements.', + }), + newPassword: z + .string() + .min(PASSWORD_MIN, { + message: 'New password must be at least 8 characters.', + }) + .max(PASSWORD_MAX, { + message: 'New password must be less than 100 characters.', + }) + .regex(/^\S+$/, { + message: 'Password must not contain whitespace.', + }) + .regex(/[0-9]/, { + message: 'Password must contain at least one digit.', + }) + .regex(/[a-z]/, { + message: 'Password must contain at least one lowercase letter.', + }) + .regex(/[A-Z]/, { + message: 'Password must contain at least one uppercase letter.', + }) + .regex(/[\p{P}\p{S}]/u, { + message: 'Password must contain at least one symbol.', + }), + confirmPassword: z.string(), + }) + .refine((data) => data.currentPassword !== data.newPassword, { + message: 'New password must be different from current password.', + path: ['newPassword'], + }) + .refine((data) => data.newPassword === data.confirmPassword, { + message: 'Passwords do not match.', + path: ['confirmPassword'], + }); + +type ResetFormProps = { + preloadedUser: Preloaded; +}; + +export const ResetPasswordForm = ({ preloadedUser }: ResetFormProps) => { + const user = usePreloadedQuery(preloadedUser); + const [loading, setLoading] = useState(false); + + const changePassword = useAction(api.auth.updateUserPassword); + + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + currentPassword: '', + newPassword: '', + confirmPassword: '', + }, + }); + + const handleSubmit = async (values: z.infer) => { + setLoading(true); + try { + const result = await changePassword({ + currentPassword: values.currentPassword, + newPassword: values.newPassword, + }); + if (result.success) { + form.reset(); + toast.success('Password updated successfully.'); + } + } catch (error) { + console.error('Error updating password:', error); + toast.error('Error updating password.'); + } finally { + setLoading(false); + } + }; + // TO DO: Make a function to get provider type from user. + return ( + //user.provider !== 'password' + !user?.email + ) ? ( +
+ ) : ( + <> + + + Change Password + + Update your password to keep your account secure + + + +
+ + ( + + Current Password + + + + + Enter your current password. + + + + )} + /> + ( + + New Password + + + + + Enter your new password. Must be at least 8 characters. + + + + )} + /> + ( + + Confirm Password + + + + + Please re-enter your new password to confirm. + + + + )} + /> +
+ + Update Password + +
+ + +
+ + ); +}; diff --git a/apps/next/src/components/layout/auth/profile/sign-out.tsx b/apps/next/src/components/layout/auth/profile/sign-out.tsx new file mode 100644 index 0000000..1047fcd --- /dev/null +++ b/apps/next/src/components/layout/auth/profile/sign-out.tsx @@ -0,0 +1,22 @@ +'use client'; + +import { useRouter } from 'next/navigation'; +import { useAuthActions } from '@convex-dev/auth/react'; + +import { SubmitButton } from '@gib/ui'; + +export const SignOutForm = () => { + const { signOut } = useAuthActions(); + const router = useRouter(); + + return ( +
+ void signOut().then(() => router.push('/sign-in'))} + > + Sign Out + +
+ ); +}; diff --git a/apps/next/src/components/layout/auth/profile/user-info.tsx b/apps/next/src/components/layout/auth/profile/user-info.tsx new file mode 100644 index 0000000..5ff579e --- /dev/null +++ b/apps/next/src/components/layout/auth/profile/user-info.tsx @@ -0,0 +1,154 @@ +'use client'; + +import type { Preloaded } from 'convex/react'; +import { useMemo, useState } from 'react'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { useMutation, usePreloadedQuery } from 'convex/react'; +import { useForm } from 'react-hook-form'; +import { toast } from 'sonner'; +import { z } from 'zod'; + +import { api } from '@gib/backend/convex/_generated/api.js'; +import { + CardContent, + CardDescription, + CardHeader, + CardTitle, + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, + Input, + SubmitButton, +} from '@gib/ui'; + +const formSchema = z.object({ + name: z + .string() + .trim() + .min(5, { + message: 'Full name is required & must be at least 5 characters.', + }) + .max(50, { + message: 'Full name must be less than 50 characters.', + }), + email: z.email({ + message: 'Please enter a valid email address.', + }), +}); + +type UserInfoFormProps = { + preloadedUser: Preloaded; +}; + +export const UserInfoForm = ({ preloadedUser }: UserInfoFormProps) => { + const user = usePreloadedQuery(preloadedUser); + const [loading, setLoading] = useState(false); + + const updateUser = useMutation(api.auth.updateUser); + + const initialValues = useMemo>( + () => ({ + name: user?.name ?? '', + email: user?.email ?? '', + }), + [user?.name, user?.email], + ); + + const form = useForm>({ + resolver: zodResolver(formSchema), + values: initialValues, + }); + + const handleSubmit = async (values: z.infer) => { + const name = values.name.trim(); + const email = values.email.trim().toLowerCase(); + const patch: Partial<{ + name: string; + email: string; + lunchTime: string; + automaticLunch: boolean; + }> = {}; + if (name !== (user.name ?? '')) patch.name = name; + if (email !== (user.email ?? '')) patch.email = email; + if (Object.keys(patch).length === 0) return; + setLoading(true); + try { + await updateUser(patch); + form.reset(patch); + toast.success('Profile updated successfully.'); + } catch (error) { + console.error(error); + toast.error('Error updating profile.'); + } finally { + setLoading(false); + } + }; + + return ( + <> + + Account Information + Update your account information here. + + +
+ + ( + + Full Name + + + + Your public display name. + + + )} + /> + + ( + + Email + + + + + Your email address associated with your account. + + + + )} + /> +
+ + Save Changes + +
+ + +
+ + ); +}; diff --git a/apps/next/src/components/providers/ConvexClientProvider.tsx b/apps/next/src/components/providers/ConvexClientProvider.tsx index 0b9c22f..8fbe367 100644 --- a/apps/next/src/components/providers/ConvexClientProvider.tsx +++ b/apps/next/src/components/providers/ConvexClientProvider.tsx @@ -1,9 +1,9 @@ -"use client"; +'use client'; -import { ConvexAuthNextjsProvider } from "@convex-dev/auth/nextjs"; -import { ConvexReactClient } from "convex/react"; -import type { ReactNode } from "react"; +import type { ReactNode } from 'react'; import { env } from '@/env'; +import { ConvexAuthNextjsProvider } from '@convex-dev/auth/nextjs'; +import { ConvexReactClient } from 'convex/react'; const convex = new ConvexReactClient(env.NEXT_PUBLIC_CONVEX_URL); diff --git a/apps/next/src/lib/metadata.ts b/apps/next/src/lib/metadata.ts index 955a984..c940a41 100644 --- a/apps/next/src/lib/metadata.ts +++ b/apps/next/src/lib/metadata.ts @@ -43,65 +43,65 @@ export const generateMetadata = (): Metadata => { media: '(prefers-color-scheme: dark)', }, //{ - //url: '/appicon/icon.png', - //type: 'image/png', - //sizes: '192x192', + //url: '/appicon/icon.png', + //type: 'image/png', + //sizes: '192x192', //}, //{ - //url: '/appicon/icon.png', - //type: 'image/png', - //sizes: '192x192', - //media: '(prefers-color-scheme: dark)', + //url: '/appicon/icon.png', + //type: 'image/png', + //sizes: '192x192', + //media: '(prefers-color-scheme: dark)', //}, ], //shortcut: [ - //{ - //url: '/appicon/icon.png', - //type: 'image/png', - //sizes: '192x192', - //}, - //{ - //url: '/appicon/icon.png', - //type: 'image/png', - //sizes: '192x192', - //media: '(prefers-color-scheme: dark)', - //}, + //{ + //url: '/appicon/icon.png', + //type: 'image/png', + //sizes: '192x192', + //}, + //{ + //url: '/appicon/icon.png', + //type: 'image/png', + //sizes: '192x192', + //media: '(prefers-color-scheme: dark)', + //}, //], //apple: [ - //{ - //url: 'appicon/icon.png', - //type: 'image/png', - //sizes: '192x192', - //}, - //{ - //url: 'appicon/icon.png', - //type: 'image/png', - //sizes: '192x192', - //media: '(prefers-color-scheme: dark)', - //}, + //{ + //url: 'appicon/icon.png', + //type: 'image/png', + //sizes: '192x192', + //}, + //{ + //url: 'appicon/icon.png', + //type: 'image/png', + //sizes: '192x192', + //media: '(prefers-color-scheme: dark)', + //}, //], //other: [ - //{ - //rel: 'apple-touch-icon-precomposed', - //url: '/appicon/icon-precomposed.png', - //type: 'image/png', - //sizes: '180x180', - //}, + //{ + //rel: 'apple-touch-icon-precomposed', + //url: '/appicon/icon-precomposed.png', + //type: 'image/png', + //sizes: '180x180', + //}, //], }, other: { ...Sentry.getTraceData(), }, //appleWebApp: { - //title: 'Convex Monorepo', - //statusBarStyle: 'black-translucent', - //startupImage: [ - //'/icons/apple/splash-768x1004.png', - //{ - //url: '/icons/apple/splash-1536x2008.png', - //media: '(device-width: 768px) and (device-height: 1024px)', - //}, - //], + //title: 'Convex Monorepo', + //statusBarStyle: 'black-translucent', + //startupImage: [ + //'/icons/apple/splash-768x1004.png', + //{ + //url: '/icons/apple/splash-1536x2008.png', + //media: '(device-width: 768px) and (device-height: 1024px)', + //}, + //], //}, verification: { google: 'google', diff --git a/apps/next/src/middleware.ts b/apps/next/src/middleware.ts index a44a019..084d60f 100644 --- a/apps/next/src/middleware.ts +++ b/apps/next/src/middleware.ts @@ -1,9 +1,9 @@ +import { banSuspiciousIPs } from '@/lib/middleware/ban-sus-ips'; import { convexAuthNextjsMiddleware, createRouteMatcher, nextjsMiddlewareRedirect, } from '@convex-dev/auth/nextjs/server'; -import { banSuspiciousIPs } from '@/lib/middleware/ban-sus-ips'; const isSignInPage = createRouteMatcher(['/sign-in']); const isProtectedRoute = createRouteMatcher(['/', '/profile']); diff --git a/packages/backend/.cache/.prettiercache b/packages/backend/.cache/.prettiercache index afc6e63..5bb3d39 100644 --- a/packages/backend/.cache/.prettiercache +++ b/packages/backend/.cache/.prettiercache @@ -1 +1 @@ -[["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15"],{"key":"16","value":"17"},{"key":"18","value":"19"},{"key":"20","value":"21"},{"key":"22","value":"23"},{"key":"24","value":"25"},{"key":"26","value":"27"},{"key":"28","value":"29"},{"key":"30","value":"31"},{"key":"32","value":"33"},{"key":"34","value":"35"},{"key":"36","value":"37"},{"key":"38","value":"39"},{"key":"40","value":"41"},{"key":"42","value":"43"},{"key":"44","value":"45"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/.cache/.prettiercache",{"size":3699,"mtime":1766222924000,"hash":"46"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/_generated/dataModel.d.ts",{"size":1726,"mtime":1768155639236,"hash":"47","data":"48"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/.gitignore",{"size":16,"mtime":1766222924000,"hash":"49"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/utils.ts",{"size":635,"mtime":1768155639993,"hash":"50","data":"51"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/tsconfig.json",{"size":732,"mtime":1766222924000,"hash":"52","data":"53"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/package.json",{"size":1120,"mtime":1766223702000,"hash":"54","data":"55"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/_generated/server.js",{"size":3453,"mtime":1768155639358,"hash":"56","data":"57"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/auth.config.js",{"size":128,"mtime":1768155639410,"hash":"58","data":"59"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/notes.ts",{"size":1632,"mtime":1768155639618,"hash":"60","data":"61"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/_generated/server.d.ts",{"size":5540,"mtime":1768155639312,"hash":"62","data":"63"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/_generated/api.d.ts",{"size":845,"mtime":1768155639122,"hash":"64","data":"65"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/_generated/api.js",{"size":414,"mtime":1768155639185,"hash":"66","data":"67"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/README.md",{"size":2525,"mtime":1768155639908,"hash":"68","data":"69"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/openai.ts",{"size":2036,"mtime":1768155639718,"hash":"70","data":"71"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/schema.ts",{"size":267,"mtime":1768155639933,"hash":"72","data":"73"},"bf09c6d61dd6a010bca24cb05271176d","ce3275ccdd28673d7e9280b33792057c",{"hashOfOptions":"74"},"175b1a771387d8b7e26145c3d04e0475","6a3198db454396c63e99ee08065726bd",{"hashOfOptions":"75"},"cfa98923457caed911ec68b626ef4234",{"hashOfOptions":"76"},"355d413e63d71e7e2107534f0d82fa31",{"hashOfOptions":"77"},"a8efc7f01f2b2dcb19115187a6f5f935",{"hashOfOptions":"78"},"449225bb5e883c1319e2ade335cdf0ad",{"hashOfOptions":"79"},"4b3c533672165e2af8d66b7149f85e1b",{"hashOfOptions":"80"},"896efcfb7466854312acff830348fec5",{"hashOfOptions":"81"},"8effb22a4ee737ecaeb923db430289f9",{"hashOfOptions":"82"},"0f5f819cfc410629d8ba1209956a037c",{"hashOfOptions":"83"},"f5aa8269478f140adb4ccf0470dd1244",{"hashOfOptions":"84"},"e06978cd8943c0adfa4d2a855c8f3627",{"hashOfOptions":"85"},"0d3d6e28d2429a34e666323218320d74",{"hashOfOptions":"86"},"1690245769","3139400620","2702670119","1723032970","1018051749","1593187711","1215337372","3786452325","2623319630","3362284046","3941219177","30277581","3515117182"] \ No newline at end of file +[["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23"],{"key":"24","value":"25"},{"key":"26","value":"27"},{"key":"28","value":"29"},{"key":"30","value":"31"},{"key":"32","value":"33"},{"key":"34","value":"35"},{"key":"36","value":"37"},{"key":"38","value":"39"},{"key":"40","value":"41"},{"key":"42","value":"43"},{"key":"44","value":"45"},{"key":"46","value":"47"},{"key":"48","value":"49"},{"key":"50","value":"51"},{"key":"52","value":"53"},{"key":"54","value":"55"},{"key":"56","value":"57"},{"key":"58","value":"59"},{"key":"60","value":"61"},{"key":"62","value":"63"},{"key":"64","value":"65"},{"key":"66","value":"67"},{"key":"68","value":"69"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/.cache/.prettiercache",{"size":3533,"mtime":1768171236843,"hash":"70"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/crons.ts",{"size":528,"mtime":1768239263662,"hash":"71","data":"72"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/auth.ts",{"size":3630,"mtime":1768239263654,"hash":"73","data":"74"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/custom/auth/providers/password.ts",{"size":900,"mtime":1768239263701,"hash":"75","data":"76"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/_generated/dataModel.d.ts",{"size":1726,"mtime":1768239263554,"hash":"77","data":"78"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/.gitignore",{"size":16,"mtime":1766222924000,"hash":"79"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/utils.ts",{"size":635,"mtime":1768155639000,"hash":"80","data":"81"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/auth.config.ts",{"size":127,"mtime":1768156477000,"hash":"82","data":"83"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/tsconfig.json",{"size":732,"mtime":1766222924000,"hash":"84","data":"85"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/package.json",{"size":1300,"mtime":1768239263823,"hash":"86","data":"87"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/custom/auth/providers/usesend.ts",{"size":3115,"mtime":1768164053000,"hash":"88","data":"89"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/_generated/server.js",{"size":3474,"mtime":1768239263584,"hash":"90","data":"91"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/_generated/server.d.ts",{"size":5695,"mtime":1768239263572,"hash":"92","data":"93"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/types/auth.ts",{"size":174,"mtime":1768188156942,"hash":"94","data":"95"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/files.ts",{"size":582,"mtime":1768239263763,"hash":"96","data":"97"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/scripts/generateKeys.mjs",{"size":520,"mtime":1768239263846,"hash":"98","data":"99"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/_generated/api.d.ts",{"size":1521,"mtime":1768239263527,"hash":"100","data":"101"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/types/index.ts",{"size":69,"mtime":1768239263861,"hash":"102","data":"103"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/_generated/api.js",{"size":480,"mtime":1768239263542,"hash":"104","data":"105"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/README.md",{"size":2525,"mtime":1768155639000,"hash":"106","data":"107"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/http.ts",{"size":153,"mtime":1768157491000,"hash":"108","data":"109"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/schema.ts",{"size":1197,"mtime":1768239263796,"hash":"110","data":"111"},"/home/gib/Documents/Code/convex-monorepo/packages/backend/convex/custom/auth/index.ts",{"size":142,"mtime":1768157708000,"hash":"112","data":"113"},"e6b51ffddcfeaaeaaf7d1a0453024eff","0d76c3867783aec5435b0c716f1bfc65",{"hashOfOptions":"114"},"bd827d1529ceec8f4804864db994747b",{"hashOfOptions":"115"},"55bcf7d546da727edf2c1b7e52db6c7f",{"hashOfOptions":"116"},"ce3275ccdd28673d7e9280b33792057c",{"hashOfOptions":"117"},"175b1a771387d8b7e26145c3d04e0475","6a3198db454396c63e99ee08065726bd",{"hashOfOptions":"118"},"2d4f4ccfc784af9d668d8c64726c2f6b",{"hashOfOptions":"119"},"cfa98923457caed911ec68b626ef4234",{"hashOfOptions":"120"},"5d96f2526115241c4a37250b0f45ac4d",{"hashOfOptions":"121"},"14f5e2d18e21f65282ac744b382f2d5f",{"hashOfOptions":"122"},"f42d53bd1ba24bfee1407d2098f3b9ff",{"hashOfOptions":"123"},"6719b019702fc173de16b1bdc8e8ed47",{"hashOfOptions":"124"},"f0f9ef72dc6fef350f3521d3fd8adfc7",{"hashOfOptions":"125"},"5ff3856f1a61b946df899f7c9880b72a",{"hashOfOptions":"126"},"ccf5b9105ad4ff66fce0a7133fa3db4b",{"hashOfOptions":"127"},"7c522302bfb45e9cf5f1c271b48fa247",{"hashOfOptions":"128"},"57577de5aadfa618e91739aea3630342",{"hashOfOptions":"129"},"9d0d3b8d30fb1a1207df0584bf0f4c2e",{"hashOfOptions":"130"},"f5aa8269478f140adb4ccf0470dd1244",{"hashOfOptions":"131"},"4bbb95a66a1e615c30ea7c5098a4a609",{"hashOfOptions":"132"},"7e6dcc47831030bfaa3e235d2226cec6",{"hashOfOptions":"133"},"8776a23ed6f2ab3681e4ba5b4bcf3d74",{"hashOfOptions":"134"},"955486392","3358731095","808562286","1690245769","3139400620","3541494261","2702670119","1723032970","892475236","1018051749","3786452325","2118532951","4112784038","4222954450","2623319630","3379800363","3362284046","3941219177","2759234967","3515117182","71183348"] \ No newline at end of file diff --git a/packages/backend/convex/_generated/api.d.ts b/packages/backend/convex/_generated/api.d.ts index 6440f2c..3fdb8a6 100644 --- a/packages/backend/convex/_generated/api.d.ts +++ b/packages/backend/convex/_generated/api.d.ts @@ -9,9 +9,11 @@ */ import type * as auth from "../auth.js"; +import type * as crons from "../crons.js"; import type * as custom_auth_index from "../custom/auth/index.js"; import type * as custom_auth_providers_password from "../custom/auth/providers/password.js"; import type * as custom_auth_providers_usesend from "../custom/auth/providers/usesend.js"; +import type * as files from "../files.js"; import type * as http from "../http.js"; import type * as utils from "../utils.js"; @@ -31,9 +33,11 @@ import type { */ declare const fullApi: ApiFromModules<{ auth: typeof auth; + crons: typeof crons; "custom/auth/index": typeof custom_auth_index; "custom/auth/providers/password": typeof custom_auth_providers_password; "custom/auth/providers/usesend": typeof custom_auth_providers_usesend; + files: typeof files; http: typeof http; utils: typeof utils; }>; diff --git a/packages/backend/convex/auth.ts b/packages/backend/convex/auth.ts index 383bfd2..305b6ea 100644 --- a/packages/backend/convex/auth.ts +++ b/packages/backend/convex/auth.ts @@ -14,10 +14,7 @@ import { action, mutation, query } from './_generated/server'; import { Password, validatePassword } from './custom/auth'; export const { auth, signIn, signOut, store, isAuthenticated } = convexAuth({ - providers: [ - Authentik({ allowDangerousEmailAccountLinking: true }), - Password, - ], + providers: [Authentik({ allowDangerousEmailAccountLinking: true }), Password], }); const getUserById = async ( @@ -39,9 +36,8 @@ const isSignedIn = async (ctx: QueryCtx): Promise | null> => { export const getUser = query({ args: { userId: v.optional(v.id('users')) }, handler: async (ctx, args) => { - const user = await isSignedIn(ctx); - const userId = args.userId ?? user?._id; - if (!userId) throw new ConvexError('Not authenticated or no ID provided.'); + const userId = args.userId ?? (await getAuthUserId(ctx)); + if (!userId) return null; return getUserById(ctx, userId); }, }); diff --git a/packages/backend/convex/crons.ts b/packages/backend/convex/crons.ts new file mode 100644 index 0000000..aa32159 --- /dev/null +++ b/packages/backend/convex/crons.ts @@ -0,0 +1,23 @@ +import { cronJobs } from 'convex/server'; + +import { api } from './_generated/api'; + +// Cron order: Minute Hour DayOfMonth Month DayOfWeek +const crons = cronJobs(); +/* Example cron jobs +crons.cron( + // Run at 7:00 AM CST / 8:00 AM CDT + // Only on weekdays + 'Schedule Automatic Lunches', + '0 13 * * 1-5', + api.statuses.automaticLunch, +); +crons.cron( + // Run at 4:00 PM CST / 5:00 PM CDT + // Only on weekdays + 'End of shift (weekdays 5pm CT)', + '0 22 * * 1-5', + api.statuses.endOfShiftUpdate, +); +*/ +export default crons; diff --git a/packages/backend/convex/custom/auth/providers/password.ts b/packages/backend/convex/custom/auth/providers/password.ts index 5123041..7ef8ed2 100644 --- a/packages/backend/convex/custom/auth/providers/password.ts +++ b/packages/backend/convex/custom/auth/providers/password.ts @@ -1,5 +1,6 @@ import { Password as DefaultPassword } from '@convex-dev/auth/providers/Password'; import { ConvexError } from 'convex/values'; + import { UseSendOTP, UseSendOTPPasswordReset } from '..'; import { DataModel } from '../../../_generated/dataModel'; diff --git a/packages/backend/convex/files.ts b/packages/backend/convex/files.ts new file mode 100644 index 0000000..3151f0e --- /dev/null +++ b/packages/backend/convex/files.ts @@ -0,0 +1,18 @@ +import { getAuthUserId } from '@convex-dev/auth/server'; +import { ConvexError, v } from 'convex/values'; + +import { mutation, query } from './_generated/server'; + +export const generateUploadUrl = mutation(async (ctx) => { + const userId = await getAuthUserId(ctx); + if (!userId) throw new ConvexError('Not authenticated.'); + return await ctx.storage.generateUploadUrl(); +}); + +export const getImageUrl = query({ + args: { storageId: v.id('_storage') }, + handler: async (ctx, { storageId }) => { + const url = await ctx.storage.getUrl(storageId); + return url ?? null; + }, +}); diff --git a/packages/backend/convex/schema.ts b/packages/backend/convex/schema.ts index 44cf964..056457f 100644 --- a/packages/backend/convex/schema.ts +++ b/packages/backend/convex/schema.ts @@ -1,6 +1,6 @@ +import { authTables } from '@convex-dev/auth/server'; import { defineSchema, defineTable } from 'convex/server'; import { v } from 'convex/values'; -import { authTables } from '@convex-dev/auth/server'; const applicationTables = { // Users contains name image & email. @@ -10,8 +10,7 @@ const applicationTables = { profiles: defineTable({ userId: v.id('users'), theme_preference: v.optional(v.string()), - }) - .index('userId', ['userId']) + }).index('userId', ['userId']), }; export default defineSchema({ @@ -29,8 +28,8 @@ export default defineSchema({ phoneVerificationTime: v.optional(v.number()), isAnonymous: v.optional(v.boolean()), }) - .index("email", ["email"]) + .index('email', ['email']) .index('name', ['name']) - .index("phone", ["phone"]), + .index('phone', ['phone']), ...applicationTables, }); diff --git a/packages/backend/package.json b/packages/backend/package.json index 7fb0193..933b7a5 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -7,7 +7,9 @@ "author": "Gib", "license": "MIT", "exports": { - "./types" : "./types/index.ts" + "./convex": "./convex/", + "./convex/*": "./convex/*", + "./types": "./types/index.ts" }, "scripts": { "dev": "bun with-env convex dev", diff --git a/packages/backend/scripts/generateKeys.mjs b/packages/backend/scripts/generateKeys.mjs index 2116061..647538f 100755 --- a/packages/backend/scripts/generateKeys.mjs +++ b/packages/backend/scripts/generateKeys.mjs @@ -1,17 +1,16 @@ #!/usr/bin/env node +import { exportJWK, exportPKCS8, generateKeyPair } from 'jose'; -import { exportJWK, exportPKCS8, generateKeyPair } from "jose"; - -const keys = await generateKeyPair("RS256", { +const keys = await generateKeyPair('RS256', { extractable: true, }); const privateKey = await exportPKCS8(keys.privateKey); const publicKey = await exportJWK(keys.publicKey); -const jwks = JSON.stringify({ keys: [{ use: "sig", ...publicKey }] }); +const jwks = JSON.stringify({ keys: [{ use: 'sig', ...publicKey }] }); process.stdout.write( - `JWT_PRIVATE_KEY="${privateKey.trimEnd().replace(/\n/g, " ")}"`, + `JWT_PRIVATE_KEY="${privateKey.trimEnd().replace(/\n/g, ' ')}"`, ); -process.stdout.write("\n"); +process.stdout.write('\n'); process.stdout.write(`JWKS=${jwks}`); -process.stdout.write("\n"); +process.stdout.write('\n'); diff --git a/packages/backend/types/index.ts b/packages/backend/types/index.ts index 0ac8378..3c22f74 100644 --- a/packages/backend/types/index.ts +++ b/packages/backend/types/index.ts @@ -1,5 +1 @@ -export { - PASSWORD_MIN, - PASSWORD_MAX, - PASSWORD_REGEX, -} from './auth'; +export { PASSWORD_MIN, PASSWORD_MAX, PASSWORD_REGEX } from './auth'; diff --git a/packages/ui/.cache/.prettiercache b/packages/ui/.cache/.prettiercache index 0a20728..f53033a 100644 --- a/packages/ui/.cache/.prettiercache +++ b/packages/ui/.cache/.prettiercache @@ -1 +1 @@ -[["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32"],{"key":"33","value":"34"},{"key":"35","value":"36"},{"key":"37","value":"38"},{"key":"39","value":"40"},{"key":"41","value":"42"},{"key":"43","value":"44"},{"key":"45","value":"46"},{"key":"47","value":"48"},{"key":"49","value":"50"},{"key":"51","value":"52"},{"key":"53","value":"54"},{"key":"55","value":"56"},{"key":"57","value":"58"},{"key":"59","value":"60"},{"key":"61","value":"62"},{"key":"63","value":"64"},{"key":"65","value":"66"},{"key":"67","value":"68"},{"key":"69","value":"70"},{"key":"71","value":"72"},{"key":"73","value":"74"},{"key":"75","value":"76"},{"key":"77","value":"78"},{"key":"79","value":"80"},{"key":"81","value":"82"},{"key":"83","value":"84"},{"key":"85","value":"86"},{"key":"87","value":"88"},{"key":"89","value":"90"},{"key":"91","value":"92"},{"key":"93","value":"94"},{"key":"95","value":"96"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/based-avatar.tsx",{"size":1783,"mtime":1768155640183,"hash":"97","data":"98"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/switch.tsx",{"size":1184,"mtime":1768155641096,"hash":"99","data":"100"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/card.tsx",{"size":2001,"mtime":1768155640347,"hash":"101","data":"102"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/table.tsx",{"size":2463,"mtime":1768155641128,"hash":"103","data":"104"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/theme.tsx",{"size":5136,"mtime":1768155641207,"hash":"105","data":"106"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/status-message.tsx",{"size":1620,"mtime":1768155641049,"hash":"107","data":"108"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/drawer.tsx",{"size":4272,"mtime":1768155640435,"hash":"109","data":"110"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/field.tsx",{"size":6143,"mtime":1768155640581,"hash":"111","data":"112"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/input-otp.tsx",{"size":2269,"mtime":1768155640716,"hash":"113","data":"114"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/separator.tsx",{"size":705,"mtime":1768155640895,"hash":"115","data":"116"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/shadcn-io/image-crop/index.tsx",{"size":8265,"mtime":1768155640999,"hash":"117","data":"118"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/avatar.tsx",{"size":1103,"mtime":1768155640108,"hash":"119","data":"120"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/checkbox.tsx",{"size":1233,"mtime":1768155640375,"hash":"121","data":"122"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/submit-button.tsx",{"size":1229,"mtime":1768155641074,"hash":"123","data":"124"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/eslint.config.ts",{"size":254,"mtime":1768155640007,"hash":"125","data":"126"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/scroll-area.tsx",{"size":1652,"mtime":1768155640872,"hash":"127","data":"128"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/toast.tsx",{"size":616,"mtime":1768155641226,"hash":"129","data":"130"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/input.tsx",{"size":971,"mtime":1768155640742,"hash":"131","data":"132"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/progress.tsx",{"size":746,"mtime":1768155640843,"hash":"133","data":"134"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/sonner.tsx",{"size":571,"mtime":1768155641017,"hash":"135","data":"136"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/components.json",{"size":334,"mtime":1768154488750,"hash":"137","data":"138"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/package.json",{"size":2863,"mtime":1768154592304,"hash":"139","data":"140"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/pagination.tsx",{"size":2726,"mtime":1768155640818,"hash":"141","data":"142"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/dropdown-menu.tsx",{"size":8316,"mtime":1768155640501,"hash":"143","data":"144"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/form.tsx",{"size":3820,"mtime":1768155640641,"hash":"145","data":"146"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/index.ts",{"size":358,"mtime":1768155640668,"hash":"147","data":"148"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/label.tsx",{"size":617,"mtime":1768155640773,"hash":"149","data":"150"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/button.tsx",{"size":2175,"mtime":1768155640302,"hash":"151","data":"152"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/tabs.tsx",{"size":1979,"mtime":1768155641150,"hash":"153","data":"154"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/.cache/.prettiercache",{"size":10630,"mtime":1766222924000,"hash":"155"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/based-progress.tsx",{"size":1375,"mtime":1768155640252,"hash":"156","data":"157"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/tsconfig.json",{"size":212,"mtime":1766222924000,"hash":"158","data":"159"},"d69a0e5fdb3888844b71dfdee5f813dd",{"hashOfOptions":"160"},"30fdb7fe3f0f4d9cb3f17ead38ab2710",{"hashOfOptions":"161"},"fd1402a8aa6236b1eb117ada1f98bd21",{"hashOfOptions":"162"},"42967486452ac83a149ee140423a4065",{"hashOfOptions":"163"},"1f86d79c756f84b47125c6a3732aaf45",{"hashOfOptions":"164"},"dac382d2d0d08026270d9c933f9737dd",{"hashOfOptions":"165"},"c31e895d3d278760c17a87f2d33131e1",{"hashOfOptions":"166"},"1d4bbaf35debf9b198c886243d2745ed",{"hashOfOptions":"167"},"93effaa68d3ff052b89b54ced171a245",{"hashOfOptions":"168"},"f01e024d0d178647dc7204452075ce12",{"hashOfOptions":"169"},"2e23103491f72060b7b9971eb2938457",{"hashOfOptions":"170"},"1d9a1751746f365ac032bc97f9e39d43",{"hashOfOptions":"171"},"2e1fabe687ca93eb253bf88ab65a1553",{"hashOfOptions":"172"},"3ad0e3e4e3b4653b9aaf6fb7073add9a",{"hashOfOptions":"173"},"4f0c0909cf87c379b2cfc8de210e356b",{"hashOfOptions":"174"},"a9c4e791b40bab3829728e433a9737f8",{"hashOfOptions":"175"},"89e227070d3bd527069b51fcb38bf478",{"hashOfOptions":"176"},"03d3114dab331cb026cfcc942da0d4e4",{"hashOfOptions":"177"},"ff01b0e779be43df0dc536e3cd7c0722",{"hashOfOptions":"178"},"110620cc4b93a9dd62b75fe19d1996b0",{"hashOfOptions":"179"},"533014bafb3b9cbc3d1dbb8de7268bad",{"hashOfOptions":"180"},"b104854cfecde915ac60e2e237113200",{"hashOfOptions":"181"},"259c895da43e67115580315b5b01a82c",{"hashOfOptions":"182"},"7d924e3089aae53a4faaf35e9556c2ce",{"hashOfOptions":"183"},"7d6df6cca4478a4d47b978a33f565a9f",{"hashOfOptions":"184"},"b5e4fddb152ae937ac66af6267234c87",{"hashOfOptions":"185"},"8d5829c6cf524ab076d0598c6f567c27",{"hashOfOptions":"186"},"5ae3c05dee3828c34aeabac3fd8304e9",{"hashOfOptions":"187"},"e847b04c5623e9d066c5949ec6c917e8",{"hashOfOptions":"188"},"7b347163172048f2a800bbad09ed6f3d","17b0a237cedd06d700004aff79857eb0",{"hashOfOptions":"189"},"9fdf7ba4483e1150ea3944be29f4900e",{"hashOfOptions":"190"},"593095751","3976055592","1290706692","2480099922","524365","1319403232","1827761285","972618942","3592434636","1635320393","743650936","629671245","2070032983","1838800395","2060562380","3013375985","833715467","1603058254","2314953537","611737693","3085883012","565564622","4292802606","2164177983","1838826072","71323076","2657373336","442963750","2643614674","1817537851","2682208729"] \ No newline at end of file +[["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31"],{"key":"32","value":"33"},{"key":"34","value":"35"},{"key":"36","value":"37"},{"key":"38","value":"39"},{"key":"40","value":"41"},{"key":"42","value":"43"},{"key":"44","value":"45"},{"key":"46","value":"47"},{"key":"48","value":"49"},{"key":"50","value":"51"},{"key":"52","value":"53"},{"key":"54","value":"55"},{"key":"56","value":"57"},{"key":"58","value":"59"},{"key":"60","value":"61"},{"key":"62","value":"63"},{"key":"64","value":"65"},{"key":"66","value":"67"},{"key":"68","value":"69"},{"key":"70","value":"71"},{"key":"72","value":"73"},{"key":"74","value":"75"},{"key":"76","value":"77"},{"key":"78","value":"79"},{"key":"80","value":"81"},{"key":"82","value":"83"},{"key":"84","value":"85"},{"key":"86","value":"87"},{"key":"88","value":"89"},{"key":"90","value":"91"},{"key":"92","value":"93"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/based-avatar.tsx",{"size":1738,"mtime":1768239263550,"hash":"94","data":"95"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/switch.tsx",{"size":1186,"mtime":1768239263972,"hash":"96","data":"97"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/card.tsx",{"size":1998,"mtime":1768239263622,"hash":"98","data":"99"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/table.tsx",{"size":2465,"mtime":1768239263980,"hash":"100","data":"101"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/theme.tsx",{"size":1796,"mtime":1768239264008,"hash":"102","data":"103"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/status-message.tsx",{"size":1619,"mtime":1768239263956,"hash":"104","data":"105"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/drawer.tsx",{"size":4269,"mtime":1768239263651,"hash":"106","data":"107"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/field.tsx",{"size":6073,"mtime":1768239263711,"hash":"108","data":"109"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/input-otp.tsx",{"size":2266,"mtime":1768239263796,"hash":"110","data":"111"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/separator.tsx",{"size":702,"mtime":1768239263893,"hash":"112","data":"113"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/shadcn-io/image-crop/index.tsx",{"size":8230,"mtime":1768239263934,"hash":"114","data":"115"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/avatar.tsx",{"size":1102,"mtime":1768155815000,"hash":"116","data":"117"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/checkbox.tsx",{"size":1230,"mtime":1768239263633,"hash":"118","data":"119"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/submit-button.tsx",{"size":1192,"mtime":1768239263964,"hash":"120","data":"121"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/eslint.config.ts",{"size":254,"mtime":1768155640000,"hash":"122","data":"123"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/scroll-area.tsx",{"size":1654,"mtime":1768239263883,"hash":"124","data":"125"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/input.tsx",{"size":968,"mtime":1768239263824,"hash":"126","data":"127"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/progress.tsx",{"size":748,"mtime":1768239263868,"hash":"128","data":"129"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/sonner.tsx",{"size":601,"mtime":1768239263943,"hash":"130","data":"131"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/components.json",{"size":334,"mtime":1768154488000,"hash":"132","data":"133"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/package.json",{"size":2864,"mtime":1768155775000,"hash":"134","data":"135"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/pagination.tsx",{"size":2718,"mtime":1768239263856,"hash":"136","data":"137"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/index.tsx",{"size":2381,"mtime":1768155754000,"hash":"138","data":"139"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/dropdown-menu.tsx",{"size":8313,"mtime":1768239263677,"hash":"140","data":"141"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/form.tsx",{"size":3782,"mtime":1768239263749,"hash":"142","data":"143"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/label.tsx",{"size":614,"mtime":1768239263842,"hash":"144","data":"145"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/button.tsx",{"size":2172,"mtime":1768239263600,"hash":"146","data":"147"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/tabs.tsx",{"size":1981,"mtime":1768239263989,"hash":"148","data":"149"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/.cache/.prettiercache",{"size":7506,"mtime":1768171236843,"hash":"150"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/src/based-progress.tsx",{"size":1372,"mtime":1768239263575,"hash":"151","data":"152"},"/home/gib/Documents/Code/convex-monorepo/packages/ui/tsconfig.json",{"size":212,"mtime":1766222924000,"hash":"153","data":"154"},"fb305784644a3f5d8fee10c2ed2bc13c",{"hashOfOptions":"155"},"533106c95900b0778503c7e1fbd7e3b5",{"hashOfOptions":"156"},"cf72b92490a107b644191f7290b825ae",{"hashOfOptions":"157"},"6ce1ae153ab75c579dc6eabb8643257c",{"hashOfOptions":"158"},"7c84912508ed760794d0c0104d782029",{"hashOfOptions":"159"},"e55bdfcf730dec13a309bb21f75e8689",{"hashOfOptions":"160"},"bcbeecffac17987c207e626dd26148a9",{"hashOfOptions":"161"},"ae8ad594f4f6731e49733b5fd4bb6883",{"hashOfOptions":"162"},"1ebededed229f855d2743e9ccd2e1486",{"hashOfOptions":"163"},"376b0a40538923372eefa9b19efd57dc",{"hashOfOptions":"164"},"fcc6041c9c099fc81f69b4d5a6327831",{"hashOfOptions":"165"},"632a57a2d7eae6407d283bce342edbd8",{"hashOfOptions":"166"},"816c03f0a00da8a832dd89128d7c9a54",{"hashOfOptions":"167"},"91769a403a6c712be29807f2adbdef2b",{"hashOfOptions":"168"},"4f0c0909cf87c379b2cfc8de210e356b",{"hashOfOptions":"169"},"30a83c96e273271c3f66fba972485a41",{"hashOfOptions":"170"},"04874c2ed8a809a073524b1471ae3ec5",{"hashOfOptions":"171"},"a699f0f22a5a4f600c92e7fc62820b2c",{"hashOfOptions":"172"},"dad3743e90a5fbb7859d0cbe23383c3e",{"hashOfOptions":"173"},"533014bafb3b9cbc3d1dbb8de7268bad",{"hashOfOptions":"174"},"07ca2d3653b88632d9228701a48dd027",{"hashOfOptions":"175"},"ce4d12d02aa36fee546bd875b9a440f5",{"hashOfOptions":"176"},"80aabcfed37770114c91932cd7036b00",{"hashOfOptions":"177"},"ee1f597f563b1002e2d2543b3113d4c3",{"hashOfOptions":"178"},"6772ab7e31cf042d85c60bee4c5a4f76",{"hashOfOptions":"179"},"1be500b8403f6747d5f9f6663b68c5da",{"hashOfOptions":"180"},"5cb226d69a8978c28ab7ce94f6e9f759",{"hashOfOptions":"181"},"139e53f66e8d675644ccf04bbe7ad442",{"hashOfOptions":"182"},"1a2388a40d94645fe8ccae286923dcc1","44e8c8a88f79a7e3a22c288574f201f9",{"hashOfOptions":"183"},"9fdf7ba4483e1150ea3944be29f4900e",{"hashOfOptions":"184"},"593095751","3976055592","1290706692","2480099922","524365","1319403232","1827761285","972618942","3592434636","1635320393","743650936","629671245","2070032983","1838800395","2060562380","3013375985","1603058254","2314953537","611737693","3085883012","565564622","4292802606","1037691990","2164177983","1838826072","2657373336","442963750","2643614674","1817537851","2682208729"] \ No newline at end of file diff --git a/packages/ui/src/based-avatar.tsx b/packages/ui/src/based-avatar.tsx index fbe6d1c..cf549f2 100644 --- a/packages/ui/src/based-avatar.tsx +++ b/packages/ui/src/based-avatar.tsx @@ -1,10 +1,11 @@ 'use client'; import type { ComponentProps } from 'react'; -import { cn, AvatarImage } from '@gib/ui'; import * as AvatarPrimitive from '@radix-ui/react-avatar'; import { User } from 'lucide-react'; +import { AvatarImage, cn } from '@gib/ui'; + type BasedAvatarProps = ComponentProps & { src?: string | null; fullName?: string | null; diff --git a/packages/ui/src/based-progress.tsx b/packages/ui/src/based-progress.tsx index 55d4c87..a82de57 100644 --- a/packages/ui/src/based-progress.tsx +++ b/packages/ui/src/based-progress.tsx @@ -1,9 +1,10 @@ 'use client'; import * as React from 'react'; -import { cn } from '@gib/ui'; import * as ProgressPrimitive from '@radix-ui/react-progress'; +import { cn } from '@gib/ui'; + type BasedProgressProps = React.ComponentProps< typeof ProgressPrimitive.Root > & { diff --git a/packages/ui/src/button.tsx b/packages/ui/src/button.tsx index 35b0bbf..ffa0d21 100644 --- a/packages/ui/src/button.tsx +++ b/packages/ui/src/button.tsx @@ -1,9 +1,10 @@ import type { VariantProps } from 'class-variance-authority'; import * as React from 'react'; -import { cn } from '@gib/ui'; import { Slot } from '@radix-ui/react-slot'; import { cva } from 'class-variance-authority'; +import { cn } from '@gib/ui'; + const buttonVariants = cva( "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", { diff --git a/packages/ui/src/card.tsx b/packages/ui/src/card.tsx index f7033e1..9ed6d6b 100644 --- a/packages/ui/src/card.tsx +++ b/packages/ui/src/card.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; + import { cn } from '@gib/ui'; function Card({ className, ...props }: React.ComponentProps<'div'>) { diff --git a/packages/ui/src/checkbox.tsx b/packages/ui/src/checkbox.tsx index 612a836..49c8a33 100644 --- a/packages/ui/src/checkbox.tsx +++ b/packages/ui/src/checkbox.tsx @@ -1,10 +1,11 @@ 'use client'; import * as React from 'react'; -import { cn } from '@gib/ui'; import * as CheckboxPrimitive from '@radix-ui/react-checkbox'; import { CheckIcon } from 'lucide-react'; +import { cn } from '@gib/ui'; + function Checkbox({ className, ...props diff --git a/packages/ui/src/drawer.tsx b/packages/ui/src/drawer.tsx index 6f60f52..64bc309 100644 --- a/packages/ui/src/drawer.tsx +++ b/packages/ui/src/drawer.tsx @@ -1,9 +1,10 @@ 'use client'; import * as React from 'react'; -import { cn } from '@gib/ui'; import { Drawer as DrawerPrimitive } from 'vaul'; +import { cn } from '@gib/ui'; + function Drawer({ ...props }: React.ComponentProps) { diff --git a/packages/ui/src/dropdown-menu.tsx b/packages/ui/src/dropdown-menu.tsx index e7dc19c..477a17e 100644 --- a/packages/ui/src/dropdown-menu.tsx +++ b/packages/ui/src/dropdown-menu.tsx @@ -1,10 +1,11 @@ 'use client'; import * as React from 'react'; -import { cn } from '@gib/ui'; import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'; import { CheckIcon, ChevronRightIcon, CircleIcon } from 'lucide-react'; +import { cn } from '@gib/ui'; + function DropdownMenu({ ...props }: React.ComponentProps) { diff --git a/packages/ui/src/field.tsx b/packages/ui/src/field.tsx index d613531..7fd614e 100644 --- a/packages/ui/src/field.tsx +++ b/packages/ui/src/field.tsx @@ -2,9 +2,10 @@ import type { VariantProps } from 'class-variance-authority'; import { useMemo } from 'react'; -import { cn, Label, Separator } from '@gib/ui'; import { cva } from 'class-variance-authority'; +import { cn, Label, Separator } from '@gib/ui'; + export function FieldSet({ className, ...props diff --git a/packages/ui/src/form.tsx b/packages/ui/src/form.tsx index ec64a86..847cb4e 100644 --- a/packages/ui/src/form.tsx +++ b/packages/ui/src/form.tsx @@ -1,9 +1,8 @@ 'use client'; +import type * as LabelPrimitive from '@radix-ui/react-label'; import type { ControllerProps, FieldPath, FieldValues } from 'react-hook-form'; import * as React from 'react'; -import { cn, Label } from '@gib/ui'; -import type * as LabelPrimitive from '@radix-ui/react-label'; import { Slot } from '@radix-ui/react-slot'; import { Controller, @@ -12,6 +11,8 @@ import { useFormState, } from 'react-hook-form'; +import { cn, Label } from '@gib/ui'; + const Form = FormProvider; type FormFieldContextValue< diff --git a/packages/ui/src/input-otp.tsx b/packages/ui/src/input-otp.tsx index a979fab..b93792a 100644 --- a/packages/ui/src/input-otp.tsx +++ b/packages/ui/src/input-otp.tsx @@ -1,10 +1,11 @@ 'use client'; import * as React from 'react'; -import { cn } from '@gib/ui'; import { OTPInput, OTPInputContext } from 'input-otp'; import { MinusIcon } from 'lucide-react'; +import { cn } from '@gib/ui'; + function InputOTP({ className, containerClassName, diff --git a/packages/ui/src/input.tsx b/packages/ui/src/input.tsx index 1e47043..90e48ff 100644 --- a/packages/ui/src/input.tsx +++ b/packages/ui/src/input.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; + import { cn } from '@gib/ui'; function Input({ className, type, ...props }: React.ComponentProps<'input'>) { diff --git a/packages/ui/src/label.tsx b/packages/ui/src/label.tsx index a691a05..ee78a9b 100644 --- a/packages/ui/src/label.tsx +++ b/packages/ui/src/label.tsx @@ -1,9 +1,10 @@ 'use client'; import * as React from 'react'; -import { cn } from '@gib/ui'; import * as LabelPrimitive from '@radix-ui/react-label'; +import { cn } from '@gib/ui'; + function Label({ className, ...props diff --git a/packages/ui/src/pagination.tsx b/packages/ui/src/pagination.tsx index 88a9fba..cc3c71b 100644 --- a/packages/ui/src/pagination.tsx +++ b/packages/ui/src/pagination.tsx @@ -1,12 +1,13 @@ import type * as React from 'react'; -import type { Button } from '@gib/ui'; -import { cn, buttonVariants } from '@gib/ui'; import { ChevronLeftIcon, ChevronRightIcon, MoreHorizontalIcon, } from 'lucide-react'; +import type { Button } from '@gib/ui'; +import { buttonVariants, cn } from '@gib/ui'; + function Pagination({ className, ...props }: React.ComponentProps<'nav'>) { return (