<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های shopid</title>
        <link>https://virgool.io/feed/@shopid</link>
        <description>shopid.ir -&gt;open source online shop solutions</description>
        <language>fa</language>
        <pubDate>2026-04-14 18:35:25</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/1576438/avatar/uYoYPg.png?height=120&amp;width=120</url>
            <title>shopid</title>
            <link>https://virgool.io/@shopid</link>
        </image>

                    <item>
                <title>async , await , Promise به زبان خیلی ساده</title>
                <link>https://virgool.io/@shopid/async-await-promise-wvow4pri41nw</link>
                <description>توی خیلی از اپ های جاوا اسکریپت async , await , Promise میبینیماینجا میخوایم خیلی ساده بگیم که اینا چطوری کار میکنن مشاهده این آموزش توی یوتوب : https://www.youtube.com/watch?v=mpYUof-FUB4 (۸:۵۶ دقیقه)مشاهده نمونه ی زنده ی این آموزش توی استکبلیتزشروع:تصور کنید یه تابع داریم اینجوریfunction sayMyName() {
 console.log(&amp;quotbehnam&amp;quot);
}خب واضحه که وقتی اجراش کنیم چکار میکنه ! کلمه behnam توی کنسول نمایش داده میشهحالا بیاین اینجوریش کنیمfunction myName() {
 return  &amp;quotbehnam&amp;quot
}
function sayMyName() {
  console.log(myName()); 
}خب اینم که معلومه دقیقا همون کار قبلیو میکنه با این تفاوت که behnam از تابع myName گرفته میشهخب حالا تصور کنید که تابع myName قراره اطلاعاتو با تاخیر به ما برگردونه مثلا همچین چیزی :function myName() {  
setTimeout(() =&gt; {
    return  &amp;quotbehnam&amp;quot 
 },2000);
}خب همچین چیزی توی جاوا اسکریپت نداریم که تابع با تاخیر چیزی return کنه !برای این کار باید قسمتی که با تاخیر اجرا میشه توی Promise بذاریم و ریترن کردنشو به عهده ی پرامیس بذاریم و پرامیسو ریترن کنیم یعنی اینجوری :function myName() {
  return new Promise(function (resolve) {
    setTimeout(() =&gt; {
    resolve(&#039;behnam&#039;);
    }, 2000);
  });
}دقت کنید که توی پرامیس بجای ریترن کردن باید تابعمونو با مقدار دلخواهمون صدا بزنیم که اینجا اسم این تابع resolve که میتونید هر اسمی بذارید براشاما myName الان Promise برمیگردونه نه behnam پس باید چکار کنیم ؟اینجاس که باید با await مقدارشو بیرون بکشیم یعنی اینجوری :console.log(await myName());اما این await فقط اجازه داره توی توابعی باشه که اولشون async باشن !یعنی اینجوری :async function sayMyName() {
    console.log(await myName());
}دلیلشم اینه که به جاوا اسکریپت بگه که این قطعه کد تابع باید حتما به ترتیبی که ما میگیم اجرا بشه !در آخر همچین چیزی داریم :
function myName() {
   return new Promise(function (resolve) {
        setTimeout(() =&gt; {
        resolve(&#039;behnam&#039;);
    }, 2000);
    });
}
async function sayMyName() {
 console.log(await myName());
}
</description>
                <category>shopid</category>
                <author>shopid</author>
                <pubDate>Tue, 13 Sep 2022 10:18:46 +0430</pubDate>
            </item>
                    <item>
                <title>ساخت اپ اندرویدی با HTML , javaScript</title>
                <link>https://virgool.io/@shopid/%D8%B3%D8%A7%D8%AE%D8%AA-%D8%A7%D9%BE-%D8%A7%D9%86%D8%AF%D8%B1%D9%88%DB%8C%D8%AF%DB%8C-%D8%A8%D8%A7-html-javascript-fjojh9hlac6p</link>
                <description>خیلی وقتا یه استارت آپ کوچیک داریم که میخوایم خیلی سریع اپ و سایتشو بالا بیاریمگزینه های زیادی جلوی ما هست یکی از این گزینه ها html و جاوا اسکریپت وانیلی هست !که خب سایتشو راحت بالا میاریم و اپ اندروید و iOS هم همینطور !مشاهده این آموزش توی یوتوب (۲۷ دقیقه یا ۱۳ دقیقه دابل اسپید?)https://www.youtube.com/watch?v=ooyWwRs1XPMتوی سایت اندرویدhttps://developer.android.com/develop/ui/views/layout/webapps/webviewخیلی واضح گفته که این کار یکی از روش های ساخت وب اپلیکیشنه !درسته ! شما بدون اینکه فریم ورک خاصی بلد باشی یا حتی اندروید خیلی راحت میتونید با html و جاوا اسکریپت این کارو انجام بدید فقط باید اندروید استدیو داشته باشیدیه اپ اندروید ایجاد کنید با Empty Activityزبانشو Kotlin بذارید و Finishبعدش اینو بذارید توی res-&gt;layout-&gt;activity_main.xml&lt;WebView
    app:layout_constraintBottom_toBottomOf=&amp;quotparent&amp;quot
    app:layout_constraintEnd_toEndOf=&amp;quotparent&amp;quot
    app:layout_constraintStart_toStartOf=&amp;quotparent&amp;quot
    app:layout_constraintTop_toTopOf=&amp;quotparent&amp;quot
    android:id=&amp;quot@+id/webview&amp;quot
    android:layout_width=&amp;quotmatch_parent&amp;quot
    android:layout_height=&amp;quotmatch_parent&amp;quot
    /&gt;بعد توی Java بگردین و MainActivity پیدا کنین و اینو توش بذاریدval myWebView: WebView = findViewById(R.id.webview)
myWebView.loadUrl(&amp;quothttp://www.google.com&amp;quot)اینجوری :بعدش برید توی manifest و پرمیژن اینترنتو اد کنید &lt;uses-permission android:name=&amp;quotandroid.permission.INTERNET&amp;quot /&gt;همینطور اینو بذارید توی تگ applicationandroid:usesCleartextTraffic=&amp;quottrue&amp;quotاینجوری :حالا ران بزنید !‌اگه گوگل لود بشه یعنی همه کارارو درست انجام دادیدحالا فقط کافیه روی لوکال یا هرجا که میخواین وب اپتونو توسعه بدین و بجای https://www.google.com آدرس اونو بذارید مثلا http://192.168.1.50:8000 یا هرجایی که دارید توسعه میدینفقط یادتون باشه آخر کار باید حتما بذارید روی هاستی که ssl باشه یعنی با https کار کنه و android:usesCleartextTraffic=&quot;true&quot; از توی مانیفست پاک کنیدجاوا اسکریپتبرای فعال کردن جاوا اسکریپت کافیه این کارو انجام بدین :myWebView.settings.javaScriptEnabled = trueالان دیگه میتونید از متد های جاوا اسکریپت هم توی اپتون استفاده کنیدارتباط از جاوا اسکریپت به اندرویدبرای اینکه بتونید از توی جاوا اسکریپت یه متد توی اندروید اجرا کنید فقط کافیه یک اینترفیس براش درست کنید اونم به این سادگی !class WebAppInterface(private val mContext: Context) {

    /** Show a toast from the web page  */
    @JavascriptInterface
    fun showToast(toast: String) {
        Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show()
    }
}فقط کافیه اینو توی کلاس MainActivity بذاریدو بعدش اینترفیسی که ساختید به وب‌ویو وصلش کنید اینجوری :webView.addJavascriptInterface(WebAppInterface(this), &quot;Android&quot;)خب الان دیگه کار تموم شد ! فقط کافیه از توی صفحه وبتون متد های اینترفیستون رو اجرا کنید و لذت ببرید !مثلا&lt;script type=&amp;quottext/javascript&amp;quot&gt;
 Android.showToast(toast);
ارتباط از اندروید به جاوااسکریپتحالا شاید بخواید یک متد توی وب‌ویو اجرا کنید !اینم خیلی سادست !فقط کافیه از evaluateJavascript استفاده کنید مثلا اینجوری myWebView.evaluateJavascript(&amp;quotmyJsMethod()&amp;quot,null)این هروقت اجرا بشه متد myJsMethod که توی جاوا اسکریپت ساختید اجرا میشه !البته اینا یک سری کامپتیبیلیتی ها و تنظیمات داره که توی کار متوجه میشیدبرای آشنایی بیشتر توی گوگل بزنید evaluateJavascript android و مثال هاشو ببنید</description>
                <category>shopid</category>
                <author>shopid</author>
                <pubDate>Fri, 09 Sep 2022 10:32:39 +0430</pubDate>
            </item>
                    <item>
                <title>لاگین با گوگل در لاراول</title>
                <link>https://virgool.io/laravel-community/%D9%84%D8%A7%DA%AF%DB%8C%D9%86-%D8%A8%D8%A7-%DA%AF%D9%88%DA%AF%D9%84-%D8%AF%D8%B1-%D9%84%D8%A7%D8%B1%D8%A7%D9%88%D9%84-gizrm55hjjnl</link>
                <description>ساخت لاگین با گوگل توی لاراول ساده تر از اونیه که فکرشو بکنید فقط یکم باید دقت کنیدکار با نصب laravel/socialite شروع میشه با این پکیج میتونید با linkedin, google, github, gitlab لاگین بسازیدنصبش با کامپوزره :composer require laravel/socialiteمشاهده آموزش کامل توی یوتوب (۲۱ دقیقه) : https://www.youtube.com/watch?v=05mL6f4xCAAسورس نمونه توی گیتهاب :‌ https://github.com/shopid-dev/laravel-socialiteبعدش باید توی config/services.phpاینو اد کنید :&#039;github&#039; =&gt; [
&#039;client_id&#039; =&gt; env(&#039;GITHUB_CLIENT_ID&#039;),
&#039;client_secret&#039; =&gt; env(&#039;GITHUB_CLIENT_SECRET&#039;),
&#039;redirect&#039; =&gt; &#039;http://example.com/callback-url&#039;,
],مقادیر client_id و client_secret باید از گوگل بگیریدredirect هم آدرس سایت و مسیریه که وقتی از گوگل برمیگردید باید ست کنیدگرفتن client_id و client_secret از گوگلمشاهده فیلم این قسمت توی یوتوب این قسمتش تقریبا سخت ترین قسمتش شاید باشه چون اینجا یکم تحریمه ولی مشکلی بابت لاگین کردن نداره فقط گرفتنش یکم سختهفقط توی گوگل بزنید google developer console و وارد سایتش بشیداگه پروژه ای نداشته باشید باید یدونه بسازید اکه قبلا consent screen کانفیگ نکرده باشید اینجا میگه برید کانفیگ کنیداینجا External بزنید و Create بزنیداینجا همه چیزایی که میخواد وارد کنید البته خیلیش آپشنال هستآخرشم SAVE AND CONTINUE بزنید و برید توی قسمت Credentialsبعدش از اون منوی بالا روی CREATE CREDENTIALS + کلیک کنیدو بزنید روی OAuth client IDبعدش Web application انتخاب کنیداینجا هم موارد خواسته شده پر کنیدبعدش میریم توی سورسمون و اون redirect میاریممیزنیم توی Authorized redirect URIs و Create میزنیمو در آخر  client_id و client_secret میاد !و میریم ثبتش میکنیممشاهده این قسمتش توی یوتوبحالا یه روت میسازیم که وقتی میریم توش بره تو گوگل به همین سادگی !use Laravel\Socialite\Facades\Socialite;
//.
//.
Route::get(&amp;quot/login&amp;quot, function () {  
return Socialite::driver(&#039;google&#039;)-&gt;redirect();
});و روت بازگشتمون هم میسازیم :به این صورت که با firstOrCreate روی مدل User اگه کاربر قبلا ثبت نام نبود رجیسترش میکنیم با یه پسورد رندم ولی اگه بود انتخابش میکنیم و در آخر میدیمش به Auth::login و احراز هویت تکمیل میشه !Route::get(&amp;quot/google-login&amp;quot, function () {
    $s_user = Socialite::driver(&#039;google&#039;)-&gt;user();
    $user = User::firstOrCreate(
        [&#039;email&#039; =&gt; $s_user-&gt;email],
        [
            &#039;name&#039; =&gt; $s_user-&gt;name,
            &#039;password&#039; =&gt; Hash::make(Str::random(8))
        ]
    );
    Auth::login($user, true);
         echo &amp;quothello &amp;quot.Auth::user()-&gt;name;
});مشاهده فیلم نتیجه ی نهایی :https://www.youtube.com/watch?v=05mL6f4xCAA&amp;amp;t=1171s </description>
                <category>shopid</category>
                <author>shopid</author>
                <pubDate>Wed, 07 Sep 2022 12:29:40 +0430</pubDate>
            </item>
                    <item>
                <title>پیاده سازی لوکیشن و نقشه و GPS روی مروگر با جاوا اسکریپت</title>
                <link>https://virgool.io/@shopid/map-and-gps-with-javascript-dpzqag7ttht6</link>
                <description>اول از همه اجازه بدید فرق نقشه و لوکیشن و  مختصات و GPS بگماینا همه به هم ربط دارن ولی یکی نیستن !اگه بخوایم به زبون خیلی ساده بگیم نقشه همون نقشه ی کل کره ی زمینه بعد اومدن این نقشرو (مثل متر) به قسمت های مختلف تقسیم بندی کردن که بهش میگن مختصات ! بعد هر نقطه روی این صفحه میشه لوکیشن یا موقعیت ، که توی مبحث ما با دوتا عدد نشونش میدن مثلا 55,37 که اگه همین الان همین 55,37 توی سرچ گوگل بزنید میفتید توی روسیه نزدیکای موسکو !مشاهده این آموزش به صورت ویدئو توی یوتوب (۲۵ دقیقه) (دابل اسپید ببین ۱۲ دقیقه ?)مشاهده دموی زنده این آموزش توی استکبلیتزhttps://stackblitz.com/edit/web-platform-yryhxqبه عدد اولی یعنی 55 میگیم عرض جغرافیایی (latitude) (حرکت عمودی یا بالا و پایین نقشه)به دومی یا همون 37 میگیم طول جغرافیایی (longitude) (حرکت به چپ و راست نقشه)(به اختصار به اینا lat,lng هم میگن)تا اینجا همه چیز روی نقشه و عدد بودحالا GPS چیه ؟جی پی اس مخفف Global Positioning System یا سامانه موقعیت‌یاب جهانی که یک سری ماهواره توی مدار زمین هستند که هرکس بهش درخواست بده و وصل بشه موقیت همون شخصو بهش میگه !میدونم هیجان دارید که زود بریم لوکیشن بازی کنیم ولی اجازه بدید قدم به قدم بریم جلو که قاطی نکنید✅ پیاده سازی نقشه روی مرورگر با جاوااسکریپتنقشه ها یا همون map چیزی بجز یک سری تصاویر که بهشون میگن tile (تایل) نیستن که کنار هم قرار میگیرن و نقشرو تشکیل میدن ! امکان درگ کردن ، زوم و اسکرول و فلگ زدن (پرچم) و کلا هرچی که بخواید هم میتونن داشته باشن و فرقی هم نداره دارید با چی کار میکنید اگه html باشه از همون المنت های مرورگر استفاده میشه اگه اندروید باشه از المنت های خودش و ... حالا ما اگه خودمون بخوایم همچین چیزی با html بسازیم یکم زمانبره و بخاطر همین میایم از پکیج ها کتابخونه ها استفاده میکنیم و خیلی راحت توسعش میدیم ! (ولی اگه علاقه دارید بسازید)لایبرری leafletjsخب یکی از پکیج های بی درد سر برای این کار leafletjs هست که میتونید برید توی سایتش https://leafletjs.com و داکیومنتاشو بخونید و کارتونو راه بندازید ما هم اینجا یه معرفی کوچیک میکنیم ازشبرای پیاده سازیش اول از همه این دوتارو باید لود کنید (میتونید دانلودنشون کنید توی هاست خودتون و ازنونجا هم لود کنید)&lt;link rel=&amp;quotstylesheet&amp;quot href=&amp;quothttps://unpkg.com/leaflet@1.8.0/dist/leaflet.css&amp;quot /&gt;
&lt;script src=&amp;quothttps://unpkg.com/leaflet@1.8.0/dist/leaflet.js&amp;quot&gt;و بعدش با این ۵ خط کد میایم بالا سر تهران وایمیسیم !&lt;div id=&amp;quotmap&amp;quot style=&amp;quotwidth:500px;height:500px&amp;quot&gt;&lt;/div&gt;
var map = L.map(&#039;map&#039;).setView([35.69, 51.38], 10);
L.tileLayer(&#039;https://tile.openstreetmap.org/{z}/{x}/{y}.png&#039;).addTo(map);یعنی در نهایت یه همچین چیزی داریم !&lt;!DOCTYPE html&gt;
&lt;html lang=&amp;quoten&amp;quot&gt;
&lt;head&gt;
&lt;title&gt;map&lt;/title&gt;
&lt;meta charset=&amp;quotUTF-8&amp;quot /&gt;
&lt;meta name=&amp;quotviewport&amp;quot content=&amp;quotwidth=device-width&amp;quot /&gt;
&lt;link rel=&amp;quotstylesheet&amp;quot href=&amp;quothttps://unpkg.com/leaflet@1.8.0/dist/leaflet.css&amp;quot /&gt;
&lt;script src=&amp;quothttps://unpkg.com/leaflet@1.8.0/dist/leaflet.js&amp;quot&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div id=&amp;quotmymap&amp;quot style=&amp;quotwidth:500px;height:500px&amp;quot&gt;&lt;/div&gt;

var map = L.map(&#039;mymap&#039;).setView([35.69, 51.38], 10);
L.tileLayer(&#039;https://tile.openstreetmap.org/{z}/{x}/{y}.png&#039;).addTo(map);

&lt;/body&gt;
&lt;/html&gt;اون div که ساختیم آی‌دیش mymap همون جاییه که میخوایم نقشه نمایش داده بشهقسمت var map = L.map(&#x27;mymap&#x27;) یه آبجکت نقشه ساختیم و گفتیم که توی همون div که آیدیش mymap بود نقشمونو نمایش بدهاونجا هم که گفتیم  setView([35.69, 51.38], 10) پارامتر اولی که آرایس مختصات تهران روی نقشس و پارامتر دومی هم مقدار زوم روی نقسشاونجا هم که نوشته https://tile.openstreetmap.org در حقیقت بیس آدرس لود کردن تایل هاست (همون تصاویر نقشه به صورت تکه تکه)  اینو میتونید از سرور خودتون یا جای دیگه هم لود کنیدتموم شد الان توی مرورگر شما یه نقشه دارید که از لایبرری leaflet استفاده میکنه و از تایل های openstreetmap استفاده میکنه و روی مختصات تهران وایساده !اگه بیشتر میخواید راجع به تایل ها و استفاده ازشون بدونید میتونید به https://wiki.openstreetmap.org/wiki/Tiles مراجعه کنید و داکیومنتاشو بخونیدرفتن به یک مختصات خاص ?خب تا اینجا ما نقشمونو توی مرورگر با جاوا اسکریپت نمایش دادیمحالا اگه بخوایم دوربین نقشرو به یک نقطه ی خاص ببریم و وایسیم فقط کافیه از همون var map که تعریف کردیم setView صدا بزنیم ! که پارامتر اول یک آرایس که همون مختصاته و پارامتر دوم مقدار زومه که کمترینش ۰ که کل دنیارو نشون میده و بیشترینش ۱۸ که دیگه خیلی میره نزدیک !map.setView([35.69, 53.38], 15)علامت زدن روی نقشه?حالا اگه بخوایم یه علامت روی یه نقطه خاص بزنیم اینجوری عمل میکنیم :var marker = L.marker([35.69, 51.38]).addTo(map);خب تا اینجا یکم با نقشه و تغییر موقیعت و اینا آشنا شدیم اگه بیشتر میخواین راجع به این جنگولک بازیا بدونید اینجا برید و کامل همه داکیومنتاشو ببینیدکارای خیلی بیشتر میشه کرد...https://leafletjs.com/examples.htmlگرفتن موقعیت کاربر از مرورگرخب اینجا دیگه هیچ ربطی به نقشه و leaflet نداره و ما فقط میخوایم با مرورگر و جاوا اسکریپت خالص کار کنیم و موقعیتو بگیریم و بعد خودمون ربطش میدیم به نقشه !گرفتن مختصات کاربر از مرورگر با تابع navigator.geolocation.getCurrentPosition انجام میشهکه داکیومنت کاملش اینجاست https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/getCurrentPositionاین تابع وقتی اجرا میشه خودش درخواست پرمیژن هم اجار میکنه که به این صورت باید اجراش کنید navigator.geolocation.getCurrentPosition(function(res) {
        console.log(res)
});که اینارو توش دارهcoords: GeolocationCoordinates
accuracy: 150
altitude: null
altitudeAccuracy: null
heading: null
latitude: 37.774929
longitude: -122.419416
speed: null
[[Prototype]]: GeolocationCoordinates
timestamp: 1662291570037خب واضحه که چه چیزایشو ما میخوایم ! الان فقط کافیه latitude و longitude به اون نقشه ای که بالا داشتیم بدیم !یه چیزی مثل این :function where_am_i() {
  navigator.geolocation.getCurrentPosition(function (res) {
  map.setView([res.coords.latitude, res.coords.longitude], 10);
});
}الان هر وقت تابع where_am_i اجرا بشه اول اجازه میگیره که میخواد به لوکیشن دست رسی داشته باشه بعد نقشه مستقیم میره روی لوکیشنی که کاربر دارهاما خیلی وقتا ما روی کامپیوتر داریم دولوپ میکنیم و خب GPS ممکنه فعال نباشهجای نگرانی نیست چون کروم توی DevTools برامون یه GPS فیک گذاشته و میتونیم اونجا باهاش بازی کنیمبرای استفاده ازش باید اینسپکت کنیم یا همون DevTool باز کنیم بعد اون سه تا نقطه کنارشو بزنیم و توی More Tools بزنم روی Sensors و  بعد از Location استفاده کنیم و هر latitude , longitude خواستیم بدیماین navigator.geolocation یه watchPosition هم داره که به صورت اتوماتیک با تغییر مکان کاربر اجرا میشه و یه جورایی زنده نشون میکه که رو نقشه کجاییم و فقط کافیه یک بار اجراش کنیماینجوریnavigator.geolocation.watchPosition(function (res) {
map.setView([res.coords.latitude, res.coords.longitude], 10);
});بقیه داکیومنتاشم که همینجا هستhttps://developer.mozilla.org/en-US/docs/Web/API/Geolocation</description>
                <category>shopid</category>
                <author>shopid</author>
                <pubDate>Sun, 04 Sep 2022 17:09:45 +0430</pubDate>
            </item>
                    <item>
                <title>سنکتوم (sanctum) لاراول برای API به زبان خیلی ساده !</title>
                <link>https://virgool.io/@shopid/laravel-sanctum-kibcmykvqfut</link>
                <description>جدیدا وقتی یه پروژه لاراول میسازیم  سنکتوم روش هست !و وقتی وارد api.php بشیمهمچین چیزی میبینیم :Route::middleware(&#039;auth:sanctum&#039;)-&gt;get(&#039;/user&#039;, function (Request $request) {
 return $request-&gt;user();
});استفاده از این پکیج خیلی سادست !مشاهده ویدئو نمونه اجرای ساده توی یوتوب (9 دقیقه)https://www.youtube.com/watch?v=d7uV17NhSUoشما فقط کافیه که از آبجکت هر یوزری که میخواین توکن بگیرید ! چجوری ؟ اینجوری :Auth::user()-&gt;createToken(&amp;quottokenname&amp;quot)یا مثلاUser::whereEmail(&amp;quotalycia.miller@example.com&amp;quot)-&gt;first()-&gt;createToken(&amp;quotmyapp&amp;quot)به همین سادگی ! یعنی بعد از اینکه یوزر یک بار احراز هویت شد ازش یک توکن میگیرید و ازون توکن توی هدر هر ریکوئستی استفاده کنید در واقع احراز هویت انجام میشههدر هم که همون پروتکل معروف خرسنده? (Bearer)Authorization : Bearer token-string-hereاین هدر به هر middleware از نوع auth:sanctum بفرستید همه کارارو خودش انجام میده و یوزر براتون احراز میشه و ریخته میشه توی ?$request-&gt;user()ازین توی همه ی فریمورکای جاوا اسکریپت مث انگولار ری اکت ویوو و همچنین جاهای دیگه مثل اندروید و iOS و کلا هرجا که ریکوئست http بفرستید و میتونید استفاده کنید !</description>
                <category>shopid</category>
                <author>shopid</author>
                <pubDate>Fri, 02 Sep 2022 23:44:16 +0430</pubDate>
            </item>
                    <item>
                <title>جاوا اسکریپت : ساخت بنر اینستاگرامی برای محصولات فروشگاه</title>
                <link>https://virgool.io/Rocket/konvajs-zd503aqp4dyb</link>
                <description>خیلی وقتا نیازه که برای محصولاتمون بنر یا همون پست به صورت فایل تصویری بسازیم که بتونیم توی اینستاگرام پست یا استوری کنیم یا حتی توی تلگرام و واتسپ برای مشتری ارسال کنیمما معمولا محصولات به صورت متنی و تصویری توی دیتابیس فروشگاهمون ثبت میکنیم فرقی نمیکنه فروشگاهمون با چی ساخته شده ، وردپرس باشه یا ری‌اکت به هر حال دیتابیس داره !مشاهده نمونه ی زنده توی استکبلیتز :https://stackblitz.com/edit/web-platform-rmk8xb?file=index.htmlمشاهده این آموزش به صورت ویدیوئی در یوتوبhttps://youtu.be/tk_h_MilqPwاگه با canvas آشنایی داشته باشید میدونید که میتونیم این اطلاعاتو با جاوااسکریپت و canvas به فایل تصویری png تبدیل کنیم !اگه با canvas کار کرده باشید میدونید که خیلی سادست اما داستان وقتی سخت میشه که بخوایم تصاویر پیچیده تر بسازیم که کاربر پسند تر هم باشه !خب یه آدم خیلی خوب (به نام آقای آنتون از مکزیک) اومده و یه لایبرری (خودش میگه فریم ورک) ساخته به نام Konva که این کارو خیلی خیلی خیلی راحت تر کرده !اینجاس که باید به زبون خودش بهش بگیم Dios te bendiga mi amigo یعنی خدا خیرت بده داداش !سایت آموزشش اینه و هرچی بخواین توش به زبون خیلی ساده یاد داده https://konvajs.org/docs/index.htmlداستاشم خیلی سادستاول نصبش میکنی یا ایمپورتش میکنیnpm install konvaیا&lt;script src=&amp;quothttps://unpkg.com/konva@8/konva.min.js&amp;quot&gt;و بعدش همه چیز از استیج شروع میشه شما یه استیج درست میکنی اینجوری :
var stage = new Konva.Stage({
  container: &#039;container&#039;, 
  width: 500,
  height: 500
});
و بعد container در واقع آی‌دی همون المنتی میشه که شما میخوای توش تصویر اجرا بشه (خودش گفته div شما هم div بزنید) مثلا اینجوری :&lt;div id=&amp;quotcontainer&amp;quot &gt;&lt;/div&gt; استیج یه چیزی تو مایه های همون new file توی فتوشاپه یه طول و عرض داره و تمام !توی استیج همه چیز لایه است ! یعنی شما باید یه لایه ایجاد کنی بعد توی این لایه هرچی دلت خواست اضافه میکنی (متن ، عکس ‌، فیلم ، اشکال مختلف و ...)ساخت لایه اینجوریه :
var layer = new Konva.Layer();
حالا مثلا فرض کنیم میخوایم یه دایره قرمز بکشیم
var circle = new Konva.Circle({
  x: stage.width() / 2,
  y: stage.height() / 2,
  radius: 70,
  fill: &#039;red&#039;
});
بعدش باید این دایره رو به اون لایه اضافه کنیم
layer.add(circle);
حالا لایه رو باید به استیج اضافه کنیم (قبلشم میشه)
stage.add(layer);
و در آخر : 
layer.draw();
//(که اینم نزنید اتومات خودش میزنه انگار وقتی اینیت میشه !)
تمام !سورس کاملش اینجوری میشه :&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;script src=&amp;quothttps://unpkg.com/konva@8/konva.min.js&amp;quot&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div id=&amp;quotcontainer&amp;quot&gt;&lt;/div&gt;

var stage = new Konva.Stage({
container: &#039;container&#039;,
width: 500,
height: 500,
});
var layer = new Konva.Layer();
var circle = new Konva.Circle({
x: stage.width() / 2,
y: stage.height() / 2,
radius: 70,
fill: &#039;red&#039;,
});
layer.add(circle);
stage.add(layer);
layer.draw();

&lt;/body&gt;
&lt;/html&gt;درگ کردن و ریسایز کردنبرای اینکه هر المنت قابلیت جابجایی با ماوس یا تاچ داشته باشه فقط کافیه draggable: true مثلا همون دایره قرمزه اینجوری میشهvar circle = new Konva.Circle({
x: stage.width() / 2,
y: stage.height() / 2,
radius: 70,
fill: &#039;red&#039;,
draggable:true
});برای ترنسفورم کردن یا همون ریسایز کردن اینجا کامل توضیح دادهداستانشم خیلی سادست فقط باید برای هر المنت یا المنت هایی که میخواید ترنسفورم بشه یدونه ‌‌Konva.Transformer بسازید و المنتایی که میخواید به nodes اضافه کنید و transformer به layer اضافه کنید !اینجوریvar tr = new Konva.Transformer();
tr.nodes([circle]);
layer.add(tr);فقط یادتون باشه موقع خروجی گرفتن یا همون سیو کردن ترنسفورم هاید کنید وگرنه میوفته توش !tr.hide();بعد اینکه سیو کردید میتونید شوش کنید tr.show();نوشتن متن فارسی و فونت !خب یکی از چیزایی که ما فارسی زبون ها باهاش از دیرباز مشکل داشتیم نوشتن متن فارسی بوده !خوشبختانه این لایبرری از زبون فارسی و متن راست به چپ و فونت پشتیبانی میکنه اما دوتا نکته وجود داره که باید دقت کنیداول اینکه برای نوشتن متن راست به چپ میتونید کانتینر rtl کنید حالا یا با css یا با dir=rtlیا اینکه اینجوری خود canvas راست به چپ کنیدconst canvas = layer.getCanvas()._canvas;
canvas.setAttribute(&#039;dir&#039;, &#039;rtl&#039;);همه چیز درسته ولی وقتی بخواین از متد هایی که خود Konva گفته برای ذخیره استفاده کنید ممکنه راست به چپتون بهم بریزهاما نگران نباشید اینجا جاوااسکریپته و همه چیز قابل دستکاریه !خیلی راحت از خود canvas سیو کنید هرچند قابلیت pixelRatio اینجا نیستش ولی خب کارو راه میندازه !یه نمونه کامل سیو کردن توی همون استکبلیتز هست برید ببیند میفهمید چطوریه ولی اینجا هم یه توضیح کوچولو میدمconst canvas = layer.getCanvas()._canvas;
var dataURL = canvas.toDataURL(&#039;image/png&#039;);
downloadURI(dataURL, &#039;stage.png&#039;);خط اول المنت canvas کشیدیم بیرونخط دوم دیتاشو کشیدیم بیرون و آخر سر دادیم به downloadURI که دانلودش کنیم !و اما فونت !ببینید طبق خود داکیومنت Konva از فونت های لود شده در DOM استفاده میکنه پس اگه فونتی لود بشه قابل استفادس شما میتونید از fontfaceobserver.com استفاده کنید که خیالتون راحت باشه فونته لود شده بعد تکست بسازید یا به روش کثیف عمل کنید و از setTimeout معروف استفاده کنید ! یعنی صبر کنید تا لود بشه بعد تکست بسازیدsetTimeout&#40;(&#41;=&gt;{
  // inja text besaz 
},1000);بقیه ابزارشم انقد خود سایت کامل و ساده توضیح داده که نوشتنشون اینجا دوباره نویسیه !خودتون برید متوجه میشید از فوتوشاپ هم آسون ترهدر پایان هم اگه پروژه ای با konva ساختید سعی کنید هرچند کم این داداش مکزیکیمونو دونیت کنید چون واقعا کار کردن با canvas خیلی سخته و ایشون ۹۹ درصد آسونش کرده !https://konvajs.org/docs/donate.html</description>
                <category>shopid</category>
                <author>shopid</author>
                <pubDate>Sat, 27 Aug 2022 19:14:16 +0430</pubDate>
            </item>
                    <item>
                <title>ارسال نوتیفیکیشن به مرورگر با لاراول</title>
                <link>https://virgool.io/Rocket/laravel-push-notification-ofd8ql4rc5ns</link>
                <description>نوتیفیکیشن یک جز جدا نشدنی از فروشگاه های اینترنتیه !خیلی خوب میشه وقتی سفارش مشتری آماده به ارسال میشه یه نوتیفیکیشن کوچیک هم براش ارسال بشه و بگه سفارش شما ارسال شد !اینجوری هم مشتری راضی میشه هم اینکه کلی وقت و انرژی از اپراتور و مشتری هدر نمیرهمشاهده ی این آموزش توی یوتوب :‌ https://www.youtube.com/watch?v=F5I5mfVZKxIخب حالا چطور باید اینکارو با لاراول انجام بدیم ؟خیلی سادهکلا داستان نوتیفیکیشن توی مرورگر ها چه دسکتاپ چه موبایل با یه تابع انجام میشه !new Notification(&#x27;salam&#x27;);همین الان همینو توی کنسول مروگر وارد کنید میبینید که هیچی نمیشه ?چون که به احتمال ۹۹ درصد هنوز اجازه ی ارسال نوتیفیکیشن به مرورگر رو ندادیدبرای اینکه اجازه بدید ، توی آدرس بار کنار اسم سایت روی علامت قفل یا همون ssl کلیک کنید و توی site setting نوتیفیکیشن allow کنید و دوباره همون کد بالا رو بزنید میبینید که شدخب درسته هیچ سایتی اینجوری نوفیکیشن ارسال نمیکنه ، اصلش اینجوریه که نوتیفیکیشن باید وقتی کاربر توی سایتمون نیست ارسال بشه تا دوباره بیاریمش توی سایتمون !مراحل عملکرد پوش نوتیفیکیشن :کاربر وارد سایت میشهاز کاربر درخواست میشه اجازه بده که براش نوتیفیکیشن ارسال بشهاگر کاربر اجازه داد pushManager.subscribe اجرا میشه و یک سری اطلاعات و آدرس اندپوینت مروگر به ما داده میشه مثلا برای کروم همچین چیزیه fcm.googleapis.com/fcm/send یا برای فایرفاکس updates.push.services.mozilla.com و ما باید این مقادیرو به صورت جی‌سان توی دیتابیسمون برای یوزر ذخیره کنیمما از طریق سرورمون به این اندپوینت درخواست میفرستیم و اون درخواستو به کاربر میفرسته !بریم که انجامش بدیمشروعاول از همه یه پروژه با لاراول استارت میزنیمتوی فولدر پابلیک یا هرجایی که میشه یه فایل js درست کرد و بهش دست رسی داریم یه فایل درست میکنیم یعنی اینجوری مثلا https://www.site.com/file.jsاسمشو معمولا میذارن sw.js که همون service worker هست ، هر اسم دیگه ای هم میتونید بذاریدداخل این فایل اینو بنویسید :self.addEventListener(&#039;push&#039;, (e) =&gt; {
    let data = e.data.json();
    const options = {
        body: data.body,
        icon: &amp;quothttps://www.shopid.ir/shopid.png&amp;quot,
        data: {
            url: data.url
        }
    }
    e.waitUntil(self.registration.showNotification(data.title, options));
});
self.addEventListener(&#039;notificationclick&#039;, function(e) {
    e.waitUntil(clients.openWindow(e.notification.data.url))
});درست حدس زدید icon همون آیکونیه که کنار نوتیفیکشنتون قراره بیاد(بقیه داکیومنتاش اینجا هست )شما الان یه سرویس ورکر برای نوتیفیکیشن نوشتید !که وقتی کاربر روش کلیک میکنه میره به آدرسی که ما میخوایم !ولی هنوز یه سری کارای دیگه باید انجام بدیممرحله ای بعدی باید یه پکیج php روی لاراولمون نصب کنیم composer require minishlink/web-pushخب حالا ما نیاز داریم که دوتا کلید بگیریم یکی پابلیک و یکی پرایویتو اینکارو یک بار نیاز داریم بکینمپس هرجا که میتونید از پیکیج minishlink/web-push استفاده کنید اینکارو میتونید بکنیدبهترین جایی که میشه اینکارو کرد web.php هست همونجایی که route هارو تعریف میکنیمپس همونجا این کد بنویسید :use Minishlink\WebPush\VAPID;
dd(VAPID::createVapidKeys());یه بار سایتو ران کنید یه همچین چیزی میبینیدarray:2 [▼
&amp;quotpublicKey&amp;quot =&gt; &amp;quotBJjPvcv9QQu3SVxvjP_WpQNeuyhWKpGozAXkab2rl6VTaMv18R4avQy5dKcudeEbCbRNMR_kRkbPxV957fxXbP8&amp;quot
 &amp;quotprivateKey&amp;quot =&gt; &amp;quotoy468fjwBBSf_3OifCNsyHisxyf4FCgQBgM77Jd8uGs&amp;quot
]خب اینو یه جا ذخیره کنید و web.php به حالت اولش برگردونید یعنی اون dd(VAPID::createVapidKeys()) پاک کنیدحالا میریم و مدل و مایگریشن و کنترلمونو میسازیمphp artisan make:model push -mcrتوی فیلد های مایگریشن pushes یه فیلد تکست اضافه میکنیم$table-&gt;text(&#039;pushdata&#039;);و بعدش :php artisan migrateحالا میریم توی کنترلرمون (PushController.php) و متد های store و index  و send اینجوری میسازییمpublic function store(Request $request) {
    push::create([
            &amp;quotpushdata&amp;quot=&gt;$request-&gt;push
        ]);
}
    public function index()
    {
        return view(&amp;quotadmin&amp;quot,[&amp;quotpushes&amp;quot=&gt;push::latest()-&gt;limit(10)-&gt;get()]);
    }
    
        public function send(Request $req , push $push)
    {
        $webPush = new WebPush([
            &amp;quotVAPID&amp;quot =&gt; [
                &amp;quotsubject&amp;quot =&gt; &amp;quothttp://localhost&amp;quot,
                &amp;quotpublicKey&amp;quot =&gt; &#039;BJjPvcv9QQu3SVxvjP_WpQNeuyhWKpGozAXkab2rl6VTaMv18R4avQy5dKcudeEbCbRNMR_kRkbPxV957fxXbP8&#039;,
                &amp;quotprivateKey&amp;quot =&gt; &amp;quotoy468fjwBBSf_3OifCNsyHisxyf4FCgQBgM77Jd8uGs&amp;quot
            ]
        ]);
        $subscription = Subscription::create(json_decode($push-&gt;pushdata,true));
        $response = $webPush-&gt;sendOneNotification($subscription,json_encode([&amp;quottitle&amp;quot=&gt;&amp;quotnew notif&amp;quot,&amp;quotbody&amp;quot=&gt;$req-&gt;text,&amp;quoturl&amp;quot=&gt;$req-&gt;url]));
            if ($response-&gt;isSuccess()) {
                 echo &amp;quotok&amp;quot
            } else {
                $response-&gt;getReason();
            }
}    دقت کنید که privateKey و publicKey از همونی که قبلا گرفتیم و سیو کردیم باید استفاده کنیمتوی مدلمون (push.php) fillable برای فیلد pushdata تعریف میکنیم    protected $fillable = [
        &#039;pushdata&#039;
   ];    حالا روت هامونو تعریف میکنیم    api.php    Route::post(&#039;admin/savepush&#039;,&amp;quotApp\Http\Controllers\PushController@store&amp;quot);     web.php    Route::get(&#039;/admin&#039;, &amp;quotApp\Http\Controllers\PushController@index&amp;quot);
    Route::post(&#039;/admin/sendpush/{push}&#039;, &amp;quotApp\Http\Controllers\PushController@send&amp;quot); حالا ویوهامونو میسازیمویوو اصلی یا هرجایی که میخوایم از کاربر اجازه بگیریم یه همچین چیزی میشه (اینجا همون welcome.blade.php) :پارامتر applicationServerKey همون کلید عمومی هست که بالاتر گرفتیم و همینجا میذاریمش و مشکلی هم نداره که در سورسمون باشهاون قسمت XMLHttpRequest هم خیلی ساده نوشتم که مقداری که میگیریم بفرستیم به بک‌اندمون اگه توی پروژتون جور دیگه ای ارسال میکنید با همون روش ارسال کنید(فقط باید push به صورت جی‌سان شده ذخیره بشه)welcome.blade.php :&lt;!DOCTYPE html&gt;
&lt;html lang=&amp;quoten&amp;quot&gt;
&lt;head&gt;
    &lt;meta charset=&amp;quotUTF-8&amp;quot&gt;
    &lt;meta name=&amp;quotviewport&amp;quot content=&amp;quotwidth=device-width, initial-scale=1.0&amp;quot&gt;
    &lt;meta http-equiv=&amp;quotX-UA-Compatible&amp;quot content=&amp;quotie=edge&amp;quot&gt;
    &lt;title&gt;Document&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    
        navigator.serviceWorker.register(&#039;sw.js&#039;);
async function subscribe() {
    let sw = await navigator.serviceWorker.ready;
    let push = await sw.pushManager.subscribe({
        userVisibleOnly:true,
        applicationServerKey:&amp;quotBJjPvcv9QQu3SVxvjP_WpQNeuyhWKpGozAXkab2rl6VTaMv18R4avQy5dKcudeEbCbRNMR_kRkbPxV957fxXbP8&amp;quot
    });
      let xhr = new XMLHttpRequest()
 
xhr.open(&#039;POST&#039;, &#039;/api/admin/savepush&#039;, true)
xhr.setRequestHeader(&#039;Content-type&#039;, &#039;application/json; charset=UTF-8&#039;)
xhr.send(JSON.stringify({&amp;quotpush&amp;quot:JSON.stringify(push)}));
}
        function enableNotif() {
            Notification.requestPermission().then(function (permission) {
               if (Notification.permission === &#039;granted&#039;) {
 subscribe()
}
            });
        }
    
    &lt;button =&amp;quotenableNotif();&amp;quot style=&amp;quotfont-size: 5rem&amp;quot&gt;enableNotif&lt;/button&gt;
&lt;/body&gt;
&lt;/html&gt;    یه ویو دیگه هم میسازیم به اسم admin.blade.php که همونجاییه که میخوایم به کاربرامون نوتیفیکیشن ارسال کنیم میتونید به صورت api هم انجام بدید اینجا به ساده ترین حالت داریم اینجام میدیمadmin.blade.php :&lt;!DOCTYPE html&gt;
&lt;html lang=&amp;quoten&amp;quot&gt;
&lt;head&gt;
    &lt;meta charset=&amp;quotUTF-8&amp;quot&gt;
    &lt;meta name=&amp;quotviewport&amp;quot content=&amp;quotwidth=device-width, initial-scale=1.0&amp;quot&gt;
    &lt;meta http-equiv=&amp;quotX-UA-Compatible&amp;quot content=&amp;quotie=edge&amp;quot&gt;
    &lt;title&gt;Document&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    @foreach($pushes as $push)
    &lt;form method=&amp;quotpost&amp;quot action=&amp;quot/admin/sendpush/{{$push-&gt;id}}&amp;quot target=&amp;quot_blank&amp;quot&gt;
        push {{$push-&gt;id}}    
        &lt;input name=&amp;quottext&amp;quot type=&amp;quottext&amp;quot placeholder=&amp;quottext&amp;quot&gt;
        &lt;input name=&amp;quoturl&amp;quot type=&amp;quottext&amp;quot placeholder=&amp;quothttps://&amp;quot&gt;
        &lt;input type=&amp;quotsubmit&amp;quot value=&amp;quotsend&amp;quot/&gt;
        {{ csrf_field() }}
    &lt;/form&gt;
    @endforeach
&lt;/body&gt;
&lt;/html&gt; خب تموم شد الان فقط باید پروژمونو ران کنیم و هر کاربری بیاد توی سایتمون و enableNotif بزنه یه توکن و اندپوینت براش توی دیتابیس ما ذخیره میشه و اگه ما بریم توی قسمت ادمین (http://127.0.0.1:8000/admin) میتونیم براش نوتیفیکیشن ارسال کنیم !مقدار text همون متنه و url هم برای وقتیه که کاربر روی نوتیفیکشن کلیک میکنه و وارد همون url میشه</description>
                <category>shopid</category>
                <author>shopid</author>
                <pubDate>Thu, 18 Aug 2022 20:01:46 +0430</pubDate>
            </item>
                    <item>
                <title>پست ورقه ای یا اسلایدی با vue2 و vue3</title>
                <link>https://virgool.io/@shopid/vue-swipe-box-g3xmrxci3cxj</link>
                <description>توی خیلی از قسمت های سایت ها مخصوصا قسمت تصاویر خیلی وقتا نیازه که قسمت هایی به صورت ورقه ای (یعنی کاربر با انگشت به چپ یا راست ورق بزنه)  داشته باشیمدرست کردن همچین چیزی کار سختی نیست ولی یک سری ریزه کاری ها داره مثلا ریسپانسیو بودنش و سازگاری با ماوس و تاچ (لمسی) بودن دستگاه کاربر و خیلی موارد دیگهمشاهده نمونه ی زنده توی استکبلیتزhttps://stackblitz.com/edit/vue-xsw3r9آموزش این پست به صورت ویدیو توی آپاراتhttps://www.aparat.com/v/Q0Tt5آموزش این پست به صورت ویدیو توی یوتوب :https://www.youtube.com/watch?v=M-6HSVe4LcEانجام این کار توی vue با پکیچ swipBox خیلی راحته و تنها کاری که باید بکنید اینه که از طریق npm نصبش کنید و توی کامپوننت مد نظرتون هرجا خواستید اجرا کنیدبرای ویو نسخه ۳npm i @shopid/vue3-swipe-boxبرای نسخه ۲npm i @shopid/vue2-swipe-boxاول ایمپورتش میکنیمimport SwipeBox from &#039;@shopid/vue3-swipe-box&#039;;بعد توی تمپلیت اینجوری ازش استفاده میکنیم&lt;SwipeBox&gt;
&lt;div class=&amp;quotbox&amp;quot&gt;
   &lt;div&gt;item1&lt;/div&gt;
   &lt;div&gt;item2&lt;/div&gt; 
   &lt;div&gt;item3&lt;/div&gt;
   &lt;div&gt;item4&lt;/div&gt;
&lt;/div&gt;
&lt;/SwipeBox&gt;اول یه دونه SwipeBox میسازیم بعد یدونه المنت که اینجا div هست به عنوان باکس میسازیمبعد هر المنت دیگه ای توش باشه به عنوان یه ورق حساب میشه تمام !این پکیج از راست به چپ و چپ به راست پشتیبانی میکنه (rtl , ltr)با تاچ و ماوس کار میکنه و سرعت انیمیشن مگنتش هم قابل تغییرهمقدار این مقدار زمانی صدا زده میشه که کاربر ورق بزنه و اینکسشو برمیگردونهمقدار speedاین همون سرعت انیمیشن مگنته که وقتی ورق میزنه چقدر تند بچبسه که برحسب میلی ثانیه کار میکنهمتد های swipetoNext , swipetoPrevious , goToاینام که از اسمشون مشخصه برای دستی جلو عقب کردن و رفتن به اینکس اسفتاده میشهبرای استفاده ازینا کافیه یه ref بزنید به SwipeBox و اینجوری صداشون بزنید this.$refs.myswipe.swipetoNext()مثال کامل :&lt;template&gt;
  &lt;div id=&amp;quotapp&amp;quot&gt;
    &lt;SwipeBox ref=&amp;quotmyswipe&amp;quot @=&amp;quotmySwipeChanged&amp;quot speed=&amp;quot150&amp;quot&gt;
      &lt;div style=&amp;quotwidth: 200px; height: 200px; border: 1px solid black&amp;quot&gt;
        &lt;div v-for=&amp;quotimage in images&amp;quot :key=&amp;quotimage.id&amp;quot&gt;
        &lt;img :src=&amp;quotimage.url&amp;quot /&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/SwipeBox&gt;

    &lt;button @click=&amp;quotnext&amp;quot&gt;next&lt;/button&gt;&lt;br /&gt;
    &lt;button @click=&amp;quotprevious&amp;quot&gt;previous&lt;/button&gt;&lt;br /&gt;
    &lt;button @click=&amp;quotgoto2&amp;quot&gt;goto index #2&lt;/button&gt;&lt;br /&gt;
  &lt;/div&gt;
&lt;/template&gt;


import SwipeBox from &#039;@shopid/vue2-swipe-box&#039;;

export default {
  name: &#039;App&#039;,
  components: {
    SwipeBox,
  },
  data: () =&gt; {
    return {
      images: [
        { id: &#039;1&#039;, url: &#039;https://picsum.photos/200&#039; },
        { id: &#039;2&#039;, url: &#039;https://picsum.photos/200?2&#039; },
        { id: &#039;3&#039;, url: &#039;https://picsum.photos/200?3&#039; },
        { id: &#039;4&#039;, url: &#039;https://picsum.photos/200?4&#039; },
        { id: &#039;5&#039;, url: &#039;https://picsum.photos/200?5&#039; },
      ],
    };
  },

  methods: {
    mySwipeChanged: function (index) {
      console.log(&#039;index&#039; + index);
    },

    next: function (x) {
      this.$refs.myswipe.swipetoNext();
    },
    previous: function (x) {
      this.$refs.myswipe.swipetoPrevious();
    },
    goto2: function () {
      this.$refs.myswipe.goTo(2);
    },
  },
};
سورس توی گیتهاب :https://github.com/shopid-dev/vue3-swipe-boxhttps://github.com/shopid-dev/vue2-swipe-box</description>
                <category>shopid</category>
                <author>shopid</author>
                <pubDate>Tue, 02 Aug 2022 12:13:25 +0430</pubDate>
            </item>
                    <item>
                <title>ساخت add , edit , delete حرفه ای و به راحتی با vue.js</title>
                <link>https://virgool.io/@shopid/vue-editobj-obgpw1m3urwd</link>
                <description>توی خیلی از پروژه ها مخصوصا فروشگاه های آنلاین ما همیشه باید یک سری چیزارو وارد کنیم ، ویرایش کنیم یا حذف کنیممثل محصول ، دسته بندی ها و یا هر مورد دیگهخیلی وقتا بیشتر دولوپرا میان برای هر قسمت یک کامپوننت جدا تعریف میکنن و توی هر کامپوننت متد های post , patch , delete و ... با axios تعریف میکنن این روش کاملا درسته و مشکلی ندارهاما برای سریع تر شدن کار و کاهش خطا ما یه پکیج درست کردیم که این متد هارو توش داره و با همون axios هم کار میکنه و روش کارش هم خیلی سادست و مقادیرو توی لیست یا هرجا باشن براتون add , edit , delete میکنهنمونه زنده این آموزش توی استک‌بلیتز ببینید :https://stackblitz.com/edit/vue-kngugpآموزش این پست توی آپارات :https://www.aparat.com/v/V9cPNآموزش این پست توی یوتوب :https://www.youtube.com/watch?v=O8IABngqnNYمزیتمزیتی که این روش داره اینه که دیتا میتونه به صورت لیست یا تکی اضافه حذف و ویرایش بشه و خیلی کاربر پسند ترهشروعاز طریق npm نصبش کنید :npm i @shopid/vue-editobjکار کردن با این پکیچ هم خیلی سادست و تنها کاری که باید بکنید اینه که کامپوننتون رو از این کامپوننت extend کنیدمثلا میخوایم کامپوننت Product.vue یا همون محصول بسازیم :نکته : سایت ویرگول (همین سایت) روی تگ script حساسه و حذفش میکنه هرجا دیدین نوشتم تگ‌اسکریپت خودتون بکنیدش script ?&lt;template&gt;
&lt;input v-model=&amp;quotitem.title&amp;quot placeholder=&amp;quottitle..&amp;quot /&gt;
&lt;input v-model=&amp;quotitem.caption&amp;quot placeholder=&amp;quotcaption..&amp;quot /&gt;
&lt;/template&gt;

&lt;تگ‌اسکریپت&gt;
import editobj from &#039;@shopid/vue-editobj&#039;;
export default {
extends: editobj,
name: &#039;product&#039;,
apiHost: &#039;http://127.0.0.1:8000/api&#039;,
apiPath:&amp;quotproduct&amp;quot,
 apiConfig: {
  headers: {
   Authorization: &#039;Bearer &#039; + &#039;mytoken&#039;,
  },
  },
};
&lt;/تگ‌اسکریپت&gt;تنها کاری که باید بکنیم اینه که اول پکیج @shopid/vue-editobj ایمپورت کنیم و کامپوننتمون رو از اون extend کنیم (extends: editobj) مقدار apiPath هم product میذاریم  (این مقدار میچسبه به apiHost و آدرس api تشکیل میشه)مقدار apiHost هم آدرس api بک‌اندمونهمقدار apiConfig هم کانفیگ کردن مقادیری مثل هدر هستحالا مثلا اگه apiHost برابر با http://127.0.0.1:8000/api بذاریم آدرس api که خود کامپوننت اتوماتیک میسازه میشه :http://127.0.0.1:8000/api/productدوتا input هم توی تمپلیتمون داریم که اینجا عنوان و کپشن هستتموم شد ! کامپوننت محصول ساخته شد و الان میتونه مقدار جدید بگیره مقادیر قبلیو ویرایش کنه ذخیره کنه یا حذف کنهخب حالا چجوری ازش استفاده کنیم ؟مثال : یک کامپوننت میسازیم به اسم ProductList.vueاول از همه Product که ساختیم ایمپورت میکنیم که ازش استفاده کنیمبعد باید لیستی که میخوایم از بک‌اند بگیریم و با اون لیست Product بسازیماینجا توی دیتا خودمون یک سری محصول به صورت آبجکت میسازیماینجوری مثلاproducts: [
{ id: 1, title: &#039;prod1&#039;, caption: &#039;cap1&#039; },
{ id: 2, title: &#039;prod2&#039;, caption: &#039;cap2&#039; },
{ id: 3, title: &#039;prod3&#039;, caption: &#039;cap3&#039; },
]حالا باید توی تمپلیت لوپ کنیم و بسازیمش همین !اون پکیجه خودش برای هرکدوم ازینا متدای ذخیره و حذف و اینارو میسازهتازه اگه به این لیست  آیتم بدون id اضافه کنیم خودش تشخیص میده که این یه آیتم جدیده و اگه متد save اجرا بشه post میکنه اگه ببینه id داره patch میکنه به همین سادگیلوپ کردن توی ویو هم که خیلی سادست :با v-for  توی products لوپ میکنیم و :item رو مساوی هر آبجکت میذاریم یعنی :&lt;div v-for=&amp;quotproduct in products&amp;quot  class=&amp;quotprodItem&amp;quot :key=&amp;quotproduct.id&amp;quot &gt;
&lt;Product :item=&amp;quotproduct&amp;quot /&gt;
&lt;/div&gt;بعد دوتا دکمه میذاریم یکیش save یکیشم delete که وقتی روشون کلیک شد متد های save و delete همون آبجکت صدا زده بشهاین متد ها ورودی هم میگیرن که وقتی ذخیره شد یا حذف شد چه کاری انجام بدنproduct.save({ onSaved: onSaved });که onSaved هم یه متد توی ProductList هست که باید توی methods تعریفش کنید برای onDeleted هم به همین صورتکامل تر :&lt;div v-for=&amp;quotproduct in products&amp;quot  class=&amp;quotprodItem&amp;quot  :key=&amp;quotproduct.id&amp;quot &gt;
&lt;Product :item=&amp;quotproduct&amp;quot /&gt;
&lt;br /&gt;
&lt;button @click=&amp;quot&#039;product.save({ onSaved: onSaved });&amp;quot&gt;save&lt;/button&gt;
&lt;br /&gt;
&lt;button v-if=&amp;quotproduct.id&amp;quot @click=&amp;quotproduct.delete({ onDeleted: onDeleted })&amp;quot&gt;
delete
&lt;/button&gt;
&lt;/div&gt;و متد هاmethods: {
onDeleted: function (item, resp) {
this.products = this.products.filter((loopItem) =&gt; loopItem !== item);
console.log(item);
console.log(resp);
this.status = resp.data.message;
},
onSaved: function (item, resp) {
console.log(item);
console.log(resp);
this.status = resp.data.message;
},
}برای اضافه کردن هم کافیه یه دکمه بسازید و به products یه آبجکت جدید و خالی پوش کنید !&lt;button @click=&amp;quotproducts.push({})&amp;quot&gt;addnew&lt;/button&gt;نسخه کامل ProductList.vue :&lt;template&gt;
&lt;div&gt;{{ status }}&lt;/div&gt;
&lt;div class=&amp;quotprodItem&amp;quot v-for=&amp;quotproduct in products&amp;quot :key=&amp;quotproduct.id&amp;quot&gt;
&lt;Product :item=&amp;quotproduct&amp;quot /&gt;
&lt;br /&gt;
&lt;button @click=&amp;quotstatus = &#039;saving ...&#039;;product.save({ onSaved: onSaved });&amp;quot&gt;
save
&lt;/button&gt;
&lt;br /&gt;
&lt;button v-if=&amp;quotproduct.id&amp;quot @click=&amp;quotstatus = &#039;deleting ...&#039;;product.delete({ onDeleted: onDeleted })&amp;quot&gt;
delete&lt;/button&gt;
&lt;/div&gt;
&lt;button @click=&amp;quotproducts.push({})&amp;quot&gt;addnew&lt;/button&gt;
&lt;/template&gt;
&lt;تگ‌اسکریپت&gt;
import Product from &#039;./Product.vue&#039;;
export default {
name: &#039;ProductList&#039;,
components: {
Product,
},
data: () =&gt; {
return {
products: [
{ id: 1, title: &#039;prod1&#039;, caption: &#039;cap1&#039; },
{ id: 2, title: &#039;prod2&#039;, caption: &#039;cap2&#039; },
{ id: 3, title: &#039;prod3&#039;, caption: &#039;cap3&#039; },
],
status: &#039;idle&#039;,
};
},
methods: {
onDeleted: function (item, resp) {
this.products = this.products.filter((loopItem) =&gt; loopItem !== item);
console.log(item);
console.log(resp);
this.status = resp.data.message;
},
onSaved: function (item, resp) {
console.log(item);
console.log(resp);
this.status = resp.data.message;
},
},
};

&lt;/تگ‌اسکریپت&gt;
&lt;style&gt;
.prodItem {
border: 1px solid black;
margin: 0.5rem;
padding: 0.5rem;
}
&lt;/style&gt;</description>
                <category>shopid</category>
                <author>shopid</author>
                <pubDate>Mon, 25 Jul 2022 14:23:46 +0430</pubDate>
            </item>
                    <item>
                <title>درگاه پرداخت آیدی‌پی (idpay) برای لاراول</title>
                <link>https://virgool.io/@shopid/%D8%AF%D8%B1%DA%AF%D8%A7%D9%87-%D9%BE%D8%B1%D8%AF%D8%A7%D8%AE%D8%AA-%D8%A2%DB%8C%D8%AF%DB%8C-%D9%BE%DB%8C-idpay-%D8%A8%D8%B1%D8%A7%DB%8C-%D9%84%D8%A7%D8%B1%D8%A7%D9%88%D9%84-nmdekqgqmtad</link>
                <description>این آموزش فقط برای لاراول نیست و شما با هر فریم ورک php یا بدون فریم ورک میتونید از این پکیچ استفاده کنیدبرای فهمیدن این آموزش شما باید آشنایی نسبی با لاراول یا php و شئ گرایی داشته باشید و درواقع این برای مرحله ای هست که کاربر سفارش ثبت کرده و فاکتور صادر شده حالا میخواید به درگاه پرداخت متصل بشیدبرای ایجاد قابلیت درگاه پرداخت آیدی‌پی توی سایت یا اپ شما اول نیاز دارید که توی سایت آیدی‌پی اکانت داشته باشید و سایت یا اپلیکیشنتونو ثبت کنید و تایید بشیدیا توی حالت sandbox بدون داشتن اکانت کدتون رو بنویسید و بعدش درگاه بگیریدما اینجا تصور میکنیم که شما همه ی مراحلو انجام دادین و API KEY هم گرفتینو API KEY توی آیدی‌پی یه همچین چیزیه 6a7f99eb-7c20-4412-a972-6dfb7cd253a4که توی سایت آیدی‌پی توی اکانتتون هست و ازونجا باید کپیش کنیدخب میریم توی پروژه ی لاراولموناول از همه پکیچ زیر باید نصب کنید , توی کامند لاین از طریق کامپوزر این دستور اجرا کنید :composer require shopid/idpayسورس : https://github.com/shopid-dev/idpay-phpاین پکیج خیلی سبکه و راحت نصب میشهتمام مقادیر بازگشتی و خطا ها به صورت json هستخب حالا باید اینو توی کنترلرمون استفاده کنیمروش استفاده هم خیلی راحته اول باید ایمپورتش کنیمuse shopid\idPay;بعد توی متد مورد نظرمون یه شئ ازش ایجاد میکنیمایجاد شئ :$idpay = new idPay([&amp;quotapiKey&amp;quot =&gt; &amp;quot6a7f99eb-7c20-4412-a972-6dfb7cd253a4&amp;quot, &amp;quotsandbox&amp;quot =&gt; true]);پارامتر apiKey که همونه که بالا توضیح دادیمپارامتر sandbox حالت تست هست که اگه true باشه شما میتونید بدون داشتن درگاه هم کدتون رو تست کنیدایجاد درخواست پرداخت :try {
$req = $idpay-&gt;apiRequest([

	    &amp;quotorder_id&amp;quot =&gt; &amp;quot1123&amp;quot,
            &amp;quotamount&amp;quot =&gt; 2000,
            &amp;quotcallback&amp;quot =&gt; &amp;quothttps://www.mywebsite.com/&amp;quot,
            &amp;quotname&amp;quot =&gt; &amp;quotshopid&amp;quot,
            &amp;quotphone&amp;quot =&gt; &amp;quot09120000000&amp;quot,
            &amp;quotmail&amp;quot =&gt; &amp;quotaa@gmail.com&amp;quot,
            &amp;quotdesc&amp;quot =&gt; &amp;quotorder 1123&amp;quot,
]);

print_r(json_decode($req));
} catch (Exception $error) {
      print_r(json_decode($error-&gt;getMessage()));
}پارامتر order_id همون شماره فاکتور یا سفارشه توی سایت شماپارامتر amount  مبلغ سفارشه به ریالپارامتر callback  آدرسی هست که کاربر بعد از پرداخت چه موفق چه ناموفق به سایت یا اپ برمیگرده و باید وضیعت پرداخت مشخص بشهپارامتر های name و phone و mail هم که مشخصه باید از یوزر بگیریدپارامتر desc توضیح تراکنشتموم شد !اگه خطایی توی روند درخواست پیش نیاد به شما یک url برگشت داده میشه که کاربر باید به اون هدایت کنید حالا با ‌‌‌هدر یا اگه برنامتون فقط api هست اونو به فرانت بفرستید و ازش استفاده کنید همچنین مقدار id هم جداگانه دارید که توی دیتابیس ذخیره کنید و بعد از بازگشت برای صحت پرداخت ازش استفاد کنیدبررسی صحت پرداخت و تایید تراکنش :خب حالا کاربر بعد از پرداخت موفق یا نا موفق دوباره به سایت شما برمیگرده و شما باید بررسی کنید که پرداخت انجام شده یا نه و عملیات مربوط به سفارش انجام بدین و همچنین تراکنشو تایید کنیدچیزی که به شما برمیگرده json هست که داکیومنت مقادیر و توضیحاتشون اینجا هستhttps://idpay.ir/web-service/v1.1/try {
    
    $verify = $idpay-&gt;verify(
        [
	        &amp;quotorder_id&amp;quot =&gt; &amp;quot1123&amp;quot,        
                &amp;quotid&amp;quot =&gt; &amp;quot350130d9fc8b5b569fecb600538f7e72&amp;quot,
        ]
    );
    var_dump(json_decode($verify));
} catch (Exception $error) {
          print_r(json_decode($error-&gt;getMessage()));
}پارامتر id همون id درخواست پرداخته که آیدی‌پی میده و شما باید از دیتابیس فراخوانی کنید (قبلا توی قسمت ایجاد درخواست ذخیرش کردید)اینجا هم اگه خطایی دریافت نکنید یعنی پرداخت انجام شده و  تایید شده و تمامکد های خطا ها هم اینجا میتونید ببنیدhttps://idpay.ir/web-service/v1.1/#ad39f18522همچنین کد خطای 9999 مربوط به خطای شبکه هست</description>
                <category>shopid</category>
                <author>shopid</author>
                <pubDate>Fri, 15 Jul 2022 12:51:01 +0430</pubDate>
            </item>
                    <item>
                <title>درگاه پرداخت زرین پال برای لاراول</title>
                <link>https://virgool.io/@shopid/zarinpal-agkiqa7tplra</link>
                <description>این آموزش فقط برای لاراول نیست و شما با هر فریم ورک php یا بدون فریم ورک میتونید از این پکیچ استفاده کنیدبرای فهمیدن این آموزش شما باید آشنایی نسبی با لاراول یا php و شئ گرایی داشته باشید و درواقع این برای مرحله ای هست که کاربر سفارش ثبت کرده و فاکتور صادر شده حالا میخواید به درگاه پرداخت متصل بشیدنسخه آپارات این آموزش در اینجا مشاهده کنیدنسخه یوتوب این آموزش در اینجا مشاهده کنیدhttps://www.aparat.com/v/8pHjthttps://www.youtube.com/watch?v=5sWpvaOKEhwشروع:برای ایجاد قابلیت درگاه پرداخت زرین پال توی سایت یا اپ شما اول نیاز دارید که توی سایت زرین پال اکانت داشته باشید و سایت یا اپلیکیشنتونو ثبت کنید و تایید بشیدما اینجا تصور میکنیم که شما همه ی مراحلو انجام دادین و کد درگاه هم گرفتینکد درگاه توی زرین پال یه همچین چیزیه  xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxکه توی سایت زرین پال توی اکانتتون هست و ازونجا باید کپیش کنیدخب میریم توی پروژه ی لاراولموناول از همه پکیچ زیر باید نصب کنید , توی کامند لاین از طریق کامپوزر این دستور اجرا کنید :composer require shopid/zarinpalسورس : https://github.com/shopid-dev/zarinpal-phpاین پکیج خیلی سبکه و راحت نصب میشه و تمام مقادیر بازگشتی و خطا ها به صورت json هستخب حالا باید اینو توی کنترلرمون استفاده کنیمروش استفاده هم خیلی راحته اول باید ایمپورتش کنیمuse shopid\zarinPal;بعد توی متد مورد نظرمون یه شئ ازش ایجاد میکنیم ایجاد شئ :$zarinpal = new zarinPal([
    &amp;quotmerchantId&amp;quot =&gt; &amp;quotxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx&amp;quot,
]);پارامتر merchantId همون کد درگاه هست که از زرین پال میگیریدخب حالا با این شئ که ایجاد کردیم میتونیم درخواست پرداخت ارسال کنیم و یا پرداخت وریفای کنیمایجاد درخواست پرداخت :        try  {           
              $request = $zarinpal-&gt;apiRequest(
                  [ 
                  &amp;quotcallbackurl&amp;quot =&gt; &amp;quothttps://www.mywebsice.com/zarinpalverify/pay,ment-1234&amp;quot,
                   &amp;quotamount&amp;quot =&gt; &amp;quot1000&amp;quot, 
                   &amp;quotdescription&amp;quot =&gt; &amp;quotpayment #999&amp;quot, 
                   &amp;quotemail&amp;quot =&gt; &amp;quotuser @gmial.com&amp;quot,
                   &amp;quotmobile&amp;quot =&gt; &amp;quot09120000000&amp;quot, 
                ]
             );   
              var_dump(json_decode($request));  
          } catch (Exception $error) {  
          var_dump(json_decode($error-&gt;getMessage())); 
       }پارامتر callbackurl همون آدرسی هست که کاربر بعد از  پرداخت چه موفق چه ناموفق به سایت یا اپ برمیگرده و باید وضیعت پرداخت مشخص بشهپارامتر amount همون مبلغ هست (به ریال)پارامتر description توضیحات هست که مثلا میشه پرداخت سفارش شماره فلان ..ایمیل و موبایل هم ایمیل و شماره ی مشتری هست (اینا آپشنال هست و میتونید مال خودتونم وارد کنید)تموم شد !اگه خطایی توی روند درخواست پیش نیاد به شما یک url برگشت داده میشه که کاربر باید به اون هدایت کنید حالا با ‌‌‌هدر یا اگه برنامتون فقط api هست اونو به فرانت بفرستید و ازش استفاده کنید همچنین مقدار authority هم جداگانه دارید که توی دیتابیس ذخیره کنید و بعد از بازگشت برای صحت پرداخت ازش استفاد کنید (البته خود زرین پال هم بعد از بازگشت به سایت شما این مقدار به صورت GET براتون ارسال میکنه و میتونید اونجا هم ازش استفاده کنید)بررسی صحت پرداخت :خب حالا کاربر بعد از پرداخت موفق یا نا موفق دوباره به سایت شما برمیگرده و شما باید بررسی کنید که پرداخت انجام شده یا نه و عملیات مربوط به سفارش انجام بدینtry {
    
    $verify = $zarinpal-&gt;verify(
        [
            &amp;quotauthority&amp;quot =&gt; &amp;quotA00000000000000000000000000000000000&amp;quot,
            &amp;quotamount&amp;quot =&gt; &amp;quot1000&amp;quot
        ]
    );
    var_dump(json_decode($verify));
} catch (Exception $error) {
    var_dump(json_decode($error-&gt;getMessage()));
}
پارامتر authority همون کد درخواست پرداخته که زرین پال براتون برمیگردونه خودتون هم میتونید از دیتابیس فراخوانی کنیدقیمت هم که همون مبلغ پرداختی هستاینجا هم اگه خطایی دریافت نکنید یعنی پرداخت انجام شده و تمامکد های خطا ها هم اینجا میتونید ببنیدhttps://docs.zarinpal.com/paymentGateway/error.htmlهمچنین کد خطای 9999 مربوط به خطای شبکه هست</description>
                <category>shopid</category>
                <author>shopid</author>
                <pubDate>Sun, 03 Apr 2022 10:42:19 +0430</pubDate>
            </item>
            </channel>
</rss>